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 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
188 cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
189 if (cache_info == (CacheInfo *) NULL)
190 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
191 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
192 cache_info->type=UndefinedCache;
193 cache_info->mode=IOMode;
194 cache_info->colorspace=RGBColorspace;
195 cache_info->file=(-1);
196 cache_info->id=GetMagickThreadId();
197 cache_info->number_threads=number_threads;
198 if (number_threads == 0)
199 cache_info->number_threads=GetOpenMPMaximumThreads();
200 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
201 if (cache_info->nexus_info == (NexusInfo **) NULL)
202 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
203 cache_info->semaphore=AllocateSemaphoreInfo();
204 cache_info->reference_count=1;
205 cache_info->disk_semaphore=AllocateSemaphoreInfo();
206 cache_info->debug=IsEventLogging();
207 cache_info->signature=MagickSignature;
208 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 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
257 nexus_info=(NexusInfo **) AcquireAlignedMemory(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 MagickPrivate 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 MagickPrivate 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 MagickPrivate 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 *) AcquireAlignedMemory(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->number_channels,
949 clone_info->number_channels)*sizeof(Quantum),MagickMax(
950 cache_info->metacontent_extent,clone_info->metacontent_extent));
951 blob=(unsigned char *) AcquireAlignedMemory(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 ((cache_info->type == DiskCache) &&
976 (strcmp(cache_info->cache_filename,clone_info->cache_filename) == 0))
978 (void) ClosePixelCacheOnDisk(clone_info);
979 *clone_info->cache_filename='\0';
981 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
983 if (cache_info->type == DiskCache)
984 (void) ClosePixelCacheOnDisk(cache_info);
985 blob=(unsigned char *) RelinquishMagickMemory(blob);
986 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
987 clone_info->cache_filename);
990 clone_offset=clone_info->offset;
993 Clone pixel channels.
996 for (y=0; y < (ssize_t) cache_info->rows; y++)
998 for (x=0; x < (ssize_t) cache_info->columns; x++)
1001 Read a set of pixel channels.
1003 length=cache_info->number_channels*sizeof(Quantum);
1004 if (cache_info->type != DiskCache)
1005 (void) memcpy(blob,(unsigned char *) cache_info->pixels+cache_offset,
1009 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1010 if ((MagickSizeType) count != length)
1016 cache_offset+=length;
1017 if ((y < (ssize_t) clone_info->rows) &&
1018 (x < (ssize_t) clone_info->columns))
1021 Write a set of pixel channels.
1023 length=clone_info->number_channels*sizeof(Quantum);
1024 if (clone_info->type != DiskCache)
1025 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1029 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1030 if ((MagickSizeType) count != length)
1036 clone_offset+=length;
1039 length=clone_info->number_channels*sizeof(Quantum);
1040 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1041 for ( ; x < (ssize_t) clone_info->columns; x++)
1044 Set remaining columns with transparent pixel channels.
1046 if (clone_info->type != DiskCache)
1047 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1051 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1052 if ((MagickSizeType) count != length)
1058 clone_offset+=length;
1061 length=clone_info->number_channels*sizeof(Quantum);
1062 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1063 for ( ; y < (ssize_t) clone_info->rows; y++)
1066 Set remaining rows with transparent pixels.
1068 for (x=0; x < (ssize_t) clone_info->columns; x++)
1070 if (clone_info->type != DiskCache)
1071 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1075 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1076 if ((MagickSizeType) count != length)
1082 clone_offset+=length;
1085 if ((cache_info->metacontent_extent != 0) &&
1086 (clone_info->metacontent_extent != 0))
1091 for (y=0; y < (ssize_t) cache_info->rows; y++)
1093 for (x=0; x < (ssize_t) cache_info->columns; x++)
1096 Read a set of metacontent.
1098 length=cache_info->metacontent_extent;
1099 if (cache_info->type != DiskCache)
1100 (void) memcpy(blob,(unsigned char *) cache_info->pixels+
1101 cache_offset,length);
1104 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1105 if ((MagickSizeType) count != length)
1111 cache_offset+=length;
1112 if ((y < (ssize_t) clone_info->rows) &&
1113 (x < (ssize_t) clone_info->columns))
1116 Write a set of metacontent.
1118 length=clone_info->metacontent_extent;
1119 if (clone_info->type != DiskCache)
1120 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1124 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1126 if ((MagickSizeType) count != length)
1132 clone_offset+=length;
1135 length=clone_info->metacontent_extent;
1136 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1137 for ( ; x < (ssize_t) clone_info->columns; x++)
1140 Set remaining columns with metacontent.
1142 if (clone_info->type != DiskCache)
1143 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1147 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1148 if ((MagickSizeType) count != length)
1154 clone_offset+=length;
1157 length=clone_info->metacontent_extent;
1158 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1159 for ( ; y < (ssize_t) clone_info->rows; y++)
1162 Set remaining rows with metacontent.
1164 for (x=0; x < (ssize_t) clone_info->columns; x++)
1166 if (clone_info->type != DiskCache)
1167 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1171 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1172 if ((MagickSizeType) count != length)
1178 clone_offset+=length;
1182 if (clone_info->type == DiskCache)
1183 (void) ClosePixelCacheOnDisk(clone_info);
1184 if (cache_info->type == DiskCache)
1185 (void) ClosePixelCacheOnDisk(cache_info);
1186 blob=(unsigned char *) RelinquishMagickMemory(blob);
1190 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1191 CacheInfo *cache_info,ExceptionInfo *exception)
1193 if (cache_info->type == PingCache)
1195 if ((cache_info->columns == clone_info->columns) &&
1196 (cache_info->rows == clone_info->rows) &&
1197 (cache_info->number_channels == clone_info->number_channels) &&
1198 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1199 return(OptimizedPixelCacheClone(clone_info,cache_info,exception));
1200 return(UnoptimizedPixelCacheClone(clone_info,cache_info,exception));
1204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1208 + C l o n e P i x e l C a c h e M e t h o d s %
1212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1214 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1217 % The format of the ClonePixelCacheMethods() method is:
1219 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1221 % A description of each parameter follows:
1223 % o clone: Specifies a pointer to a Cache structure.
1225 % o cache: the pixel cache.
1228 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
1234 assert(clone != (Cache) NULL);
1235 source_info=(CacheInfo *) clone;
1236 assert(source_info->signature == MagickSignature);
1237 if (source_info->debug != MagickFalse)
1238 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1239 source_info->filename);
1240 assert(cache != (Cache) NULL);
1241 cache_info=(CacheInfo *) cache;
1242 assert(cache_info->signature == MagickSignature);
1243 source_info->methods=cache_info->methods;
1247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1251 + D e s t r o y I m a g e P i x e l C a c h e %
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1257 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1259 % The format of the DestroyImagePixelCache() method is:
1261 % void DestroyImagePixelCache(Image *image)
1263 % A description of each parameter follows:
1265 % o image: the image.
1268 static void DestroyImagePixelCache(Image *image)
1270 assert(image != (Image *) NULL);
1271 assert(image->signature == MagickSignature);
1272 if (image->debug != MagickFalse)
1273 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1274 if (image->cache == (void *) NULL)
1276 image->cache=DestroyPixelCache(image->cache);
1280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1284 + D e s t r o y I m a g e P i x e l s %
1288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1290 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1292 % The format of the DestroyImagePixels() method is:
1294 % void DestroyImagePixels(Image *image)
1296 % A description of each parameter follows:
1298 % o image: the image.
1301 MagickExport void DestroyImagePixels(Image *image)
1306 assert(image != (const Image *) NULL);
1307 assert(image->signature == MagickSignature);
1308 if (image->debug != MagickFalse)
1309 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1310 assert(image->cache != (Cache) NULL);
1311 cache_info=(CacheInfo *) image->cache;
1312 assert(cache_info->signature == MagickSignature);
1313 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1315 cache_info->methods.destroy_pixel_handler(image);
1318 image->cache=DestroyPixelCache(image->cache);
1322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326 + D e s t r o y P i x e l C a c h e %
1330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1332 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1334 % The format of the DestroyPixelCache() method is:
1336 % Cache DestroyPixelCache(Cache cache)
1338 % A description of each parameter follows:
1340 % o cache: the pixel cache.
1344 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1346 switch (cache_info->type)
1350 if (cache_info->mapped == MagickFalse)
1351 cache_info->pixels=(Quantum *) RelinquishMagickMemory(
1352 cache_info->pixels);
1354 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1355 (size_t) cache_info->length);
1356 RelinquishMagickResource(MemoryResource,cache_info->length);
1361 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1362 cache_info->length);
1363 RelinquishMagickResource(MapResource,cache_info->length);
1367 if (cache_info->file != -1)
1368 (void) ClosePixelCacheOnDisk(cache_info);
1369 RelinquishMagickResource(DiskResource,cache_info->length);
1375 cache_info->type=UndefinedCache;
1376 cache_info->mapped=MagickFalse;
1377 cache_info->metacontent=(void *) NULL;
1380 MagickPrivate Cache DestroyPixelCache(Cache cache)
1385 assert(cache != (Cache) NULL);
1386 cache_info=(CacheInfo *) cache;
1387 assert(cache_info->signature == MagickSignature);
1388 if (cache_info->debug != MagickFalse)
1389 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1390 cache_info->filename);
1391 LockSemaphoreInfo(cache_info->semaphore);
1392 cache_info->reference_count--;
1393 if (cache_info->reference_count != 0)
1395 UnlockSemaphoreInfo(cache_info->semaphore);
1396 return((Cache) NULL);
1398 UnlockSemaphoreInfo(cache_info->semaphore);
1399 if (cache_resources != (SplayTreeInfo *) NULL)
1400 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1401 if (cache_info->debug != MagickFalse)
1404 message[MaxTextExtent];
1406 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1407 cache_info->filename);
1408 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1410 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1411 (cache_info->type != DiskCache)))
1412 RelinquishPixelCachePixels(cache_info);
1415 RelinquishPixelCachePixels(cache_info);
1416 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1418 *cache_info->cache_filename='\0';
1419 if (cache_info->nexus_info != (NexusInfo **) NULL)
1420 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1421 cache_info->number_threads);
1422 if (cache_info->random_info != (RandomInfo *) NULL)
1423 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1424 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1425 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1426 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1427 DestroySemaphoreInfo(&cache_info->semaphore);
1428 cache_info->signature=(~MagickSignature);
1429 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439 + D e s t r o y P i x e l C a c h e N e x u s %
1443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1445 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1447 % The format of the DestroyPixelCacheNexus() method is:
1449 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1450 % const size_t number_threads)
1452 % A description of each parameter follows:
1454 % o nexus_info: the nexus to destroy.
1456 % o number_threads: the number of nexus threads.
1460 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1462 if (nexus_info->mapped == MagickFalse)
1463 (void) RelinquishMagickMemory(nexus_info->cache);
1465 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1466 nexus_info->cache=(Quantum *) NULL;
1467 nexus_info->pixels=(Quantum *) NULL;
1468 nexus_info->metacontent=(void *) NULL;
1469 nexus_info->length=0;
1470 nexus_info->mapped=MagickFalse;
1473 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1474 const size_t number_threads)
1479 assert(nexus_info != (NexusInfo **) NULL);
1480 for (i=0; i < (ssize_t) number_threads; i++)
1482 if (nexus_info[i]->cache != (Quantum *) NULL)
1483 RelinquishCacheNexusPixels(nexus_info[i]);
1484 nexus_info[i]->signature=(~MagickSignature);
1485 nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]);
1487 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
1492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496 % G e t A u t h e n t i c M e t a c o n t e n t %
1500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1503 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1504 % returned if the associated pixels are not available.
1506 % The format of the GetAuthenticMetacontent() method is:
1508 % void *GetAuthenticMetacontent(const Image *image)
1510 % A description of each parameter follows:
1512 % o image: the image.
1515 MagickExport void *GetAuthenticMetacontent(const Image *image)
1521 id = GetOpenMPThreadId();
1526 assert(image != (const Image *) NULL);
1527 assert(image->signature == MagickSignature);
1528 assert(image->cache != (Cache) NULL);
1529 cache_info=(CacheInfo *) image->cache;
1530 assert(cache_info->signature == MagickSignature);
1531 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1532 (GetAuthenticMetacontentFromHandler) NULL)
1534 metacontent=cache_info->methods.
1535 get_authentic_metacontent_from_handler(image);
1536 return(metacontent);
1538 assert(id < (int) cache_info->number_threads);
1539 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1540 cache_info->nexus_info[id]);
1541 return(metacontent);
1545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1549 + 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 %
1553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1555 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1556 % with the last call to QueueAuthenticPixelsCache() or
1557 % GetAuthenticPixelsCache().
1559 % The format of the GetAuthenticMetacontentFromCache() method is:
1561 % void *GetAuthenticMetacontentFromCache(const Image *image)
1563 % A description of each parameter follows:
1565 % o image: the image.
1568 static void *GetAuthenticMetacontentFromCache(const Image *image)
1574 id = GetOpenMPThreadId();
1579 assert(image != (const Image *) NULL);
1580 assert(image->signature == MagickSignature);
1581 assert(image->cache != (Cache) NULL);
1582 cache_info=(CacheInfo *) image->cache;
1583 assert(cache_info->signature == MagickSignature);
1584 assert(id < (int) cache_info->number_threads);
1585 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1586 cache_info->nexus_info[id]);
1587 return(metacontent);
1591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1595 + 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 %
1599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1601 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1602 % disk pixel cache as defined by the geometry parameters. A pointer to the
1603 % pixels is returned if the pixels are transferred, otherwise a NULL is
1606 % The format of the GetAuthenticPixelCacheNexus() method is:
1608 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1609 % const ssize_t y,const size_t columns,const size_t rows,
1610 % NexusInfo *nexus_info,ExceptionInfo *exception)
1612 % A description of each parameter follows:
1614 % o image: the image.
1616 % o x,y,columns,rows: These values define the perimeter of a region of
1619 % o nexus_info: the cache nexus to return.
1621 % o exception: return any errors or warnings in this structure.
1625 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info,
1626 NexusInfo *nexus_info)
1634 if (cache_info->type == PingCache)
1636 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1637 nexus_info->region.x;
1638 status=nexus_info->pixels == (cache_info->pixels+offset*
1639 cache_info->number_channels) ? MagickTrue : MagickFalse;
1643 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
1644 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1645 NexusInfo *nexus_info,ExceptionInfo *exception)
1654 Transfer pixels from the cache.
1656 assert(image != (Image *) NULL);
1657 assert(image->signature == MagickSignature);
1658 q=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1659 if (q == (Quantum *) NULL)
1660 return((Quantum *) NULL);
1661 cache_info=(CacheInfo *) image->cache;
1662 assert(cache_info->signature == MagickSignature);
1663 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1665 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1666 return((Quantum *) NULL);
1667 if (cache_info->metacontent_extent != 0)
1668 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1669 return((Quantum *) NULL);
1674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678 + 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 %
1682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1684 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1685 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1687 % The format of the GetAuthenticPixelsFromCache() method is:
1689 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1691 % A description of each parameter follows:
1693 % o image: the image.
1696 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1702 id = GetOpenMPThreadId();
1704 assert(image != (const Image *) NULL);
1705 assert(image->signature == MagickSignature);
1706 assert(image->cache != (Cache) NULL);
1707 cache_info=(CacheInfo *) image->cache;
1708 assert(cache_info->signature == MagickSignature);
1709 assert(id < (int) cache_info->number_threads);
1710 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718 % G e t A u t h e n t i c P i x e l Q u e u e %
1722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724 % GetAuthenticPixelQueue() returns the authentic pixels associated
1725 % corresponding with the last call to QueueAuthenticPixels() or
1726 % GetAuthenticPixels().
1728 % The format of the GetAuthenticPixelQueue() method is:
1730 % Quantum *GetAuthenticPixelQueue(const Image image)
1732 % A description of each parameter follows:
1734 % o image: the image.
1737 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1743 id = GetOpenMPThreadId();
1745 assert(image != (const Image *) NULL);
1746 assert(image->signature == MagickSignature);
1747 assert(image->cache != (Cache) NULL);
1748 cache_info=(CacheInfo *) image->cache;
1749 assert(cache_info->signature == MagickSignature);
1750 if (cache_info->methods.get_authentic_pixels_from_handler !=
1751 (GetAuthenticPixelsFromHandler) NULL)
1752 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1753 assert(id < (int) cache_info->number_threads);
1754 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1762 % G e t A u t h e n t i c P i x e l s %
1765 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1767 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1768 % region is successfully accessed, a pointer to a Quantum array
1769 % representing the region is returned, otherwise NULL is returned.
1771 % The returned pointer may point to a temporary working copy of the pixels
1772 % or it may point to the original pixels in memory. Performance is maximized
1773 % if the selected region is part of one row, or one or more full rows, since
1774 % then there is opportunity to access the pixels in-place (without a copy)
1775 % if the image is in memory, or in a memory-mapped file. The returned pointer
1776 % must *never* be deallocated by the user.
1778 % Pixels accessed via the returned pointer represent a simple array of type
1779 % Quantum. If the image has corresponding metacontent,call
1780 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1781 % meta-content corresponding to the region. Once the Quantum array has
1782 % been updated, the changes must be saved back to the underlying image using
1783 % SyncAuthenticPixels() or they may be lost.
1785 % The format of the GetAuthenticPixels() method is:
1787 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1788 % const ssize_t y,const size_t columns,const size_t rows,
1789 % ExceptionInfo *exception)
1791 % A description of each parameter follows:
1793 % o image: the image.
1795 % o x,y,columns,rows: These values define the perimeter of a region of
1798 % o exception: return any errors or warnings in this structure.
1801 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1802 const ssize_t y,const size_t columns,const size_t rows,
1803 ExceptionInfo *exception)
1809 id = GetOpenMPThreadId();
1814 assert(image != (Image *) NULL);
1815 assert(image->signature == MagickSignature);
1816 assert(image->cache != (Cache) NULL);
1817 cache_info=(CacheInfo *) image->cache;
1818 assert(cache_info->signature == MagickSignature);
1819 if (cache_info->methods.get_authentic_pixels_handler !=
1820 (GetAuthenticPixelsHandler) NULL)
1822 q=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,rows,
1826 assert(id < (int) cache_info->number_threads);
1827 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1828 cache_info->nexus_info[id],exception);
1833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1837 + G e t A u t h e n t i c P i x e l s C a c h e %
1841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1843 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1844 % as defined by the geometry parameters. A pointer to the pixels is returned
1845 % if the pixels are transferred, otherwise a NULL is returned.
1847 % The format of the GetAuthenticPixelsCache() method is:
1849 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1850 % const ssize_t y,const size_t columns,const size_t rows,
1851 % ExceptionInfo *exception)
1853 % A description of each parameter follows:
1855 % o image: the image.
1857 % o x,y,columns,rows: These values define the perimeter of a region of
1860 % o exception: return any errors or warnings in this structure.
1863 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1864 const ssize_t y,const size_t columns,const size_t rows,
1865 ExceptionInfo *exception)
1871 id = GetOpenMPThreadId();
1876 assert(image != (const Image *) NULL);
1877 assert(image->signature == MagickSignature);
1878 assert(image->cache != (Cache) NULL);
1879 cache_info=(CacheInfo *) image->cache;
1880 if (cache_info == (Cache) NULL)
1881 return((Quantum *) NULL);
1882 assert(cache_info->signature == MagickSignature);
1883 assert(id < (int) cache_info->number_threads);
1884 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1885 cache_info->nexus_info[id],exception);
1890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1894 + G e t I m a g e E x t e n t %
1898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1900 % GetImageExtent() returns the extent of the pixels associated corresponding
1901 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1903 % The format of the GetImageExtent() method is:
1905 % MagickSizeType GetImageExtent(const Image *image)
1907 % A description of each parameter follows:
1909 % o image: the image.
1912 MagickExport MagickSizeType GetImageExtent(const Image *image)
1918 id = GetOpenMPThreadId();
1920 assert(image != (Image *) NULL);
1921 assert(image->signature == MagickSignature);
1922 if (image->debug != MagickFalse)
1923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1924 assert(image->cache != (Cache) NULL);
1925 cache_info=(CacheInfo *) image->cache;
1926 assert(cache_info->signature == MagickSignature);
1927 assert(id < (int) cache_info->number_threads);
1928 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1936 + G e t I m a g e P i x e l C a c h e %
1940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1942 % GetImagePixelCache() ensures that there is only a single reference to the
1943 % pixel cache to be modified, updating the provided cache pointer to point to
1944 % a clone of the original pixel cache if necessary.
1946 % The format of the GetImagePixelCache method is:
1948 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1949 % ExceptionInfo *exception)
1951 % A description of each parameter follows:
1953 % o image: the image.
1955 % o clone: any value other than MagickFalse clones the cache pixels.
1957 % o exception: return any errors or warnings in this structure.
1961 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
1967 Does the image match the pixel cache morphology?
1969 cache_info=(CacheInfo *) image->cache;
1970 if ((image->storage_class != cache_info->storage_class) ||
1971 (image->colorspace != cache_info->colorspace) ||
1972 (image->matte != cache_info->matte) ||
1973 (image->columns != cache_info->columns) ||
1974 (image->rows != cache_info->rows) ||
1975 (image->number_channels != cache_info->number_channels) ||
1976 (image->metacontent_extent != cache_info->metacontent_extent) ||
1977 (cache_info->nexus_info == (NexusInfo **) NULL) ||
1978 (cache_info->number_threads < GetOpenMPMaximumThreads()))
1979 return(MagickFalse);
1983 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1984 ExceptionInfo *exception)
1993 static MagickSizeType
1999 cache_timestamp = 0;
2002 LockSemaphoreInfo(image->semaphore);
2003 if (cpu_throttle == 0)
2009 Set CPU throttle in milleseconds.
2011 cpu_throttle=MagickResourceInfinity;
2012 limit=GetEnvironmentValue("MAGICK_THROTTLE");
2013 if (limit == (char *) NULL)
2014 limit=GetPolicyValue("throttle");
2015 if (limit != (char *) NULL)
2017 cpu_throttle=(MagickSizeType) StringToInteger(limit);
2018 limit=DestroyString(limit);
2021 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
2022 MagickDelay(cpu_throttle);
2023 if (time_limit == 0)
2026 Set the exire time in seconds.
2028 time_limit=GetMagickResourceLimit(TimeResource);
2029 cache_timestamp=time((time_t *) NULL);
2031 if ((time_limit != MagickResourceInfinity) &&
2032 ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
2033 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
2034 assert(image->cache != (Cache) NULL);
2035 cache_info=(CacheInfo *) image->cache;
2036 destroy=MagickFalse;
2037 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2039 LockSemaphoreInfo(cache_info->semaphore);
2040 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
2051 clone_image=(*image);
2052 clone_image.semaphore=AllocateSemaphoreInfo();
2053 clone_image.reference_count=1;
2054 clone_image.cache=ClonePixelCache(cache_info);
2055 clone_info=(CacheInfo *) clone_image.cache;
2056 status=OpenPixelCache(&clone_image,IOMode,exception);
2057 if (status != MagickFalse)
2059 if (clone != MagickFalse)
2060 status=ClonePixelCachePixels(clone_info,cache_info,exception);
2061 if (status != MagickFalse)
2063 if (cache_info->mode == ReadMode)
2064 cache_info->nexus_info=(NexusInfo **) NULL;
2066 image->cache=clone_image.cache;
2069 DestroySemaphoreInfo(&clone_image.semaphore);
2071 UnlockSemaphoreInfo(cache_info->semaphore);
2073 if (destroy != MagickFalse)
2074 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2075 if (status != MagickFalse)
2078 Ensure the image matches the pixel cache morphology.
2080 image->taint=MagickTrue;
2081 image->type=UndefinedType;
2082 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2083 status=OpenPixelCache(image,IOMode,exception);
2085 UnlockSemaphoreInfo(image->semaphore);
2086 if (status == MagickFalse)
2087 return((Cache) NULL);
2088 return(image->cache);
2092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096 % G e t O n e A u t h e n t i c P i x e l %
2100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2102 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2103 % location. The image background color is returned if an error occurs.
2105 % The format of the GetOneAuthenticPixel() method is:
2107 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2108 % const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2110 % A description of each parameter follows:
2112 % o image: the image.
2114 % o x,y: These values define the location of the pixel to return.
2116 % o pixel: return a pixel at the specified (x,y) location.
2118 % o exception: return any errors or warnings in this structure.
2121 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2122 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2130 assert(image != (Image *) NULL);
2131 assert(image->signature == MagickSignature);
2132 assert(image->cache != (Cache) NULL);
2133 cache_info=(CacheInfo *) image->cache;
2134 assert(cache_info->signature == MagickSignature);
2135 *pixel=image->background_color;
2136 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2137 (GetOneAuthenticPixelFromHandler) NULL)
2138 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2140 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2141 if (q == (Quantum *) NULL)
2142 return(MagickFalse);
2143 GetPixelPacket(image,q,pixel);
2148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2152 + 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 %
2156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2158 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2159 % location. The image background color is returned if an error occurs.
2161 % The format of the GetOneAuthenticPixelFromCache() method is:
2163 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2164 % const ssize_t x,const ssize_t y,PixelPacket *pixel,
2165 % ExceptionInfo *exception)
2167 % A description of each parameter follows:
2169 % o image: the image.
2171 % o x,y: These values define the location of the pixel to return.
2173 % o pixel: return a pixel at the specified (x,y) location.
2175 % o exception: return any errors or warnings in this structure.
2178 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2179 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2185 id = GetOpenMPThreadId();
2190 assert(image != (const Image *) NULL);
2191 assert(image->signature == MagickSignature);
2192 assert(image->cache != (Cache) NULL);
2193 cache_info=(CacheInfo *) image->cache;
2194 assert(cache_info->signature == MagickSignature);
2195 assert(id < (int) cache_info->number_threads);
2196 *pixel=image->background_color;
2197 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2199 if (q == (Quantum *) NULL)
2200 return(MagickFalse);
2201 GetPixelPacket(image,q,pixel);
2206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2210 % G e t O n e V i r t u a l M a g i c k P i x e l %
2214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2216 % GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2217 % location. The image background color is returned if an error occurs. If
2218 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2220 % The format of the GetOneVirtualMagickPixel() method is:
2222 % MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2223 % const ssize_t x,const ssize_t y,PixelInfo *pixel,
2224 % ExceptionInfo exception)
2226 % A description of each parameter follows:
2228 % o image: the image.
2230 % o x,y: these values define the location of the pixel to return.
2232 % o pixel: return a pixel at the specified (x,y) location.
2234 % o exception: return any errors or warnings in this structure.
2237 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2238 const ssize_t x,const ssize_t y,PixelInfo *pixel,
2239 ExceptionInfo *exception)
2245 id = GetOpenMPThreadId();
2247 register const Quantum
2250 assert(image != (const Image *) NULL);
2251 assert(image->signature == MagickSignature);
2252 assert(image->cache != (Cache) NULL);
2253 cache_info=(CacheInfo *) image->cache;
2254 assert(cache_info->signature == MagickSignature);
2255 assert(id < (int) cache_info->number_threads);
2256 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2257 1UL,1UL,cache_info->nexus_info[id],exception);
2258 GetPixelInfo(image,pixel);
2259 if (p == (const Quantum *) NULL)
2260 return(MagickFalse);
2261 SetPixelInfo(image,p,pixel);
2266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270 % G e t O n e V i r t u a l M e t h o d P i x e l %
2274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2276 % GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2277 % location as defined by specified pixel method. The image background color
2278 % is returned if an error occurs. If you plan to modify the pixel, use
2279 % GetOneAuthenticPixel() instead.
2281 % The format of the GetOneVirtualMethodPixel() method is:
2283 % MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2284 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2285 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2287 % A description of each parameter follows:
2289 % o image: the image.
2291 % o virtual_pixel_method: the virtual pixel method.
2293 % o x,y: These values define the location of the pixel to return.
2295 % o pixel: return a pixel at the specified (x,y) location.
2297 % o exception: return any errors or warnings in this structure.
2300 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2301 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2302 PixelPacket *pixel,ExceptionInfo *exception)
2308 id = GetOpenMPThreadId();
2313 assert(image != (const Image *) NULL);
2314 assert(image->signature == MagickSignature);
2315 assert(image->cache != (Cache) NULL);
2316 cache_info=(CacheInfo *) image->cache;
2317 assert(cache_info->signature == MagickSignature);
2318 *pixel=image->background_color;
2319 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2320 (GetOneVirtualPixelFromHandler) NULL)
2321 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2322 virtual_pixel_method,x,y,pixel,exception));
2323 assert(id < (int) cache_info->number_threads);
2324 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2325 cache_info->nexus_info[id],exception);
2326 if (p == (const Quantum *) NULL)
2327 return(MagickFalse);
2328 GetPixelPacket(image,p,pixel);
2329 if (image->colorspace == CMYKColorspace)
2330 pixel->black=GetPixelBlack(image,p);
2335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2339 % G e t O n e V i r t u a l P i x e l %
2343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2345 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2346 % (x,y) location. The image background color is returned if an error occurs.
2347 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2349 % The format of the GetOneVirtualPixel() method is:
2351 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2352 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2354 % A description of each parameter follows:
2356 % o image: the image.
2358 % o x,y: These values define the location of the pixel to return.
2360 % o pixel: return a pixel at the specified (x,y) location.
2362 % o exception: return any errors or warnings in this structure.
2365 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2366 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2372 id = GetOpenMPThreadId();
2377 assert(image != (const Image *) NULL);
2378 assert(image->signature == MagickSignature);
2379 assert(image->cache != (Cache) NULL);
2380 cache_info=(CacheInfo *) image->cache;
2381 assert(cache_info->signature == MagickSignature);
2382 *pixel=image->background_color;
2383 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2384 (GetOneVirtualPixelFromHandler) NULL)
2385 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2386 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2387 assert(id < (int) cache_info->number_threads);
2388 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2389 1UL,1UL,cache_info->nexus_info[id],exception);
2390 if (p == (const Quantum *) NULL)
2391 return(MagickFalse);
2392 GetPixelPacket(image,p,pixel);
2393 if (image->colorspace == CMYKColorspace)
2394 pixel->black=GetPixelBlack(image,p);
2399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2403 + 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 %
2407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2409 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2410 % specified (x,y) location. The image background color is returned if an
2413 % The format of the GetOneVirtualPixelFromCache() method is:
2415 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2416 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2417 % PixelPacket *pixel,ExceptionInfo *exception)
2419 % A description of each parameter follows:
2421 % o image: the image.
2423 % o virtual_pixel_method: the virtual pixel method.
2425 % o x,y: These values define the location of the pixel to return.
2427 % o pixel: return a pixel at the specified (x,y) location.
2429 % o exception: return any errors or warnings in this structure.
2432 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2433 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2434 PixelPacket *pixel,ExceptionInfo *exception)
2440 id = GetOpenMPThreadId();
2445 assert(image != (const Image *) NULL);
2446 assert(image->signature == MagickSignature);
2447 assert(image->cache != (Cache) NULL);
2448 cache_info=(CacheInfo *) image->cache;
2449 assert(cache_info->signature == MagickSignature);
2450 assert(id < (int) cache_info->number_threads);
2451 *pixel=image->background_color;
2452 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2453 cache_info->nexus_info[id],exception);
2454 if (p == (const Quantum *) NULL)
2455 return(MagickFalse);
2456 GetPixelPacket(image,p,pixel);
2457 if (image->colorspace == CMYKColorspace)
2458 pixel->black=GetPixelBlack(image,p);
2463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2467 + G e t P i x e l C a c h e C o l o r s p a c e %
2471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2473 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2475 % The format of the GetPixelCacheColorspace() method is:
2477 % Colorspace GetPixelCacheColorspace(Cache cache)
2479 % A description of each parameter follows:
2481 % o cache: the pixel cache.
2484 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
2489 assert(cache != (Cache) NULL);
2490 cache_info=(CacheInfo *) cache;
2491 assert(cache_info->signature == MagickSignature);
2492 if (cache_info->debug != MagickFalse)
2493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2494 cache_info->filename);
2495 return(cache_info->colorspace);
2499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2503 + G e t P i x e l C a c h e M e t h o d s %
2507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2509 % GetPixelCacheMethods() initializes the CacheMethods structure.
2511 % The format of the GetPixelCacheMethods() method is:
2513 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2515 % A description of each parameter follows:
2517 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2520 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
2522 assert(cache_methods != (CacheMethods *) NULL);
2523 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2524 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2525 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2526 cache_methods->get_virtual_metacontent_from_handler=
2527 GetVirtualMetacontentFromCache;
2528 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2529 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2530 cache_methods->get_authentic_metacontent_from_handler=
2531 GetAuthenticMetacontentFromCache;
2532 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2533 cache_methods->get_one_authentic_pixel_from_handler=
2534 GetOneAuthenticPixelFromCache;
2535 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2536 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2537 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2545 + G e t P i x e l C a c h e N e x u s E x t e n t %
2549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2551 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2552 % corresponding with the last call to SetPixelCacheNexusPixels() or
2553 % GetPixelCacheNexusPixels().
2555 % The format of the GetPixelCacheNexusExtent() method is:
2557 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2558 % NexusInfo *nexus_info)
2560 % A description of each parameter follows:
2562 % o nexus_info: the nexus info.
2565 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2566 NexusInfo *nexus_info)
2574 assert(cache != (const Cache) NULL);
2575 cache_info=(CacheInfo *) cache;
2576 assert(cache_info->signature == MagickSignature);
2577 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2579 return((MagickSizeType) cache_info->columns*cache_info->rows);
2584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2588 + 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 %
2592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2594 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2597 % The format of the GetPixelCacheNexusMetacontent() method is:
2599 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2600 % NexusInfo *nexus_info)
2602 % A description of each parameter follows:
2604 % o cache: the pixel cache.
2606 % o nexus_info: the cache nexus to return the meta-content.
2609 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache,
2610 NexusInfo *nexus_info)
2615 assert(cache != (const Cache) NULL);
2616 cache_info=(CacheInfo *) cache;
2617 assert(cache_info->signature == MagickSignature);
2618 if (cache_info->storage_class == UndefinedClass)
2619 return((void *) NULL);
2620 return(nexus_info->metacontent);
2624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628 + G e t P i x e l C a c h e N e x u s P i x e l s %
2632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2637 % The format of the GetPixelCacheNexusPixels() method is:
2639 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2640 % NexusInfo *nexus_info)
2642 % A description of each parameter follows:
2644 % o cache: the pixel cache.
2646 % o nexus_info: the cache nexus to return the pixels.
2649 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache,
2650 NexusInfo *nexus_info)
2655 assert(cache != (const Cache) NULL);
2656 cache_info=(CacheInfo *) cache;
2657 assert(cache_info->signature == MagickSignature);
2658 if (cache_info->storage_class == UndefinedClass)
2659 return((Quantum *) NULL);
2660 return(nexus_info->pixels);
2664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2668 + G e t P i x e l C a c h e P i x e l s %
2672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2674 % GetPixelCachePixels() returns the pixels associated with the specified image.
2676 % The format of the GetPixelCachePixels() method is:
2678 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2679 % ExceptionInfo *exception)
2681 % A description of each parameter follows:
2683 % o image: the image.
2685 % o length: the pixel cache length.
2687 % o exception: return any errors or warnings in this structure.
2690 MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2691 ExceptionInfo *exception)
2696 assert(image != (const Image *) NULL);
2697 assert(image->signature == MagickSignature);
2698 assert(image->cache != (Cache) NULL);
2699 assert(length != (MagickSizeType *) NULL);
2700 assert(exception != (ExceptionInfo *) NULL);
2701 assert(exception->signature == MagickSignature);
2702 cache_info=(CacheInfo *) image->cache;
2703 assert(cache_info->signature == MagickSignature);
2705 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2706 return((void *) NULL);
2707 *length=cache_info->length;
2708 return((void *) cache_info->pixels);
2712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2716 + 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 %
2720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2722 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2724 % The format of the GetPixelCacheStorageClass() method is:
2726 % ClassType GetPixelCacheStorageClass(Cache cache)
2728 % A description of each parameter follows:
2730 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2732 % o cache: the pixel cache.
2735 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
2740 assert(cache != (Cache) NULL);
2741 cache_info=(CacheInfo *) cache;
2742 assert(cache_info->signature == MagickSignature);
2743 if (cache_info->debug != MagickFalse)
2744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2745 cache_info->filename);
2746 return(cache_info->storage_class);
2750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2754 + G e t P i x e l C a c h e T i l e S i z e %
2758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2760 % GetPixelCacheTileSize() returns the pixel cache tile size.
2762 % The format of the GetPixelCacheTileSize() method is:
2764 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2767 % A description of each parameter follows:
2769 % o image: the image.
2771 % o width: the optimize cache tile width in pixels.
2773 % o height: the optimize cache tile height in pixels.
2776 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2782 assert(image != (Image *) NULL);
2783 assert(image->signature == MagickSignature);
2784 if (image->debug != MagickFalse)
2785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2786 cache_info=(CacheInfo *) image->cache;
2787 assert(cache_info->signature == MagickSignature);
2788 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2789 if (GetPixelCacheType(image) == DiskCache)
2790 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2799 + G e t P i x e l C a c h e T y p e %
2803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2805 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2807 % The format of the GetPixelCacheType() method is:
2809 % CacheType GetPixelCacheType(const Image *image)
2811 % A description of each parameter follows:
2813 % o image: the image.
2816 MagickPrivate CacheType GetPixelCacheType(const Image *image)
2821 assert(image != (Image *) NULL);
2822 assert(image->signature == MagickSignature);
2823 assert(image->cache != (Cache) NULL);
2824 cache_info=(CacheInfo *) image->cache;
2825 assert(cache_info->signature == MagickSignature);
2826 return(cache_info->type);
2830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2834 + 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 %
2838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2840 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2841 % pixel cache. A virtual pixel is any pixel access that is outside the
2842 % boundaries of the image cache.
2844 % The format of the GetPixelCacheVirtualMethod() method is:
2846 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2848 % A description of each parameter follows:
2850 % o image: the image.
2853 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2858 assert(image != (Image *) NULL);
2859 assert(image->signature == MagickSignature);
2860 assert(image->cache != (Cache) NULL);
2861 cache_info=(CacheInfo *) image->cache;
2862 assert(cache_info->signature == MagickSignature);
2863 return(cache_info->virtual_pixel_method);
2867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871 + 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 %
2875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2878 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2880 % The format of the GetVirtualMetacontentFromCache() method is:
2882 % void *GetVirtualMetacontentFromCache(const Image *image)
2884 % A description of each parameter follows:
2886 % o image: the image.
2889 static const void *GetVirtualMetacontentFromCache(const Image *image)
2895 id = GetOpenMPThreadId();
2900 assert(image != (const Image *) NULL);
2901 assert(image->signature == MagickSignature);
2902 assert(image->cache != (Cache) NULL);
2903 cache_info=(CacheInfo *) image->cache;
2904 assert(cache_info->signature == MagickSignature);
2905 assert(id < (int) cache_info->number_threads);
2906 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2907 cache_info->nexus_info[id]);
2908 return(metacontent);
2912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2916 + 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 %
2920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2922 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2925 % The format of the GetVirtualMetacontentFromNexus() method is:
2927 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2928 % NexusInfo *nexus_info)
2930 % A description of each parameter follows:
2932 % o cache: the pixel cache.
2934 % o nexus_info: the cache nexus to return the meta-content.
2937 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
2938 NexusInfo *nexus_info)
2943 assert(cache != (Cache) NULL);
2944 cache_info=(CacheInfo *) cache;
2945 assert(cache_info->signature == MagickSignature);
2946 if (cache_info->storage_class == UndefinedClass)
2947 return((void *) NULL);
2948 return(nexus_info->metacontent);
2952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956 % G e t V i r t u a l M e t a c o n t e n t %
2960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2962 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2963 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2964 % returned if the meta-content are not available.
2966 % The format of the GetVirtualMetacontent() method is:
2968 % const void *GetVirtualMetacontent(const Image *image)
2970 % A description of each parameter follows:
2972 % o image: the image.
2975 MagickExport const void *GetVirtualMetacontent(const Image *image)
2981 id = GetOpenMPThreadId();
2986 assert(image != (const Image *) NULL);
2987 assert(image->signature == MagickSignature);
2988 assert(image->cache != (Cache) NULL);
2989 cache_info=(CacheInfo *) image->cache;
2990 assert(cache_info->signature == MagickSignature);
2991 if (cache_info->methods.get_virtual_metacontent_from_handler !=
2992 (GetVirtualMetacontentFromHandler) NULL)
2994 metacontent=cache_info->methods.
2995 get_virtual_metacontent_from_handler(image);
2996 return(metacontent);
2998 assert(id < (int) cache_info->number_threads);
2999 metacontent=GetVirtualMetacontentFromNexus(cache_info,
3000 cache_info->nexus_info[id]);
3001 return(metacontent);
3005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3009 + 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 %
3013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3015 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3016 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3017 % is returned if the pixels are transferred, otherwise a NULL is returned.
3019 % The format of the GetVirtualPixelsFromNexus() method is:
3021 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
3022 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3023 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3024 % ExceptionInfo *exception)
3026 % A description of each parameter follows:
3028 % o image: the image.
3030 % o virtual_pixel_method: the virtual pixel method.
3032 % o x,y,columns,rows: These values define the perimeter of a region of
3035 % o nexus_info: the cache nexus to acquire.
3037 % o exception: return any errors or warnings in this structure.
3044 0, 48, 12, 60, 3, 51, 15, 63,
3045 32, 16, 44, 28, 35, 19, 47, 31,
3046 8, 56, 4, 52, 11, 59, 7, 55,
3047 40, 24, 36, 20, 43, 27, 39, 23,
3048 2, 50, 14, 62, 1, 49, 13, 61,
3049 34, 18, 46, 30, 33, 17, 45, 29,
3050 10, 58, 6, 54, 9, 57, 5, 53,
3051 42, 26, 38, 22, 41, 25, 37, 21
3054 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3059 index=x+DitherMatrix[x & 0x07]-32L;
3062 if (index >= (ssize_t) columns)
3063 return((ssize_t) columns-1L);
3067 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3072 index=y+DitherMatrix[y & 0x07]-32L;
3075 if (index >= (ssize_t) rows)
3076 return((ssize_t) rows-1L);
3080 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3084 if (x >= (ssize_t) columns)
3085 return((ssize_t) (columns-1));
3089 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3093 if (y >= (ssize_t) rows)
3094 return((ssize_t) (rows-1));
3098 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3100 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3103 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3105 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3108 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3109 const size_t extent)
3115 Compute the remainder of dividing offset by extent. It returns not only
3116 the quotient (tile the offset falls in) but also the positive remainer
3117 within that tile such that 0 <= remainder < extent. This method is
3118 essentially a ldiv() using a floored modulo division rather than the
3119 normal default truncated modulo division.
3121 modulo.quotient=offset/(ssize_t) extent;
3124 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3128 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3129 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3130 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3131 ExceptionInfo *exception)
3148 virtual_pixel[MaxPixelChannels];
3153 register const Quantum
3166 register unsigned char
3173 *virtual_metacontent;
3178 assert(image != (const Image *) NULL);
3179 assert(image->signature == MagickSignature);
3180 assert(image->cache != (Cache) NULL);
3181 cache_info=(CacheInfo *) image->cache;
3182 assert(cache_info->signature == MagickSignature);
3183 if (cache_info->type == UndefinedCache)
3184 return((const Quantum *) NULL);
3187 region.width=columns;
3189 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3190 if (pixels == (Quantum *) NULL)
3191 return((const Quantum *) NULL);
3193 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3194 nexus_info->region.x;
3195 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3196 nexus_info->region.width-1L;
3197 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3198 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3199 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3200 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3206 Pixel request is inside cache extents.
3208 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3210 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3211 if (status == MagickFalse)
3212 return((const Quantum *) NULL);
3213 if (cache_info->metacontent_extent != 0)
3215 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3216 if (status == MagickFalse)
3217 return((const Quantum *) NULL);
3222 Pixel request is outside cache extents.
3224 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3225 virtual_nexus=AcquirePixelCacheNexus(1);
3226 if (virtual_nexus == (NexusInfo **) NULL)
3228 if (virtual_nexus != (NexusInfo **) NULL)
3229 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3230 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3231 "UnableToGetCacheNexus","`%s'",image->filename);
3232 return((const Quantum *) NULL);
3234 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3235 sizeof(*virtual_pixel));
3236 virtual_metacontent=(void *) NULL;
3237 switch (virtual_pixel_method)
3239 case BackgroundVirtualPixelMethod:
3240 case BlackVirtualPixelMethod:
3241 case GrayVirtualPixelMethod:
3242 case TransparentVirtualPixelMethod:
3243 case MaskVirtualPixelMethod:
3244 case WhiteVirtualPixelMethod:
3245 case EdgeVirtualPixelMethod:
3246 case CheckerTileVirtualPixelMethod:
3247 case HorizontalTileVirtualPixelMethod:
3248 case VerticalTileVirtualPixelMethod:
3250 if (cache_info->metacontent_extent != 0)
3253 Acquire a metacontent buffer.
3255 virtual_metacontent=(void *) AcquireAlignedMemory(1,
3256 cache_info->metacontent_extent);
3257 if (virtual_metacontent == (void *) NULL)
3259 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3260 (void) ThrowMagickException(exception,GetMagickModule(),
3261 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3262 return((const Quantum *) NULL);
3264 (void) ResetMagickMemory(virtual_metacontent,0,
3265 cache_info->metacontent_extent);
3267 switch (virtual_pixel_method)
3269 case BlackVirtualPixelMethod:
3271 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3272 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3273 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3276 case GrayVirtualPixelMethod:
3278 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3279 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
3281 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3284 case TransparentVirtualPixelMethod:
3286 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3287 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3288 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3291 case MaskVirtualPixelMethod:
3292 case WhiteVirtualPixelMethod:
3294 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3295 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3296 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3301 SetPixelRed(image,image->background_color.red,virtual_pixel);
3302 SetPixelGreen(image,image->background_color.green,virtual_pixel);
3303 SetPixelBlue(image,image->background_color.blue,virtual_pixel);
3304 if (image->colorspace == CMYKColorspace)
3305 SetPixelBlack(image,image->background_color.black,virtual_pixel);
3306 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3315 for (v=0; v < (ssize_t) rows; v++)
3317 for (u=0; u < (ssize_t) columns; u+=length)
3319 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3320 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3321 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3329 Transfer a single pixel.
3331 length=(MagickSizeType) 1;
3332 switch (virtual_pixel_method)
3336 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3337 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3338 1UL,1UL,*virtual_nexus,exception);
3339 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3342 case RandomVirtualPixelMethod:
3344 if (cache_info->random_info == (RandomInfo *) NULL)
3345 cache_info->random_info=AcquireRandomInfo();
3346 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3347 RandomX(cache_info->random_info,cache_info->columns),
3348 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3349 *virtual_nexus,exception);
3350 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3353 case DitherVirtualPixelMethod:
3355 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3356 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3357 1UL,1UL,*virtual_nexus,exception);
3358 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3361 case TileVirtualPixelMethod:
3363 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3364 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3365 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3366 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3368 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3371 case MirrorVirtualPixelMethod:
3373 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3374 if ((x_modulo.quotient & 0x01) == 1L)
3375 x_modulo.remainder=(ssize_t) cache_info->columns-
3376 x_modulo.remainder-1L;
3377 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3378 if ((y_modulo.quotient & 0x01) == 1L)
3379 y_modulo.remainder=(ssize_t) cache_info->rows-
3380 y_modulo.remainder-1L;
3381 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3382 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3384 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3387 case HorizontalTileEdgeVirtualPixelMethod:
3389 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3390 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3391 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3392 *virtual_nexus,exception);
3393 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3396 case VerticalTileEdgeVirtualPixelMethod:
3398 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3399 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3400 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3401 *virtual_nexus,exception);
3402 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3405 case BackgroundVirtualPixelMethod:
3406 case BlackVirtualPixelMethod:
3407 case GrayVirtualPixelMethod:
3408 case TransparentVirtualPixelMethod:
3409 case MaskVirtualPixelMethod:
3410 case WhiteVirtualPixelMethod:
3413 r=virtual_metacontent;
3416 case EdgeVirtualPixelMethod:
3417 case CheckerTileVirtualPixelMethod:
3419 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3420 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3421 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3424 r=virtual_metacontent;
3427 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3428 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3430 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3433 case HorizontalTileVirtualPixelMethod:
3435 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3438 r=virtual_metacontent;
3441 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3442 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3443 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3444 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3446 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3449 case VerticalTileVirtualPixelMethod:
3451 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3454 r=virtual_metacontent;
3457 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3458 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3459 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3460 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3462 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3466 if (p == (const Quantum *) NULL)
3468 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3470 q+=cache_info->number_channels;
3471 if ((s != (void *) NULL) && (r != (const void *) NULL))
3473 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3474 s+=cache_info->metacontent_extent;
3479 Transfer a run of pixels.
3481 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3482 length,1UL,*virtual_nexus,exception);
3483 if (p == (const Quantum *) NULL)
3485 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3486 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3487 q+=length*cache_info->number_channels;
3488 if ((r != (void *) NULL) && (s != (const void *) NULL))
3490 (void) memcpy(s,r,(size_t) length);
3491 s+=length*cache_info->metacontent_extent;
3498 if (virtual_metacontent != (void *) NULL)
3499 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3500 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3509 + G e t V i r t u a l P i x e l C a c h e %
3513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3515 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3516 % cache as defined by the geometry parameters. A pointer to the pixels
3517 % is returned if the pixels are transferred, otherwise a NULL is returned.
3519 % The format of the GetVirtualPixelCache() method is:
3521 % const Quantum *GetVirtualPixelCache(const Image *image,
3522 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3523 % const ssize_t y,const size_t columns,const size_t rows,
3524 % ExceptionInfo *exception)
3526 % A description of each parameter follows:
3528 % o image: the image.
3530 % o virtual_pixel_method: the virtual pixel method.
3532 % o x,y,columns,rows: These values define the perimeter of a region of
3535 % o exception: return any errors or warnings in this structure.
3538 static const Quantum *GetVirtualPixelCache(const Image *image,
3539 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3540 const size_t columns,const size_t rows,ExceptionInfo *exception)
3546 id = GetOpenMPThreadId();
3551 assert(image != (const Image *) NULL);
3552 assert(image->signature == MagickSignature);
3553 assert(image->cache != (Cache) NULL);
3554 cache_info=(CacheInfo *) image->cache;
3555 assert(cache_info->signature == MagickSignature);
3556 assert(id < (int) cache_info->number_threads);
3557 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3558 cache_info->nexus_info[id],exception);
3563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3567 % G e t V i r t u a l P i x e l Q u e u e %
3571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3573 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3574 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3576 % The format of the GetVirtualPixelQueue() method is:
3578 % const Quantum *GetVirtualPixelQueue(const Image image)
3580 % A description of each parameter follows:
3582 % o image: the image.
3585 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3591 id = GetOpenMPThreadId();
3593 assert(image != (const Image *) NULL);
3594 assert(image->signature == MagickSignature);
3595 assert(image->cache != (Cache) NULL);
3596 cache_info=(CacheInfo *) image->cache;
3597 assert(cache_info->signature == MagickSignature);
3598 if (cache_info->methods.get_virtual_pixels_handler !=
3599 (GetVirtualPixelsHandler) NULL)
3600 return(cache_info->methods.get_virtual_pixels_handler(image));
3601 assert(id < (int) cache_info->number_threads);
3602 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3610 % G e t V i r t u a l P i x e l s %
3614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3616 % GetVirtualPixels() returns an immutable pixel region. If the
3617 % region is successfully accessed, a pointer to it is returned, otherwise
3618 % NULL is returned. The returned pointer may point to a temporary working
3619 % copy of the pixels or it may point to the original pixels in memory.
3620 % Performance is maximized if the selected region is part of one row, or one
3621 % or more full rows, since there is opportunity to access the pixels in-place
3622 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3623 % returned pointer must *never* be deallocated by the user.
3625 % Pixels accessed via the returned pointer represent a simple array of type
3626 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3627 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3628 % access the meta-content (of type void) corresponding to the the
3631 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3633 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3634 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3635 % GetCacheViewAuthenticPixels() instead.
3637 % The format of the GetVirtualPixels() method is:
3639 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3640 % const ssize_t y,const size_t columns,const size_t rows,
3641 % ExceptionInfo *exception)
3643 % A description of each parameter follows:
3645 % o image: the image.
3647 % o x,y,columns,rows: These values define the perimeter of a region of
3650 % o exception: return any errors or warnings in this structure.
3653 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3654 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3655 ExceptionInfo *exception)
3661 id = GetOpenMPThreadId();
3666 assert(image != (const Image *) NULL);
3667 assert(image->signature == MagickSignature);
3668 assert(image->cache != (Cache) NULL);
3669 cache_info=(CacheInfo *) image->cache;
3670 assert(cache_info->signature == MagickSignature);
3671 if (cache_info->methods.get_virtual_pixel_handler !=
3672 (GetVirtualPixelHandler) NULL)
3673 return(cache_info->methods.get_virtual_pixel_handler(image,
3674 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3675 assert(id < (int) cache_info->number_threads);
3676 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3677 columns,rows,cache_info->nexus_info[id],exception);
3682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3686 + 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 %
3690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3692 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3693 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3695 % The format of the GetVirtualPixelsCache() method is:
3697 % Quantum *GetVirtualPixelsCache(const Image *image)
3699 % A description of each parameter follows:
3701 % o image: the image.
3704 static const Quantum *GetVirtualPixelsCache(const Image *image)
3710 id = GetOpenMPThreadId();
3712 assert(image != (const Image *) NULL);
3713 assert(image->signature == MagickSignature);
3714 assert(image->cache != (Cache) NULL);
3715 cache_info=(CacheInfo *) image->cache;
3716 assert(cache_info->signature == MagickSignature);
3717 assert(id < (int) cache_info->number_threads);
3718 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3726 + G e t V i r t u a l P i x e l s N e x u s %
3730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3732 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3735 % The format of the GetVirtualPixelsNexus() method is:
3737 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3738 % NexusInfo *nexus_info)
3740 % A description of each parameter follows:
3742 % o cache: the pixel cache.
3744 % o nexus_info: the cache nexus to return the colormap pixels.
3747 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
3748 NexusInfo *nexus_info)
3753 assert(cache != (Cache) NULL);
3754 cache_info=(CacheInfo *) cache;
3755 assert(cache_info->signature == MagickSignature);
3756 if (cache_info->storage_class == UndefinedClass)
3757 return((Quantum *) NULL);
3758 return((const Quantum *) nexus_info->pixels);
3762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3766 + M a s k P i x e l C a c h e N e x u s %
3770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3772 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3773 % The method returns MagickTrue if the pixel region is masked, otherwise
3776 % The format of the MaskPixelCacheNexus() method is:
3778 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3779 % NexusInfo *nexus_info,ExceptionInfo *exception)
3781 % A description of each parameter follows:
3783 % o image: the image.
3785 % o nexus_info: the cache nexus to clip.
3787 % o exception: return any errors or warnings in this structure.
3791 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3792 const MagickRealType alpha,const PixelInfo *q,
3793 const MagickRealType beta,PixelInfo *composite)
3798 if (alpha == TransparentAlpha)
3803 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3804 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3805 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3806 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3807 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3808 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3809 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3812 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3813 ExceptionInfo *exception)
3829 register const Quantum
3842 if (image->debug != MagickFalse)
3843 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3844 if (image->mask == (Image *) NULL)
3845 return(MagickFalse);
3846 cache_info=(CacheInfo *) image->cache;
3847 if (cache_info == (Cache) NULL)
3848 return(MagickFalse);
3849 image_nexus=AcquirePixelCacheNexus(1);
3850 clip_nexus=AcquirePixelCacheNexus(1);
3851 if ((image_nexus == (NexusInfo **) NULL) ||
3852 (clip_nexus == (NexusInfo **) NULL))
3853 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3854 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3855 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3856 nexus_info->region.height,image_nexus[0],exception);
3857 q=nexus_info->pixels;
3858 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3859 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3860 nexus_info->region.height,clip_nexus[0],&image->exception);
3861 GetPixelInfo(image,&alpha);
3862 GetPixelInfo(image,&beta);
3863 number_pixels=(MagickSizeType) nexus_info->region.width*
3864 nexus_info->region.height;
3865 for (i=0; i < (ssize_t) number_pixels; i++)
3867 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3869 SetPixelInfo(image,p,&alpha);
3870 SetPixelInfo(image,q,&beta);
3871 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3872 &alpha,alpha.alpha,&beta);
3873 SetPixelRed(image,ClampToQuantum(beta.red),q);
3874 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3875 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3876 if (cache_info->colorspace == CMYKColorspace)
3877 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3878 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3883 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3884 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3885 if (i < (ssize_t) number_pixels)
3886 return(MagickFalse);
3891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3895 + O p e n P i x e l C a c h e %
3899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3901 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3902 % dimensions, allocating space for the image pixels and optionally the
3903 % metacontent, and memory mapping the cache if it is disk based. The cache
3904 % nexus array is initialized as well.
3906 % The format of the OpenPixelCache() method is:
3908 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3909 % ExceptionInfo *exception)
3911 % A description of each parameter follows:
3913 % o image: the image.
3915 % o mode: ReadMode, WriteMode, or IOMode.
3917 % o exception: return any errors or warnings in this structure.
3921 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3923 cache_info->mapped=MagickFalse;
3924 cache_info->pixels=(Quantum *) AcquireAlignedMemory(1,(size_t)
3925 cache_info->length);
3926 if (cache_info->pixels == (Quantum *) NULL)
3928 cache_info->mapped=MagickTrue;
3929 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3930 cache_info->length);
3934 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3944 cache_info=(CacheInfo *) image->cache;
3945 if (image->debug != MagickFalse)
3948 format[MaxTextExtent],
3949 message[MaxTextExtent];
3951 (void) FormatMagickSize(length,MagickFalse,format);
3952 (void) FormatLocaleString(message,MaxTextExtent,
3953 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3954 cache_info->cache_filename,cache_info->file,format);
3955 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3957 if (length != (MagickSizeType) ((MagickOffsetType) length))
3958 return(MagickFalse);
3959 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3961 return(MagickFalse);
3962 if ((MagickSizeType) extent >= length)
3964 offset=(MagickOffsetType) length-1;
3965 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3966 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3969 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3970 ExceptionInfo *exception)
3977 format[MaxTextExtent],
3978 message[MaxTextExtent];
3991 assert(image != (const Image *) NULL);
3992 assert(image->signature == MagickSignature);
3993 assert(image->cache != (Cache) NULL);
3994 if (image->debug != MagickFalse)
3995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3996 if ((image->columns == 0) || (image->rows == 0))
3997 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3998 cache_info=(CacheInfo *) image->cache;
3999 assert(cache_info->signature == MagickSignature);
4000 source_info=(*cache_info);
4001 source_info.file=(-1);
4002 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4003 image->filename,(double) GetImageIndexInList(image));
4004 cache_info->storage_class=image->storage_class;
4005 cache_info->colorspace=image->colorspace;
4006 cache_info->matte=image->matte;
4007 cache_info->rows=image->rows;
4008 cache_info->columns=image->columns;
4009 InitializePixelChannelMap(image);
4010 cache_info->number_channels=GetPixelChannels(image);
4011 cache_info->metacontent_extent=image->metacontent_extent;
4012 cache_info->mode=mode;
4013 if (image->ping != MagickFalse)
4015 cache_info->type=PingCache;
4016 cache_info->pixels=(Quantum *) NULL;
4017 cache_info->metacontent=(void *) NULL;
4018 cache_info->length=0;
4021 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4022 packet_size=cache_info->number_channels*sizeof(Quantum);
4023 if (image->metacontent_extent != 0)
4024 packet_size+=cache_info->metacontent_extent;
4025 length=number_pixels*packet_size;
4026 columns=(size_t) (length/cache_info->rows/packet_size);
4027 if (cache_info->columns != columns)
4028 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4030 cache_info->length=length;
4031 if ((cache_info->type != UndefinedCache) &&
4032 (cache_info->columns <= source_info.columns) &&
4033 (cache_info->rows <= source_info.rows) &&
4034 (cache_info->number_channels <= source_info.number_channels) &&
4035 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4038 Inline pixel cache clone optimization.
4040 if ((cache_info->columns == source_info.columns) &&
4041 (cache_info->rows == source_info.rows) &&
4042 (cache_info->number_channels == source_info.number_channels) &&
4043 (cache_info->metacontent_extent == source_info.metacontent_extent))
4045 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4047 status=AcquireMagickResource(AreaResource,cache_info->length);
4048 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4049 cache_info->metacontent_extent);
4050 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4052 status=AcquireMagickResource(MemoryResource,cache_info->length);
4053 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4054 (cache_info->type == MemoryCache))
4056 AllocatePixelCachePixels(cache_info);
4057 if (cache_info->pixels == (Quantum *) NULL)
4058 cache_info->pixels=source_info.pixels;
4062 Create memory pixel cache.
4065 if (image->debug != MagickFalse)
4067 (void) FormatMagickSize(cache_info->length,MagickTrue,
4069 (void) FormatLocaleString(message,MaxTextExtent,
4070 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4071 cache_info->filename,cache_info->mapped != MagickFalse ?
4072 "anonymous" : "heap",(double) cache_info->columns,(double)
4073 cache_info->rows,(double) cache_info->number_channels,
4075 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4078 cache_info->type=MemoryCache;
4079 cache_info->metacontent=(void *) NULL;
4080 if (cache_info->metacontent_extent != 0)
4081 cache_info->metacontent=(void *) (cache_info->pixels+
4082 number_pixels*cache_info->number_channels);
4083 if (source_info.storage_class != UndefinedClass)
4085 status=ClonePixelCachePixels(cache_info,&source_info,
4087 RelinquishPixelCachePixels(&source_info);
4092 RelinquishMagickResource(MemoryResource,cache_info->length);
4095 Create pixel cache on disk.
4097 status=AcquireMagickResource(DiskResource,cache_info->length);
4098 if (status == MagickFalse)
4100 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4101 "CacheResourcesExhausted","`%s'",image->filename);
4102 return(MagickFalse);
4104 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4106 RelinquishMagickResource(DiskResource,cache_info->length);
4107 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4109 return(MagickFalse);
4111 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4112 cache_info->length);
4113 if (status == MagickFalse)
4115 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4117 return(MagickFalse);
4119 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4120 cache_info->metacontent_extent);
4121 status=AcquireMagickResource(AreaResource,cache_info->length);
4122 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4123 cache_info->type=DiskCache;
4126 status=AcquireMagickResource(MapResource,cache_info->length);
4127 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4128 (cache_info->type != MemoryCache))
4129 cache_info->type=DiskCache;
4132 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4133 cache_info->offset,(size_t) cache_info->length);
4134 if (cache_info->pixels == (Quantum *) NULL)
4136 cache_info->type=DiskCache;
4137 cache_info->pixels=source_info.pixels;
4142 Create file-backed memory-mapped pixel cache.
4145 (void) ClosePixelCacheOnDisk(cache_info);
4146 cache_info->type=MapCache;
4147 cache_info->mapped=MagickTrue;
4148 cache_info->metacontent=(void *) NULL;
4149 if (cache_info->metacontent_extent != 0)
4150 cache_info->metacontent=(void *) (cache_info->pixels+
4151 number_pixels*cache_info->number_channels);
4152 if (source_info.storage_class != UndefinedClass)
4154 status=ClonePixelCachePixels(cache_info,&source_info,
4156 RelinquishPixelCachePixels(&source_info);
4158 if (image->debug != MagickFalse)
4160 (void) FormatMagickSize(cache_info->length,MagickTrue,
4162 (void) FormatLocaleString(message,MaxTextExtent,
4163 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4164 cache_info->filename,cache_info->cache_filename,
4165 cache_info->file,(double) cache_info->columns,(double)
4166 cache_info->rows,(double) cache_info->number_channels,
4168 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4174 RelinquishMagickResource(MapResource,cache_info->length);
4177 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4179 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4180 RelinquishPixelCachePixels(&source_info);
4182 if (image->debug != MagickFalse)
4184 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4185 (void) FormatLocaleString(message,MaxTextExtent,
4186 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4187 cache_info->cache_filename,cache_info->file,(double)
4188 cache_info->columns,(double) cache_info->rows,(double)
4189 cache_info->number_channels,format);
4190 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4200 + P e r s i s t P i x e l C a c h e %
4204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4206 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4207 % persistent pixel cache is one that resides on disk and is not destroyed
4208 % when the program exits.
4210 % The format of the PersistPixelCache() method is:
4212 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4213 % const MagickBooleanType attach,MagickOffsetType *offset,
4214 % ExceptionInfo *exception)
4216 % A description of each parameter follows:
4218 % o image: the image.
4220 % o filename: the persistent pixel cache filename.
4222 % o attach: A value other than zero initializes the persistent pixel cache.
4224 % o initialize: A value other than zero initializes the persistent pixel
4227 % o offset: the offset in the persistent cache to store pixels.
4229 % o exception: return any errors or warnings in this structure.
4232 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4233 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4234 ExceptionInfo *exception)
4249 assert(image != (Image *) NULL);
4250 assert(image->signature == MagickSignature);
4251 if (image->debug != MagickFalse)
4252 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4253 assert(image->cache != (void *) NULL);
4254 assert(filename != (const char *) NULL);
4255 assert(offset != (MagickOffsetType *) NULL);
4256 page_size=GetMagickPageSize();
4257 cache_info=(CacheInfo *) image->cache;
4258 assert(cache_info->signature == MagickSignature);
4259 if (attach != MagickFalse)
4262 Attach existing persistent pixel cache.
4264 if (image->debug != MagickFalse)
4265 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4266 "attach persistent cache");
4267 (void) CopyMagickString(cache_info->cache_filename,filename,
4269 cache_info->type=DiskCache;
4270 cache_info->offset=(*offset);
4271 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4272 return(MagickFalse);
4273 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4276 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4277 (cache_info->reference_count == 1))
4279 LockSemaphoreInfo(cache_info->semaphore);
4280 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4281 (cache_info->reference_count == 1))
4287 Usurp existing persistent pixel cache.
4289 status=rename(cache_info->cache_filename,filename);
4292 (void) CopyMagickString(cache_info->cache_filename,filename,
4294 *offset+=cache_info->length+page_size-(cache_info->length %
4296 UnlockSemaphoreInfo(cache_info->semaphore);
4297 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4298 if (image->debug != MagickFalse)
4299 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4300 "Usurp resident persistent cache");
4304 UnlockSemaphoreInfo(cache_info->semaphore);
4307 Clone persistent pixel cache.
4309 clone_image=(*image);
4310 clone_info=(CacheInfo *) clone_image.cache;
4311 image->cache=ClonePixelCache(cache_info);
4312 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4313 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4314 cache_info->type=DiskCache;
4315 cache_info->offset=(*offset);
4316 cache_info=(CacheInfo *) image->cache;
4317 status=OpenPixelCache(image,IOMode,exception);
4318 if (status != MagickFalse)
4319 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4320 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4321 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4330 + Q u e u e A u t h e n t i c N e x u s %
4334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4336 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4337 % by the region rectangle and returns a pointer to the region. This region is
4338 % subsequently transferred from the pixel cache with
4339 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4340 % pixels are transferred, otherwise a NULL is returned.
4342 % The format of the QueueAuthenticNexus() method is:
4344 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4345 % const ssize_t y,const size_t columns,const size_t rows,
4346 % NexusInfo *nexus_info,ExceptionInfo *exception)
4348 % A description of each parameter follows:
4350 % o image: the image.
4352 % o x,y,columns,rows: These values define the perimeter of a region of
4355 % o nexus_info: the cache nexus to set.
4357 % o exception: return any errors or warnings in this structure.
4360 MagickPrivate Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4361 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4362 ExceptionInfo *exception)
4377 Validate pixel cache geometry.
4379 assert(image != (const Image *) NULL);
4380 assert(image->signature == MagickSignature);
4381 assert(image->cache != (Cache) NULL);
4382 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4383 assert(cache_info->signature == MagickSignature);
4384 if (cache_info == (Cache) NULL)
4385 return((Quantum *) NULL);
4386 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4388 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4389 "NoPixelsDefinedInCache","`%s'",image->filename);
4390 return((Quantum *) NULL);
4392 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4393 (y >= (ssize_t) cache_info->rows))
4395 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4396 "PixelsAreNotAuthentic","`%s'",image->filename);
4397 return((Quantum *) NULL);
4399 offset=(MagickOffsetType) y*cache_info->columns+x;
4401 return((Quantum *) NULL);
4402 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4403 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4404 if ((MagickSizeType) offset >= number_pixels)
4405 return((Quantum *) NULL);
4411 region.width=columns;
4413 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4421 + 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 %
4425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4427 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4428 % defined by the region rectangle and returns a pointer to the region. This
4429 % region is subsequently transferred from the pixel cache with
4430 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4431 % pixels are transferred, otherwise a NULL is returned.
4433 % The format of the QueueAuthenticPixelsCache() method is:
4435 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4436 % const ssize_t y,const size_t columns,const size_t rows,
4437 % ExceptionInfo *exception)
4439 % A description of each parameter follows:
4441 % o image: the image.
4443 % o x,y,columns,rows: These values define the perimeter of a region of
4446 % o exception: return any errors or warnings in this structure.
4449 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4450 const ssize_t y,const size_t columns,const size_t rows,
4451 ExceptionInfo *exception)
4457 id = GetOpenMPThreadId();
4462 assert(image != (const Image *) NULL);
4463 assert(image->signature == MagickSignature);
4464 assert(image->cache != (Cache) NULL);
4465 cache_info=(CacheInfo *) image->cache;
4466 assert(cache_info->signature == MagickSignature);
4467 assert(id < (int) cache_info->number_threads);
4468 q=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4478 % Q u e u e A u t h e n t i c P i x e l s %
4482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4484 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4485 % successfully initialized a pointer to a Quantum array representing the
4486 % region is returned, otherwise NULL is returned. The returned pointer may
4487 % point to a temporary working buffer for the pixels or it may point to the
4488 % final location of the pixels in memory.
4490 % Write-only access means that any existing pixel values corresponding to
4491 % the region are ignored. This is useful if the initial image is being
4492 % created from scratch, or if the existing pixel values are to be
4493 % completely replaced without need to refer to their pre-existing values.
4494 % The application is free to read and write the pixel buffer returned by
4495 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4496 % initialize the pixel array values. Initializing pixel array values is the
4497 % application's responsibility.
4499 % Performance is maximized if the selected region is part of one row, or
4500 % one or more full rows, since then there is opportunity to access the
4501 % pixels in-place (without a copy) if the image is in memory, or in a
4502 % memory-mapped file. The returned pointer must *never* be deallocated
4505 % Pixels accessed via the returned pointer represent a simple array of type
4506 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4507 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4508 % obtain the meta-content (of type void) corresponding to the region.
4509 % Once the Quantum (and/or Quantum) array has been updated, the
4510 % changes must be saved back to the underlying image using
4511 % SyncAuthenticPixels() or they may be lost.
4513 % The format of the QueueAuthenticPixels() method is:
4515 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4516 % const ssize_t y,const size_t columns,const size_t rows,
4517 % ExceptionInfo *exception)
4519 % A description of each parameter follows:
4521 % o image: the image.
4523 % o x,y,columns,rows: These values define the perimeter of a region of
4526 % o exception: return any errors or warnings in this structure.
4529 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4530 const ssize_t y,const size_t columns,const size_t rows,
4531 ExceptionInfo *exception)
4537 id = GetOpenMPThreadId();
4542 assert(image != (Image *) NULL);
4543 assert(image->signature == MagickSignature);
4544 assert(image->cache != (Cache) NULL);
4545 cache_info=(CacheInfo *) image->cache;
4546 assert(cache_info->signature == MagickSignature);
4547 if (cache_info->methods.queue_authentic_pixels_handler !=
4548 (QueueAuthenticPixelsHandler) NULL)
4550 q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4551 columns,rows,exception);
4554 assert(id < (int) cache_info->number_threads);
4555 q=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4565 + 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 %
4569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4571 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4574 % The format of the ReadPixelCacheMetacontent() method is:
4576 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4577 % NexusInfo *nexus_info,ExceptionInfo *exception)
4579 % A description of each parameter follows:
4581 % o cache_info: the pixel cache.
4583 % o nexus_info: the cache nexus to read the metacontent.
4585 % o exception: return any errors or warnings in this structure.
4588 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4589 NexusInfo *nexus_info,ExceptionInfo *exception)
4602 register unsigned char
4608 if (cache_info->metacontent_extent == 0)
4609 return(MagickFalse);
4610 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4612 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4613 nexus_info->region.x;
4614 length=(MagickSizeType) nexus_info->region.width*
4615 cache_info->metacontent_extent;
4616 rows=nexus_info->region.height;
4618 q=(unsigned char *) nexus_info->metacontent;
4619 switch (cache_info->type)
4624 register unsigned char
4628 Read meta-content from memory.
4630 if ((cache_info->columns == nexus_info->region.width) &&
4631 (extent == (MagickSizeType) ((size_t) extent)))
4636 p=(unsigned char *) cache_info->metacontent+offset*
4637 cache_info->metacontent_extent;
4638 for (y=0; y < (ssize_t) rows; y++)
4640 (void) memcpy(q,p,(size_t) length);
4641 p+=cache_info->metacontent_extent*cache_info->columns;
4642 q+=cache_info->metacontent_extent*nexus_info->region.width;
4649 Read meta content from disk.
4651 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4653 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4654 cache_info->cache_filename);
4655 return(MagickFalse);
4657 if ((cache_info->columns == nexus_info->region.width) &&
4658 (extent <= MagickMaxBufferExtent))
4663 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4664 for (y=0; y < (ssize_t) rows; y++)
4666 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4667 cache_info->number_channels*sizeof(Quantum)+offset*
4668 cache_info->metacontent_extent,length,(unsigned char *) q);
4669 if ((MagickSizeType) count != length)
4671 offset+=cache_info->columns;
4672 q+=cache_info->metacontent_extent*nexus_info->region.width;
4674 if (y < (ssize_t) rows)
4676 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4677 cache_info->cache_filename);
4678 return(MagickFalse);
4685 if ((cache_info->debug != MagickFalse) &&
4686 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4687 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4688 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4689 nexus_info->region.width,(double) nexus_info->region.height,(double)
4690 nexus_info->region.x,(double) nexus_info->region.y);
4695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4699 + R e a d P i x e l C a c h e P i x e l s %
4703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4705 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4708 % The format of the ReadPixelCachePixels() method is:
4710 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4711 % NexusInfo *nexus_info,ExceptionInfo *exception)
4713 % A description of each parameter follows:
4715 % o cache_info: the pixel cache.
4717 % o nexus_info: the cache nexus to read the pixels.
4719 % o exception: return any errors or warnings in this structure.
4722 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4723 NexusInfo *nexus_info,ExceptionInfo *exception)
4742 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4744 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4745 nexus_info->region.x;
4746 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4748 rows=nexus_info->region.height;
4750 q=nexus_info->pixels;
4751 switch (cache_info->type)
4760 Read pixels from memory.
4762 if ((cache_info->columns == nexus_info->region.width) &&
4763 (extent == (MagickSizeType) ((size_t) extent)))
4768 p=cache_info->pixels+offset*cache_info->number_channels;
4769 for (y=0; y < (ssize_t) rows; y++)
4771 (void) memcpy(q,p,(size_t) length);
4772 p+=cache_info->number_channels*cache_info->columns;
4773 q+=cache_info->number_channels*nexus_info->region.width;
4780 Read pixels from disk.
4782 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4784 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4785 cache_info->cache_filename);
4786 return(MagickFalse);
4788 if ((cache_info->columns == nexus_info->region.width) &&
4789 (extent <= MagickMaxBufferExtent))
4794 for (y=0; y < (ssize_t) rows; y++)
4796 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4797 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4798 if ((MagickSizeType) count != length)
4800 offset+=cache_info->columns;
4801 q+=cache_info->number_channels*nexus_info->region.width;
4803 if (y < (ssize_t) rows)
4805 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4806 cache_info->cache_filename);
4807 return(MagickFalse);
4814 if ((cache_info->debug != MagickFalse) &&
4815 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4816 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4817 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4818 nexus_info->region.width,(double) nexus_info->region.height,(double)
4819 nexus_info->region.x,(double) nexus_info->region.y);
4824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4828 + R e f e r e n c e P i x e l C a c h e %
4832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4834 % ReferencePixelCache() increments the reference count associated with the
4835 % pixel cache returning a pointer to the cache.
4837 % The format of the ReferencePixelCache method is:
4839 % Cache ReferencePixelCache(Cache cache_info)
4841 % A description of each parameter follows:
4843 % o cache_info: the pixel cache.
4846 MagickPrivate Cache ReferencePixelCache(Cache cache)
4851 assert(cache != (Cache *) NULL);
4852 cache_info=(CacheInfo *) cache;
4853 assert(cache_info->signature == MagickSignature);
4854 LockSemaphoreInfo(cache_info->semaphore);
4855 cache_info->reference_count++;
4856 UnlockSemaphoreInfo(cache_info->semaphore);
4861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4865 + S e t P i x e l C a c h e M e t h o d s %
4869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4871 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4873 % The format of the SetPixelCacheMethods() method is:
4875 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4877 % A description of each parameter follows:
4879 % o cache: the pixel cache.
4881 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4884 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4889 GetOneAuthenticPixelFromHandler
4890 get_one_authentic_pixel_from_handler;
4892 GetOneVirtualPixelFromHandler
4893 get_one_virtual_pixel_from_handler;
4896 Set cache pixel methods.
4898 assert(cache != (Cache) NULL);
4899 assert(cache_methods != (CacheMethods *) NULL);
4900 cache_info=(CacheInfo *) cache;
4901 assert(cache_info->signature == MagickSignature);
4902 if (cache_info->debug != MagickFalse)
4903 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4904 cache_info->filename);
4905 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4906 cache_info->methods.get_virtual_pixel_handler=
4907 cache_methods->get_virtual_pixel_handler;
4908 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4909 cache_info->methods.destroy_pixel_handler=
4910 cache_methods->destroy_pixel_handler;
4911 if (cache_methods->get_virtual_metacontent_from_handler !=
4912 (GetVirtualMetacontentFromHandler) NULL)
4913 cache_info->methods.get_virtual_metacontent_from_handler=
4914 cache_methods->get_virtual_metacontent_from_handler;
4915 if (cache_methods->get_authentic_pixels_handler !=
4916 (GetAuthenticPixelsHandler) NULL)
4917 cache_info->methods.get_authentic_pixels_handler=
4918 cache_methods->get_authentic_pixels_handler;
4919 if (cache_methods->queue_authentic_pixels_handler !=
4920 (QueueAuthenticPixelsHandler) NULL)
4921 cache_info->methods.queue_authentic_pixels_handler=
4922 cache_methods->queue_authentic_pixels_handler;
4923 if (cache_methods->sync_authentic_pixels_handler !=
4924 (SyncAuthenticPixelsHandler) NULL)
4925 cache_info->methods.sync_authentic_pixels_handler=
4926 cache_methods->sync_authentic_pixels_handler;
4927 if (cache_methods->get_authentic_pixels_from_handler !=
4928 (GetAuthenticPixelsFromHandler) NULL)
4929 cache_info->methods.get_authentic_pixels_from_handler=
4930 cache_methods->get_authentic_pixels_from_handler;
4931 if (cache_methods->get_authentic_metacontent_from_handler !=
4932 (GetAuthenticMetacontentFromHandler) NULL)
4933 cache_info->methods.get_authentic_metacontent_from_handler=
4934 cache_methods->get_authentic_metacontent_from_handler;
4935 get_one_virtual_pixel_from_handler=
4936 cache_info->methods.get_one_virtual_pixel_from_handler;
4937 if (get_one_virtual_pixel_from_handler !=
4938 (GetOneVirtualPixelFromHandler) NULL)
4939 cache_info->methods.get_one_virtual_pixel_from_handler=
4940 cache_methods->get_one_virtual_pixel_from_handler;
4941 get_one_authentic_pixel_from_handler=
4942 cache_methods->get_one_authentic_pixel_from_handler;
4943 if (get_one_authentic_pixel_from_handler !=
4944 (GetOneAuthenticPixelFromHandler) NULL)
4945 cache_info->methods.get_one_authentic_pixel_from_handler=
4946 cache_methods->get_one_authentic_pixel_from_handler;
4950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4954 + S e t P i x e l C a c h e N e x u s P i x e l s %
4958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4960 % SetPixelCacheNexusPixels() defines the region of the cache for the
4961 % specified cache nexus.
4963 % The format of the SetPixelCacheNexusPixels() method is:
4965 % Quantum SetPixelCacheNexusPixels(const Image *image,
4966 % const RectangleInfo *region,NexusInfo *nexus_info,
4967 % ExceptionInfo *exception)
4969 % A description of each parameter follows:
4971 % o image: the image.
4973 % o region: A pointer to the RectangleInfo structure that defines the
4974 % region of this particular cache nexus.
4976 % o nexus_info: the cache nexus to set.
4978 % o exception: return any errors or warnings in this structure.
4982 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4983 NexusInfo *nexus_info,ExceptionInfo *exception)
4985 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4986 return(MagickFalse);
4987 nexus_info->mapped=MagickFalse;
4988 nexus_info->cache=(Quantum *) AcquireAlignedMemory(1,(size_t)
4989 nexus_info->length);
4990 if (nexus_info->cache == (Quantum *) NULL)
4992 nexus_info->mapped=MagickTrue;
4993 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4994 nexus_info->length);
4996 if (nexus_info->cache == (Quantum *) NULL)
4998 (void) ThrowMagickException(exception,GetMagickModule(),
4999 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5000 cache_info->filename);
5001 return(MagickFalse);
5006 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5007 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5019 cache_info=(CacheInfo *) image->cache;
5020 assert(cache_info->signature == MagickSignature);
5021 if (cache_info->type == UndefinedCache)
5022 return((Quantum *) NULL);
5023 nexus_info->region=(*region);
5024 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5025 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5031 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5032 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5033 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5034 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5035 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5036 ((nexus_info->region.width == cache_info->columns) ||
5037 ((nexus_info->region.width % cache_info->columns) == 0)))))
5043 Pixels are accessed directly from memory.
5045 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5046 nexus_info->region.x;
5047 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5049 nexus_info->metacontent=(void *) NULL;
5050 if (cache_info->metacontent_extent != 0)
5051 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5052 offset*cache_info->metacontent_extent;
5053 return(nexus_info->pixels);
5057 Pixels are stored in a cache region until they are synced to the cache.
5059 number_pixels=(MagickSizeType) nexus_info->region.width*
5060 nexus_info->region.height;
5061 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5062 if (cache_info->metacontent_extent != 0)
5063 length+=number_pixels*cache_info->metacontent_extent;
5064 if (nexus_info->cache == (Quantum *) NULL)
5066 nexus_info->length=length;
5067 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5068 if (status == MagickFalse)
5070 nexus_info->length=0;
5071 return((Quantum *) NULL);
5075 if (nexus_info->length != length)
5077 RelinquishCacheNexusPixels(nexus_info);
5078 nexus_info->length=length;
5079 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5080 if (status == MagickFalse)
5082 nexus_info->length=0;
5083 return((Quantum *) NULL);
5086 nexus_info->pixels=nexus_info->cache;
5087 nexus_info->metacontent=(void *) NULL;
5088 if (cache_info->metacontent_extent != 0)
5089 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5090 cache_info->number_channels);
5091 return(nexus_info->pixels);
5095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5099 % S e t P i x e l C a c h e V i r t u a l M e t h o d %
5103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5105 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5106 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5107 % access that is outside the boundaries of the image cache.
5109 % The format of the SetPixelCacheVirtualMethod() method is:
5111 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5112 % const VirtualPixelMethod virtual_pixel_method)
5114 % A description of each parameter follows:
5116 % o image: the image.
5118 % o virtual_pixel_method: choose the type of virtual pixel.
5121 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5122 const VirtualPixelMethod virtual_pixel_method)
5130 assert(image != (Image *) NULL);
5131 assert(image->signature == MagickSignature);
5132 if (image->debug != MagickFalse)
5133 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5134 assert(image->cache != (Cache) NULL);
5135 cache_info=(CacheInfo *) image->cache;
5136 assert(cache_info->signature == MagickSignature);
5137 method=cache_info->virtual_pixel_method;
5138 cache_info->virtual_pixel_method=virtual_pixel_method;
5143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5147 + S y n c A u t h e n t i c P i x e l C a c h e N e x u s %
5151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5153 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5154 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5155 % is synced, otherwise MagickFalse.
5157 % The format of the SyncAuthenticPixelCacheNexus() method is:
5159 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5160 % NexusInfo *nexus_info,ExceptionInfo *exception)
5162 % A description of each parameter follows:
5164 % o image: the image.
5166 % o nexus_info: the cache nexus to sync.
5168 % o exception: return any errors or warnings in this structure.
5171 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5172 NexusInfo *nexus_info,ExceptionInfo *exception)
5181 Transfer pixels to the cache.
5183 assert(image != (Image *) NULL);
5184 assert(image->signature == MagickSignature);
5185 if (image->cache == (Cache) NULL)
5186 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5187 cache_info=(CacheInfo *) image->cache;
5188 assert(cache_info->signature == MagickSignature);
5189 if (cache_info->type == UndefinedCache)
5190 return(MagickFalse);
5191 if ((image->clip_mask != (Image *) NULL) &&
5192 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5193 return(MagickFalse);
5194 if ((image->mask != (Image *) NULL) &&
5195 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5196 return(MagickFalse);
5197 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5199 assert(cache_info->signature == MagickSignature);
5200 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5201 if ((cache_info->metacontent_extent != 0) &&
5202 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5203 return(MagickFalse);
5208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5212 + S y n c A u t h e n t i c P i x e l C a c h e %
5216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5218 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5219 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5220 % otherwise MagickFalse.
5222 % The format of the SyncAuthenticPixelsCache() method is:
5224 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5225 % ExceptionInfo *exception)
5227 % A description of each parameter follows:
5229 % o image: the image.
5231 % o exception: return any errors or warnings in this structure.
5234 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5235 ExceptionInfo *exception)
5241 id = GetOpenMPThreadId();
5246 assert(image != (Image *) NULL);
5247 assert(image->signature == MagickSignature);
5248 assert(image->cache != (Cache) NULL);
5249 cache_info=(CacheInfo *) image->cache;
5250 assert(cache_info->signature == MagickSignature);
5251 assert(id < (int) cache_info->number_threads);
5252 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5262 % S y n c A u t h e n t i c P i x e l s %
5266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5268 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5269 % The method returns MagickTrue if the pixel region is flushed, otherwise
5272 % The format of the SyncAuthenticPixels() method is:
5274 % MagickBooleanType SyncAuthenticPixels(Image *image,
5275 % ExceptionInfo *exception)
5277 % A description of each parameter follows:
5279 % o image: the image.
5281 % o exception: return any errors or warnings in this structure.
5284 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5285 ExceptionInfo *exception)
5291 id = GetOpenMPThreadId();
5296 assert(image != (Image *) NULL);
5297 assert(image->signature == MagickSignature);
5298 assert(image->cache != (Cache) NULL);
5299 cache_info=(CacheInfo *) image->cache;
5300 assert(cache_info->signature == MagickSignature);
5301 if (cache_info->methods.sync_authentic_pixels_handler !=
5302 (SyncAuthenticPixelsHandler) NULL)
5304 status=cache_info->methods.sync_authentic_pixels_handler(image,
5308 assert(id < (int) cache_info->number_threads);
5309 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5319 % S y n c I m a g e P i x e l C a c h e %
5323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5326 % The method returns MagickTrue if the pixel region is flushed, otherwise
5329 % The format of the SyncImagePixelCache() method is:
5331 % MagickBooleanType SyncImagePixelCache(Image *image,
5332 % ExceptionInfo *exception)
5334 % A description of each parameter follows:
5336 % o image: the image.
5338 % o exception: return any errors or warnings in this structure.
5341 MagickExport MagickBooleanType SyncImagePixelCache(Image *image,
5342 ExceptionInfo *exception)
5347 assert(image != (Image *) NULL);
5348 assert(exception != (ExceptionInfo *) NULL);
5349 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5350 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5358 + W r i t e P i x e l C a c h e M e t a c o n t e n t %
5362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5364 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5365 % of the pixel cache.
5367 % The format of the WritePixelCacheMetacontent() method is:
5369 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5370 % NexusInfo *nexus_info,ExceptionInfo *exception)
5372 % A description of each parameter follows:
5374 % o cache_info: the pixel cache.
5376 % o nexus_info: the cache nexus to write the meta-content.
5378 % o exception: return any errors or warnings in this structure.
5381 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5382 NexusInfo *nexus_info,ExceptionInfo *exception)
5392 register const unsigned char
5401 if (cache_info->metacontent_extent == 0)
5402 return(MagickFalse);
5403 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5405 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5406 nexus_info->region.x;
5407 length=(MagickSizeType) nexus_info->region.width*
5408 cache_info->metacontent_extent;
5409 rows=nexus_info->region.height;
5410 extent=(MagickSizeType) length*rows;
5411 p=(unsigned char *) nexus_info->metacontent;
5412 switch (cache_info->type)
5417 register unsigned char
5421 Write associated pixels to memory.
5423 if ((cache_info->columns == nexus_info->region.width) &&
5424 (extent == (MagickSizeType) ((size_t) extent)))
5429 q=(unsigned char *) cache_info->metacontent+offset*
5430 cache_info->metacontent_extent;
5431 for (y=0; y < (ssize_t) rows; y++)
5433 (void) memcpy(q,p,(size_t) length);
5434 p+=nexus_info->region.width*cache_info->metacontent_extent;
5435 q+=cache_info->columns*cache_info->metacontent_extent;
5442 Write associated pixels to disk.
5444 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5446 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5447 cache_info->cache_filename);
5448 return(MagickFalse);
5450 if ((cache_info->columns == nexus_info->region.width) &&
5451 (extent <= MagickMaxBufferExtent))
5456 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5457 for (y=0; y < (ssize_t) rows; y++)
5459 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5460 cache_info->number_channels*sizeof(Quantum)+offset*
5461 cache_info->metacontent_extent,length,(const unsigned char *) p);
5462 if ((MagickSizeType) count != length)
5464 p+=nexus_info->region.width*cache_info->metacontent_extent;
5465 offset+=cache_info->columns;
5467 if (y < (ssize_t) rows)
5469 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5470 cache_info->cache_filename);
5471 return(MagickFalse);
5478 if ((cache_info->debug != MagickFalse) &&
5479 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5480 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5481 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5482 nexus_info->region.width,(double) nexus_info->region.height,(double)
5483 nexus_info->region.x,(double) nexus_info->region.y);
5488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5492 + W r i t e C a c h e P i x e l s %
5496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5498 % WritePixelCachePixels() writes image pixels to the specified region of the
5501 % The format of the WritePixelCachePixels() method is:
5503 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5504 % NexusInfo *nexus_info,ExceptionInfo *exception)
5506 % A description of each parameter follows:
5508 % o cache_info: the pixel cache.
5510 % o nexus_info: the cache nexus to write the pixels.
5512 % o exception: return any errors or warnings in this structure.
5515 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5516 NexusInfo *nexus_info,ExceptionInfo *exception)
5526 register const Quantum
5535 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5537 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5538 nexus_info->region.x;
5539 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5541 rows=nexus_info->region.height;
5543 p=nexus_info->pixels;
5544 switch (cache_info->type)
5553 Write pixels to memory.
5555 if ((cache_info->columns == nexus_info->region.width) &&
5556 (extent == (MagickSizeType) ((size_t) extent)))
5561 q=cache_info->pixels+offset*cache_info->number_channels;
5562 for (y=0; y < (ssize_t) rows; y++)
5564 (void) memcpy(q,p,(size_t) length);
5565 p+=nexus_info->region.width*cache_info->number_channels;
5566 q+=cache_info->columns*cache_info->number_channels;
5573 Write pixels to disk.
5575 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5577 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5578 cache_info->cache_filename);
5579 return(MagickFalse);
5581 if ((cache_info->columns == nexus_info->region.width) &&
5582 (extent <= MagickMaxBufferExtent))
5587 for (y=0; y < (ssize_t) rows; y++)
5589 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5590 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5592 if ((MagickSizeType) count != length)
5594 p+=nexus_info->region.width*cache_info->number_channels;
5595 offset+=cache_info->columns;
5597 if (y < (ssize_t) rows)
5599 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5600 cache_info->cache_filename);
5601 return(MagickFalse);
5608 if ((cache_info->debug != MagickFalse) &&
5609 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5610 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5611 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5612 nexus_info->region.width,(double) nexus_info->region.height,(double)
5613 nexus_info->region.x,(double) nexus_info->region.y);