2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % CCCC AAA CCCC H H EEEEE %
8 % C AAAAA C HHHHH EEE %
10 % CCCC A A CCCC H H EEEEE %
13 % MagickCore Pixel Cache Methods %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/geometry.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/log.h"
55 #include "MagickCore/magick.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/pixel.h"
58 #include "MagickCore/pixel-accessor.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/quantum.h"
61 #include "MagickCore/random_.h"
62 #include "MagickCore/resource_.h"
63 #include "MagickCore/semaphore.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/string-private.h"
67 #include "MagickCore/thread-private.h"
68 #include "MagickCore/utility.h"
69 #if defined(MAGICKCORE_ZLIB_DELEGATE)
76 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
81 typedef struct _MagickModulo
111 Forward declarations.
113 #if defined(__cplusplus) || defined(c_plusplus)
118 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
119 const ssize_t,const size_t,const size_t,ExceptionInfo *),
120 *GetVirtualPixelsCache(const Image *);
123 *GetVirtualMetacontentFromCache(const Image *);
125 static MagickBooleanType
126 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
127 PixelPacket *,ExceptionInfo *),
128 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
129 const ssize_t,const ssize_t,PixelPacket *,ExceptionInfo *),
130 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
131 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
132 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
133 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
134 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
135 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
138 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
139 const size_t,ExceptionInfo *),
140 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
141 const size_t,ExceptionInfo *),
142 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
145 #if defined(__cplusplus) || defined(c_plusplus)
152 static volatile MagickBooleanType
153 instantiate_cache = MagickFalse;
156 *cache_semaphore = (SemaphoreInfo *) NULL;
159 *cache_resources = (SplayTreeInfo *) NULL;
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 + A c q u i r e P i x e l C a c h e %
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % AcquirePixelCache() acquires a pixel cache.
174 % The format of the AcquirePixelCache() method is:
176 % Cache AcquirePixelCache(const size_t number_threads)
178 % A description of each parameter follows:
180 % o number_threads: the number of nexus threads.
183 MagickExport Cache AcquirePixelCache(const size_t number_threads)
188 cache_info=(CacheInfo *) 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 MagickExport 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 MagickExport MagickBooleanType CacheComponentGenesis(void)
340 AcquireSemaphoreInfo(&cache_semaphore);
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 + C a c h e C o m p o n e n t T e r m i n u s %
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 % CacheComponentTerminus() destroys the cache component.
357 % The format of the CacheComponentTerminus() method is:
359 % CacheComponentTerminus(void)
362 MagickExport void CacheComponentTerminus(void)
364 if (cache_semaphore == (SemaphoreInfo *) NULL)
365 AcquireSemaphoreInfo(&cache_semaphore);
366 LockSemaphoreInfo(cache_semaphore);
367 if (cache_resources != (SplayTreeInfo *) NULL)
368 cache_resources=DestroySplayTree(cache_resources);
369 instantiate_cache=MagickFalse;
370 UnlockSemaphoreInfo(cache_semaphore);
371 DestroySemaphoreInfo(&cache_semaphore);
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 + C l i p P i x e l C a c h e N e x u s %
383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
386 % mask. It returns MagickTrue if the pixel region is clipped, otherwise
389 % The format of the ClipPixelCacheNexus() method is:
391 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
392 % ExceptionInfo *exception)
394 % A description of each parameter follows:
396 % o image: the image.
398 % o nexus_info: the cache nexus to clip.
400 % o exception: return any errors or warnings in this structure.
403 static MagickBooleanType ClipPixelCacheNexus(Image *image,
404 NexusInfo *nexus_info,ExceptionInfo *exception)
416 register const Quantum
429 if (image->debug != MagickFalse)
430 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
431 if (image->clip_mask == (Image *) NULL)
433 cache_info=(CacheInfo *) image->cache;
434 if (cache_info == (Cache) NULL)
436 image_nexus=AcquirePixelCacheNexus(1);
437 clip_nexus=AcquirePixelCacheNexus(1);
438 if ((image_nexus == (NexusInfo **) NULL) ||
439 (clip_nexus == (NexusInfo **) NULL))
440 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
441 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
442 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
443 nexus_info->region.height,image_nexus[0],exception);
444 q=nexus_info->pixels;
445 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
446 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
447 nexus_info->region.height,clip_nexus[0],exception);
448 number_pixels=(MagickSizeType) nexus_info->region.width*
449 nexus_info->region.height;
450 for (i=0; i < (ssize_t) number_pixels; i++)
452 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
454 if (GetPixelIntensity(image,r) > ((Quantum) QuantumRange/2))
456 SetPixelRed(image,GetPixelRed(image,p),q);
457 SetPixelGreen(image,GetPixelGreen(image,p),q);
458 SetPixelBlue(image,GetPixelBlue(image,p),q);
459 if (cache_info->colorspace == CMYKColorspace)
460 SetPixelBlack(image,GetPixelBlack(image,p),q);
461 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
463 p+=GetPixelChannels(image);
464 q+=GetPixelChannels(image);
465 r+=GetPixelChannels(image->clip_mask);
467 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
468 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
469 if (i < (ssize_t) number_pixels)
475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479 + C l o n e P i x e l C a c h e %
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 % ClonePixelCache() clones a pixel cache.
487 % The format of the ClonePixelCache() method is:
489 % Cache ClonePixelCache(const Cache cache)
491 % A description of each parameter follows:
493 % o cache: the pixel cache.
496 MagickExport Cache ClonePixelCache(const Cache cache)
504 assert(cache != (const Cache) NULL);
505 cache_info=(const CacheInfo *) cache;
506 assert(cache_info->signature == MagickSignature);
507 if (cache_info->debug != MagickFalse)
508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
509 cache_info->filename);
510 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
511 if (clone_info == (Cache) NULL)
512 return((Cache) NULL);
513 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
514 return((Cache ) clone_info);
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 + C l o n e P i x e l C a c h e P i x e l s %
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
527 % ClonePixelCachePixels() clones the source pixel cache to the destination
530 % The format of the ClonePixelCachePixels() method is:
532 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
533 % CacheInfo *source_info,ExceptionInfo *exception)
535 % A description of each parameter follows:
537 % o cache_info: the pixel cache.
539 % o source_info: the source pixel cache.
541 % o exception: return any errors or warnings in this structure.
545 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
551 LockSemaphoreInfo(cache_info->disk_semaphore);
552 if (cache_info->file != -1)
554 status=close(cache_info->file);
555 cache_info->file=(-1);
556 RelinquishMagickResource(FileResource,1);
558 UnlockSemaphoreInfo(cache_info->disk_semaphore);
559 return(status == -1 ? MagickFalse : MagickTrue);
562 static void LimitPixelCacheDescriptors(void)
569 Limit # of open file descriptors.
571 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
573 LockSemaphoreInfo(cache_semaphore);
574 if (cache_resources == (SplayTreeInfo *) NULL)
576 UnlockSemaphoreInfo(cache_semaphore);
579 ResetSplayTreeIterator(cache_resources);
580 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
581 while (p != (CacheInfo *) NULL)
583 if ((p->type == DiskCache) && (p->file != -1))
585 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
587 for (q=p; p != (CacheInfo *) NULL; )
589 if ((p->type == DiskCache) && (p->file != -1) &&
590 (p->timestamp < q->timestamp))
592 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
594 if (q != (CacheInfo *) NULL)
597 Close least recently used cache.
599 (void) close(q->file);
602 UnlockSemaphoreInfo(cache_semaphore);
605 static inline MagickSizeType MagickMax(const MagickSizeType x,
606 const MagickSizeType y)
613 static inline MagickSizeType MagickMin(const MagickSizeType x,
614 const MagickSizeType y)
621 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
628 Open pixel cache on disk.
630 LockSemaphoreInfo(cache_info->disk_semaphore);
631 if (cache_info->file != -1)
633 UnlockSemaphoreInfo(cache_info->disk_semaphore);
634 return(MagickTrue); /* cache already open */
636 LimitPixelCacheDescriptors();
637 if (*cache_info->cache_filename == '\0')
638 file=AcquireUniqueFileResource(cache_info->cache_filename);
644 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
649 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
652 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
658 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
661 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
667 UnlockSemaphoreInfo(cache_info->disk_semaphore);
670 (void) AcquireMagickResource(FileResource,1);
671 cache_info->file=file;
672 cache_info->timestamp=time(0);
673 UnlockSemaphoreInfo(cache_info->disk_semaphore);
677 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
678 const MagickOffsetType offset,const MagickSizeType length,
679 unsigned char *restrict buffer)
681 register MagickOffsetType
687 cache_info->timestamp=time(0);
688 #if !defined(MAGICKCORE_HAVE_PREAD)
689 LockSemaphoreInfo(cache_info->disk_semaphore);
690 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
692 UnlockSemaphoreInfo(cache_info->disk_semaphore);
693 return((MagickOffsetType) -1);
697 for (i=0; i < (MagickOffsetType) length; i+=count)
699 #if !defined(MAGICKCORE_HAVE_PREAD)
700 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
701 (MagickSizeType) SSIZE_MAX));
703 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
704 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
715 #if !defined(MAGICKCORE_HAVE_PREAD)
716 UnlockSemaphoreInfo(cache_info->disk_semaphore);
721 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
722 const MagickOffsetType offset,const MagickSizeType length,
723 const unsigned char *restrict buffer)
725 register MagickOffsetType
731 cache_info->timestamp=time(0);
732 #if !defined(MAGICKCORE_HAVE_PWRITE)
733 LockSemaphoreInfo(cache_info->disk_semaphore);
734 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
736 UnlockSemaphoreInfo(cache_info->disk_semaphore);
737 return((MagickOffsetType) -1);
741 for (i=0; i < (MagickOffsetType) length; i+=count)
743 #if !defined(MAGICKCORE_HAVE_PWRITE)
744 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
745 (MagickSizeType) SSIZE_MAX));
747 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
748 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
759 #if !defined(MAGICKCORE_HAVE_PWRITE)
760 UnlockSemaphoreInfo(cache_info->disk_semaphore);
765 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
766 CacheInfo *cache_info,ExceptionInfo *exception)
771 register MagickOffsetType
781 Clone pixel cache (both caches on disk).
783 if (cache_info->debug != MagickFalse)
784 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
785 blob=(unsigned char *) 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 MagickExport 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 MagickExport 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 MagickExport 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 MagickExport 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 pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1659 if (pixels == (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 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1826 assert(id < (int) cache_info->number_threads);
1827 pixels=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 pixels=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 (1 && image->colorspace == GRAYColorspace)
2083 image->colorspace=RGBColorspace;
2084 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2085 status=OpenPixelCache(image,IOMode,exception);
2087 UnlockSemaphoreInfo(image->semaphore);
2088 if (status == MagickFalse)
2089 return((Cache) NULL);
2090 return(image->cache);
2094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2098 % G e t O n e A u t h e n t i c P i x e l %
2102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2104 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2105 % location. The image background color is returned if an error occurs.
2107 % The format of the GetOneAuthenticPixel() method is:
2109 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2110 % const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2112 % A description of each parameter follows:
2114 % o image: the image.
2116 % o x,y: These values define the location of the pixel to return.
2118 % o pixel: return a pixel at the specified (x,y) location.
2120 % o exception: return any errors or warnings in this structure.
2123 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2124 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2132 assert(image != (Image *) NULL);
2133 assert(image->signature == MagickSignature);
2134 assert(image->cache != (Cache) NULL);
2135 cache_info=(CacheInfo *) image->cache;
2136 assert(cache_info->signature == MagickSignature);
2137 *pixel=image->background_color;
2138 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2139 (GetOneAuthenticPixelFromHandler) NULL)
2140 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2142 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2143 if (q == (Quantum *) NULL)
2144 return(MagickFalse);
2145 GetPixelPacket(image,q,pixel);
2150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2154 + 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 %
2158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2160 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2161 % location. The image background color is returned if an error occurs.
2163 % The format of the GetOneAuthenticPixelFromCache() method is:
2165 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2166 % const ssize_t x,const ssize_t y,PixelPacket *pixel,
2167 % ExceptionInfo *exception)
2169 % A description of each parameter follows:
2171 % o image: the image.
2173 % o x,y: These values define the location of the pixel to return.
2175 % o pixel: return a pixel at the specified (x,y) location.
2177 % o exception: return any errors or warnings in this structure.
2180 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2181 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2187 id = GetOpenMPThreadId();
2192 assert(image != (const Image *) NULL);
2193 assert(image->signature == MagickSignature);
2194 assert(image->cache != (Cache) NULL);
2195 cache_info=(CacheInfo *) image->cache;
2196 assert(cache_info->signature == MagickSignature);
2197 assert(id < (int) cache_info->number_threads);
2198 *pixel=image->background_color;
2199 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2201 if (q == (Quantum *) NULL)
2202 return(MagickFalse);
2203 GetPixelPacket(image,q,pixel);
2208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2212 % G e t O n e V i r t u a l M a g i c k P i x e l %
2216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2218 % GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2219 % location. The image background color is returned if an error occurs. If
2220 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2222 % The format of the GetOneVirtualMagickPixel() method is:
2224 % MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2225 % const ssize_t x,const ssize_t y,PixelInfo *pixel,
2226 % ExceptionInfo exception)
2228 % A description of each parameter follows:
2230 % o image: the image.
2232 % o x,y: these values define the location of the pixel to return.
2234 % o pixel: return a pixel at the specified (x,y) location.
2236 % o exception: return any errors or warnings in this structure.
2239 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2240 const ssize_t x,const ssize_t y,PixelInfo *pixel,
2241 ExceptionInfo *exception)
2247 id = GetOpenMPThreadId();
2249 register const Quantum
2252 assert(image != (const Image *) NULL);
2253 assert(image->signature == MagickSignature);
2254 assert(image->cache != (Cache) NULL);
2255 cache_info=(CacheInfo *) image->cache;
2256 assert(cache_info->signature == MagickSignature);
2257 assert(id < (int) cache_info->number_threads);
2258 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2259 1UL,1UL,cache_info->nexus_info[id],exception);
2260 GetPixelInfo(image,pixel);
2261 if (pixels == (const Quantum *) NULL)
2262 return(MagickFalse);
2263 SetPixelInfo(image,pixels,pixel);
2268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2272 % G e t O n e V i r t u a l M e t h o d P i x e l %
2276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278 % GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2279 % location as defined by specified pixel method. The image background color
2280 % is returned if an error occurs. If you plan to modify the pixel, use
2281 % GetOneAuthenticPixel() instead.
2283 % The format of the GetOneVirtualMethodPixel() method is:
2285 % MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2286 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2287 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2289 % A description of each parameter follows:
2291 % o image: the image.
2293 % o virtual_pixel_method: the virtual pixel method.
2295 % o x,y: These values define the location of the pixel to return.
2297 % o pixel: return a pixel at the specified (x,y) location.
2299 % o exception: return any errors or warnings in this structure.
2302 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2303 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2304 PixelPacket *pixel,ExceptionInfo *exception)
2310 id = GetOpenMPThreadId();
2315 assert(image != (const Image *) NULL);
2316 assert(image->signature == MagickSignature);
2317 assert(image->cache != (Cache) NULL);
2318 cache_info=(CacheInfo *) image->cache;
2319 assert(cache_info->signature == MagickSignature);
2320 *pixel=image->background_color;
2321 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2322 (GetOneVirtualPixelFromHandler) NULL)
2323 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2324 virtual_pixel_method,x,y,pixel,exception));
2325 assert(id < (int) cache_info->number_threads);
2326 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2327 cache_info->nexus_info[id],exception);
2328 if (p == (const Quantum *) NULL)
2329 return(MagickFalse);
2330 GetPixelPacket(image,p,pixel);
2331 if (image->colorspace == CMYKColorspace)
2332 pixel->black=GetPixelBlack(image,p);
2337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2341 % G e t O n e V i r t u a l P i x e l %
2345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2347 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2348 % (x,y) location. The image background color is returned if an error occurs.
2349 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2351 % The format of the GetOneVirtualPixel() method is:
2353 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2354 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2356 % A description of each parameter follows:
2358 % o image: the image.
2360 % o x,y: These values define the location of the pixel to return.
2362 % o pixel: return a pixel at the specified (x,y) location.
2364 % o exception: return any errors or warnings in this structure.
2367 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2368 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2374 id = GetOpenMPThreadId();
2379 assert(image != (const Image *) NULL);
2380 assert(image->signature == MagickSignature);
2381 assert(image->cache != (Cache) NULL);
2382 cache_info=(CacheInfo *) image->cache;
2383 assert(cache_info->signature == MagickSignature);
2384 *pixel=image->background_color;
2385 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2386 (GetOneVirtualPixelFromHandler) NULL)
2387 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2388 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2389 assert(id < (int) cache_info->number_threads);
2390 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2391 1UL,1UL,cache_info->nexus_info[id],exception);
2392 if (p == (const Quantum *) NULL)
2393 return(MagickFalse);
2394 GetPixelPacket(image,p,pixel);
2395 if (image->colorspace == CMYKColorspace)
2396 pixel->black=GetPixelBlack(image,p);
2401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2405 + 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 %
2409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2411 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2412 % specified (x,y) location. The image background color is returned if an
2415 % The format of the GetOneVirtualPixelFromCache() method is:
2417 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2418 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2419 % PixelPacket *pixel,ExceptionInfo *exception)
2421 % A description of each parameter follows:
2423 % o image: the image.
2425 % o virtual_pixel_method: the virtual pixel method.
2427 % o x,y: These values define the location of the pixel to return.
2429 % o pixel: return a pixel at the specified (x,y) location.
2431 % o exception: return any errors or warnings in this structure.
2434 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2435 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2436 PixelPacket *pixel,ExceptionInfo *exception)
2442 id = GetOpenMPThreadId();
2447 assert(image != (const Image *) NULL);
2448 assert(image->signature == MagickSignature);
2449 assert(image->cache != (Cache) NULL);
2450 cache_info=(CacheInfo *) image->cache;
2451 assert(cache_info->signature == MagickSignature);
2452 assert(id < (int) cache_info->number_threads);
2453 *pixel=image->background_color;
2454 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2455 cache_info->nexus_info[id],exception);
2456 if (p == (const Quantum *) NULL)
2457 return(MagickFalse);
2458 GetPixelPacket(image,p,pixel);
2459 if (image->colorspace == CMYKColorspace)
2460 pixel->black=GetPixelBlack(image,p);
2465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2469 + G e t P i x e l C a c h e C o l o r s p a c e %
2473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2475 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2477 % The format of the GetPixelCacheColorspace() method is:
2479 % Colorspace GetPixelCacheColorspace(Cache cache)
2481 % A description of each parameter follows:
2483 % o cache: the pixel cache.
2486 MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
2491 assert(cache != (Cache) NULL);
2492 cache_info=(CacheInfo *) cache;
2493 assert(cache_info->signature == MagickSignature);
2494 if (cache_info->debug != MagickFalse)
2495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2496 cache_info->filename);
2497 return(cache_info->colorspace);
2501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2505 + G e t P i x e l C a c h e M e t h o d s %
2509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2511 % GetPixelCacheMethods() initializes the CacheMethods structure.
2513 % The format of the GetPixelCacheMethods() method is:
2515 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2517 % A description of each parameter follows:
2519 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2522 MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
2524 assert(cache_methods != (CacheMethods *) NULL);
2525 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2526 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2527 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2528 cache_methods->get_virtual_metacontent_from_handler=
2529 GetVirtualMetacontentFromCache;
2530 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2531 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2532 cache_methods->get_authentic_metacontent_from_handler=
2533 GetAuthenticMetacontentFromCache;
2534 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2535 cache_methods->get_one_authentic_pixel_from_handler=
2536 GetOneAuthenticPixelFromCache;
2537 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2538 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2539 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2547 + G e t P i x e l C a c h e N e x u s E x t e n t %
2551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2553 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2554 % corresponding with the last call to SetPixelCacheNexusPixels() or
2555 % GetPixelCacheNexusPixels().
2557 % The format of the GetPixelCacheNexusExtent() method is:
2559 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2560 % NexusInfo *nexus_info)
2562 % A description of each parameter follows:
2564 % o nexus_info: the nexus info.
2567 MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2568 NexusInfo *nexus_info)
2576 assert(cache != (const Cache) NULL);
2577 cache_info=(CacheInfo *) cache;
2578 assert(cache_info->signature == MagickSignature);
2579 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2581 return((MagickSizeType) cache_info->columns*cache_info->rows);
2586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2590 + 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 %
2594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2596 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2599 % The format of the GetPixelCacheNexusMetacontent() method is:
2601 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2602 % NexusInfo *nexus_info)
2604 % A description of each parameter follows:
2606 % o cache: the pixel cache.
2608 % o nexus_info: the cache nexus to return the meta-content.
2611 MagickExport void *GetPixelCacheNexusMetacontent(const Cache cache,
2612 NexusInfo *nexus_info)
2617 assert(cache != (const Cache) NULL);
2618 cache_info=(CacheInfo *) cache;
2619 assert(cache_info->signature == MagickSignature);
2620 if (cache_info->storage_class == UndefinedClass)
2621 return((void *) NULL);
2622 return(nexus_info->metacontent);
2626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2630 + G e t P i x e l C a c h e N e x u s P i x e l s %
2634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2639 % The format of the GetPixelCacheNexusPixels() method is:
2641 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2642 % NexusInfo *nexus_info)
2644 % A description of each parameter follows:
2646 % o cache: the pixel cache.
2648 % o nexus_info: the cache nexus to return the pixels.
2651 MagickExport Quantum *GetPixelCacheNexusPixels(const Cache cache,
2652 NexusInfo *nexus_info)
2657 assert(cache != (const Cache) NULL);
2658 cache_info=(CacheInfo *) cache;
2659 assert(cache_info->signature == MagickSignature);
2660 if (cache_info->storage_class == UndefinedClass)
2661 return((Quantum *) NULL);
2662 return(nexus_info->pixels);
2666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2670 + G e t P i x e l C a c h e P i x e l s %
2674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2676 % GetPixelCachePixels() returns the pixels associated with the specified image.
2678 % The format of the GetPixelCachePixels() method is:
2680 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2681 % ExceptionInfo *exception)
2683 % A description of each parameter follows:
2685 % o image: the image.
2687 % o length: the pixel cache length.
2689 % o exception: return any errors or warnings in this structure.
2692 MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2693 ExceptionInfo *exception)
2698 assert(image != (const Image *) NULL);
2699 assert(image->signature == MagickSignature);
2700 assert(image->cache != (Cache) NULL);
2701 assert(length != (MagickSizeType *) NULL);
2702 assert(exception != (ExceptionInfo *) NULL);
2703 assert(exception->signature == MagickSignature);
2704 cache_info=(CacheInfo *) image->cache;
2705 assert(cache_info->signature == MagickSignature);
2707 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2708 return((void *) NULL);
2709 *length=cache_info->length;
2710 return((void *) cache_info->pixels);
2714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2718 + 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 %
2722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2724 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2726 % The format of the GetPixelCacheStorageClass() method is:
2728 % ClassType GetPixelCacheStorageClass(Cache cache)
2730 % A description of each parameter follows:
2732 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2734 % o cache: the pixel cache.
2737 MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
2742 assert(cache != (Cache) NULL);
2743 cache_info=(CacheInfo *) cache;
2744 assert(cache_info->signature == MagickSignature);
2745 if (cache_info->debug != MagickFalse)
2746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2747 cache_info->filename);
2748 return(cache_info->storage_class);
2752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2756 + G e t P i x e l C a c h e T i l e S i z e %
2760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2762 % GetPixelCacheTileSize() returns the pixel cache tile size.
2764 % The format of the GetPixelCacheTileSize() method is:
2766 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2769 % A description of each parameter follows:
2771 % o image: the image.
2773 % o width: the optimize cache tile width in pixels.
2775 % o height: the optimize cache tile height in pixels.
2778 MagickExport void GetPixelCacheTileSize(const Image *image,size_t *width,
2784 assert(image != (Image *) NULL);
2785 assert(image->signature == MagickSignature);
2786 if (image->debug != MagickFalse)
2787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2788 cache_info=(CacheInfo *) image->cache;
2789 assert(cache_info->signature == MagickSignature);
2790 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2791 if (GetPixelCacheType(image) == DiskCache)
2792 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2801 + G e t P i x e l C a c h e T y p e %
2805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2807 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2809 % The format of the GetPixelCacheType() method is:
2811 % CacheType GetPixelCacheType(const Image *image)
2813 % A description of each parameter follows:
2815 % o image: the image.
2818 MagickExport CacheType GetPixelCacheType(const Image *image)
2823 assert(image != (Image *) NULL);
2824 assert(image->signature == MagickSignature);
2825 assert(image->cache != (Cache) NULL);
2826 cache_info=(CacheInfo *) image->cache;
2827 assert(cache_info->signature == MagickSignature);
2828 return(cache_info->type);
2832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2836 + 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 %
2840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2842 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2843 % pixel cache. A virtual pixel is any pixel access that is outside the
2844 % boundaries of the image cache.
2846 % The format of the GetPixelCacheVirtualMethod() method is:
2848 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2850 % A description of each parameter follows:
2852 % o image: the image.
2855 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2860 assert(image != (Image *) NULL);
2861 assert(image->signature == MagickSignature);
2862 assert(image->cache != (Cache) NULL);
2863 cache_info=(CacheInfo *) image->cache;
2864 assert(cache_info->signature == MagickSignature);
2865 return(cache_info->virtual_pixel_method);
2869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2873 + 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 %
2877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2879 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2880 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2882 % The format of the GetVirtualMetacontentFromCache() method is:
2884 % void *GetVirtualMetacontentFromCache(const Image *image)
2886 % A description of each parameter follows:
2888 % o image: the image.
2891 static const void *GetVirtualMetacontentFromCache(const Image *image)
2897 id = GetOpenMPThreadId();
2902 assert(image != (const Image *) NULL);
2903 assert(image->signature == MagickSignature);
2904 assert(image->cache != (Cache) NULL);
2905 cache_info=(CacheInfo *) image->cache;
2906 assert(cache_info->signature == MagickSignature);
2907 assert(id < (int) cache_info->number_threads);
2908 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2909 cache_info->nexus_info[id]);
2910 return(metacontent);
2914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2918 + 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 %
2922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2924 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2927 % The format of the GetVirtualMetacontentFromNexus() method is:
2929 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2930 % NexusInfo *nexus_info)
2932 % A description of each parameter follows:
2934 % o cache: the pixel cache.
2936 % o nexus_info: the cache nexus to return the meta-content.
2939 MagickExport const void *GetVirtualMetacontentFromNexus(const Cache cache,
2940 NexusInfo *nexus_info)
2945 assert(cache != (Cache) NULL);
2946 cache_info=(CacheInfo *) cache;
2947 assert(cache_info->signature == MagickSignature);
2948 if (cache_info->storage_class == UndefinedClass)
2949 return((void *) NULL);
2950 return(nexus_info->metacontent);
2954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2958 % G e t V i r t u a l M e t a c o n t e n t %
2962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2964 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2965 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2966 % returned if the meta-content are not available.
2968 % The format of the GetVirtualMetacontent() method is:
2970 % const void *GetVirtualMetacontent(const Image *image)
2972 % A description of each parameter follows:
2974 % o image: the image.
2977 MagickExport const void *GetVirtualMetacontent(const Image *image)
2983 id = GetOpenMPThreadId();
2988 assert(image != (const Image *) NULL);
2989 assert(image->signature == MagickSignature);
2990 assert(image->cache != (Cache) NULL);
2991 cache_info=(CacheInfo *) image->cache;
2992 assert(cache_info->signature == MagickSignature);
2993 if (cache_info->methods.get_virtual_metacontent_from_handler !=
2994 (GetVirtualMetacontentFromHandler) NULL)
2996 metacontent=cache_info->methods.
2997 get_virtual_metacontent_from_handler(image);
2998 return(metacontent);
3000 assert(id < (int) cache_info->number_threads);
3001 metacontent=GetVirtualMetacontentFromNexus(cache_info,
3002 cache_info->nexus_info[id]);
3003 return(metacontent);
3007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3011 + 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 %
3015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3017 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3018 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3019 % is returned if the pixels are transferred, otherwise a NULL is returned.
3021 % The format of the GetVirtualPixelsFromNexus() method is:
3023 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
3024 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3025 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3026 % ExceptionInfo *exception)
3028 % A description of each parameter follows:
3030 % o image: the image.
3032 % o virtual_pixel_method: the virtual pixel method.
3034 % o x,y,columns,rows: These values define the perimeter of a region of
3037 % o nexus_info: the cache nexus to acquire.
3039 % o exception: return any errors or warnings in this structure.
3046 0, 48, 12, 60, 3, 51, 15, 63,
3047 32, 16, 44, 28, 35, 19, 47, 31,
3048 8, 56, 4, 52, 11, 59, 7, 55,
3049 40, 24, 36, 20, 43, 27, 39, 23,
3050 2, 50, 14, 62, 1, 49, 13, 61,
3051 34, 18, 46, 30, 33, 17, 45, 29,
3052 10, 58, 6, 54, 9, 57, 5, 53,
3053 42, 26, 38, 22, 41, 25, 37, 21
3056 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3061 index=x+DitherMatrix[x & 0x07]-32L;
3064 if (index >= (ssize_t) columns)
3065 return((ssize_t) columns-1L);
3069 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3074 index=y+DitherMatrix[y & 0x07]-32L;
3077 if (index >= (ssize_t) rows)
3078 return((ssize_t) rows-1L);
3082 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3086 if (x >= (ssize_t) columns)
3087 return((ssize_t) (columns-1));
3091 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3095 if (y >= (ssize_t) rows)
3096 return((ssize_t) (rows-1));
3100 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3102 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3105 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3107 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3110 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3111 const size_t extent)
3117 Compute the remainder of dividing offset by extent. It returns not only
3118 the quotient (tile the offset falls in) but also the positive remainer
3119 within that tile such that 0 <= remainder < extent. This method is
3120 essentially a ldiv() using a floored modulo division rather than the
3121 normal default truncated modulo division.
3123 modulo.quotient=offset/(ssize_t) extent;
3126 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3130 MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3131 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3132 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3133 ExceptionInfo *exception)
3150 virtual_pixel[MaxPixelChannels];
3155 register const Quantum
3168 register unsigned char
3175 *virtual_metacontent;
3180 assert(image != (const Image *) NULL);
3181 assert(image->signature == MagickSignature);
3182 assert(image->cache != (Cache) NULL);
3183 cache_info=(CacheInfo *) image->cache;
3184 assert(cache_info->signature == MagickSignature);
3185 if (cache_info->type == UndefinedCache)
3186 return((const Quantum *) NULL);
3189 region.width=columns;
3191 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3192 if (pixels == (Quantum *) NULL)
3193 return((const Quantum *) NULL);
3194 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3195 nexus_info->region.x;
3196 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3197 nexus_info->region.width-1L;
3198 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3199 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3200 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3201 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3207 Pixel request is inside cache extents.
3209 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3211 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3212 if (status == MagickFalse)
3213 return((const Quantum *) NULL);
3214 if (cache_info->metacontent_extent != 0)
3216 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3217 if (status == MagickFalse)
3218 return((const Quantum *) NULL);
3223 Pixel request is outside cache extents.
3226 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3227 virtual_nexus=AcquirePixelCacheNexus(1);
3228 if (virtual_nexus == (NexusInfo **) NULL)
3230 if (virtual_nexus != (NexusInfo **) NULL)
3231 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3232 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3233 "UnableToGetCacheNexus","`%s'",image->filename);
3234 return((const Quantum *) NULL);
3236 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3237 sizeof(*virtual_pixel));
3238 virtual_metacontent=(void *) NULL;
3239 switch (virtual_pixel_method)
3241 case BackgroundVirtualPixelMethod:
3242 case BlackVirtualPixelMethod:
3243 case GrayVirtualPixelMethod:
3244 case TransparentVirtualPixelMethod:
3245 case MaskVirtualPixelMethod:
3246 case WhiteVirtualPixelMethod:
3247 case EdgeVirtualPixelMethod:
3248 case CheckerTileVirtualPixelMethod:
3249 case HorizontalTileVirtualPixelMethod:
3250 case VerticalTileVirtualPixelMethod:
3252 if (cache_info->metacontent_extent != 0)
3255 Acquire a metacontent buffer.
3257 virtual_metacontent=(void *) AcquireAlignedMemory(1,
3258 cache_info->metacontent_extent);
3259 if (virtual_metacontent == (void *) NULL)
3261 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3262 (void) ThrowMagickException(exception,GetMagickModule(),
3263 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3264 return((const Quantum *) NULL);
3266 (void) ResetMagickMemory(virtual_metacontent,0,
3267 cache_info->metacontent_extent);
3269 switch (virtual_pixel_method)
3271 case BlackVirtualPixelMethod:
3273 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3274 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3275 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3278 case GrayVirtualPixelMethod:
3280 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3281 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
3283 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3286 case TransparentVirtualPixelMethod:
3288 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3289 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3290 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3293 case MaskVirtualPixelMethod:
3294 case WhiteVirtualPixelMethod:
3296 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3297 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3298 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3303 SetPixelRed(image,image->background_color.red,virtual_pixel);
3304 SetPixelGreen(image,image->background_color.green,virtual_pixel);
3305 SetPixelBlue(image,image->background_color.blue,virtual_pixel);
3306 if (image->colorspace == CMYKColorspace)
3307 SetPixelBlack(image,image->background_color.black,virtual_pixel);
3308 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3317 for (v=0; v < (ssize_t) rows; v++)
3319 for (u=0; u < (ssize_t) columns; u+=length)
3321 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3322 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3323 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3331 Transfer a single pixel.
3333 length=(MagickSizeType) 1;
3334 switch (virtual_pixel_method)
3338 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3339 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3340 1UL,1UL,*virtual_nexus,exception);
3341 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3344 case RandomVirtualPixelMethod:
3346 if (cache_info->random_info == (RandomInfo *) NULL)
3347 cache_info->random_info=AcquireRandomInfo();
3348 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3349 RandomX(cache_info->random_info,cache_info->columns),
3350 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3351 *virtual_nexus,exception);
3352 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3355 case DitherVirtualPixelMethod:
3357 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3358 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3359 1UL,1UL,*virtual_nexus,exception);
3360 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3363 case TileVirtualPixelMethod:
3365 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3366 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3367 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3368 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3370 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3373 case MirrorVirtualPixelMethod:
3375 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3376 if ((x_modulo.quotient & 0x01) == 1L)
3377 x_modulo.remainder=(ssize_t) cache_info->columns-
3378 x_modulo.remainder-1L;
3379 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3380 if ((y_modulo.quotient & 0x01) == 1L)
3381 y_modulo.remainder=(ssize_t) cache_info->rows-
3382 y_modulo.remainder-1L;
3383 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3384 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3386 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3389 case HorizontalTileEdgeVirtualPixelMethod:
3391 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3392 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3393 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3394 *virtual_nexus,exception);
3395 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3398 case VerticalTileEdgeVirtualPixelMethod:
3400 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3401 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3402 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3403 *virtual_nexus,exception);
3404 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3407 case BackgroundVirtualPixelMethod:
3408 case BlackVirtualPixelMethod:
3409 case GrayVirtualPixelMethod:
3410 case TransparentVirtualPixelMethod:
3411 case MaskVirtualPixelMethod:
3412 case WhiteVirtualPixelMethod:
3415 r=virtual_metacontent;
3418 case EdgeVirtualPixelMethod:
3419 case CheckerTileVirtualPixelMethod:
3421 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3422 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3423 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3426 r=virtual_metacontent;
3429 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3430 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3432 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3435 case HorizontalTileVirtualPixelMethod:
3437 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3440 r=virtual_metacontent;
3443 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3444 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3445 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3446 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3448 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3451 case VerticalTileVirtualPixelMethod:
3453 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3456 r=virtual_metacontent;
3459 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3460 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3461 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3462 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3464 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3468 if (p == (const Quantum *) NULL)
3470 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3472 q+=cache_info->number_channels;
3473 if ((s != (void *) NULL) && (r != (const void *) NULL))
3475 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3476 s+=cache_info->metacontent_extent;
3481 Transfer a run of pixels.
3483 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3484 length,1UL,*virtual_nexus,exception);
3485 if (p == (const Quantum *) NULL)
3487 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3488 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3489 q+=length*cache_info->number_channels;
3490 if ((r != (void *) NULL) && (s != (const void *) NULL))
3492 (void) memcpy(s,r,(size_t) length);
3493 s+=length*cache_info->metacontent_extent;
3500 if (virtual_metacontent != (void *) NULL)
3501 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3502 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3511 + G e t V i r t u a l P i x e l C a c h e %
3515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3517 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3518 % cache as defined by the geometry parameters. A pointer to the pixels
3519 % is returned if the pixels are transferred, otherwise a NULL is returned.
3521 % The format of the GetVirtualPixelCache() method is:
3523 % const Quantum *GetVirtualPixelCache(const Image *image,
3524 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3525 % const ssize_t y,const size_t columns,const size_t rows,
3526 % ExceptionInfo *exception)
3528 % A description of each parameter follows:
3530 % o image: the image.
3532 % o virtual_pixel_method: the virtual pixel method.
3534 % o x,y,columns,rows: These values define the perimeter of a region of
3537 % o exception: return any errors or warnings in this structure.
3540 static const Quantum *GetVirtualPixelCache(const Image *image,
3541 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3542 const size_t columns,const size_t rows,ExceptionInfo *exception)
3548 id = GetOpenMPThreadId();
3553 assert(image != (const Image *) NULL);
3554 assert(image->signature == MagickSignature);
3555 assert(image->cache != (Cache) NULL);
3556 cache_info=(CacheInfo *) image->cache;
3557 assert(cache_info->signature == MagickSignature);
3558 assert(id < (int) cache_info->number_threads);
3559 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3560 cache_info->nexus_info[id],exception);
3565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3569 % G e t V i r t u a l P i x e l Q u e u e %
3573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3575 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3576 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3578 % The format of the GetVirtualPixelQueue() method is:
3580 % const Quantum *GetVirtualPixelQueue(const Image image)
3582 % A description of each parameter follows:
3584 % o image: the image.
3587 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3593 id = GetOpenMPThreadId();
3595 assert(image != (const Image *) NULL);
3596 assert(image->signature == MagickSignature);
3597 assert(image->cache != (Cache) NULL);
3598 cache_info=(CacheInfo *) image->cache;
3599 assert(cache_info->signature == MagickSignature);
3600 if (cache_info->methods.get_virtual_pixels_handler !=
3601 (GetVirtualPixelsHandler) NULL)
3602 return(cache_info->methods.get_virtual_pixels_handler(image));
3603 assert(id < (int) cache_info->number_threads);
3604 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3612 % G e t V i r t u a l P i x e l s %
3616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3618 % GetVirtualPixels() returns an immutable pixel region. If the
3619 % region is successfully accessed, a pointer to it is returned, otherwise
3620 % NULL is returned. The returned pointer may point to a temporary working
3621 % copy of the pixels or it may point to the original pixels in memory.
3622 % Performance is maximized if the selected region is part of one row, or one
3623 % or more full rows, since there is opportunity to access the pixels in-place
3624 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3625 % returned pointer must *never* be deallocated by the user.
3627 % Pixels accessed via the returned pointer represent a simple array of type
3628 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3629 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3630 % access the meta-content (of type void) corresponding to the the
3633 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3635 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3636 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3637 % GetCacheViewAuthenticPixels() instead.
3639 % The format of the GetVirtualPixels() method is:
3641 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3642 % const ssize_t y,const size_t columns,const size_t rows,
3643 % ExceptionInfo *exception)
3645 % A description of each parameter follows:
3647 % o image: the image.
3649 % o x,y,columns,rows: These values define the perimeter of a region of
3652 % o exception: return any errors or warnings in this structure.
3655 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3656 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3657 ExceptionInfo *exception)
3663 id = GetOpenMPThreadId();
3668 assert(image != (const Image *) NULL);
3669 assert(image->signature == MagickSignature);
3670 assert(image->cache != (Cache) NULL);
3671 cache_info=(CacheInfo *) image->cache;
3672 assert(cache_info->signature == MagickSignature);
3673 if (cache_info->methods.get_virtual_pixel_handler !=
3674 (GetVirtualPixelHandler) NULL)
3675 return(cache_info->methods.get_virtual_pixel_handler(image,
3676 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3677 assert(id < (int) cache_info->number_threads);
3678 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3679 columns,rows,cache_info->nexus_info[id],exception);
3684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3688 + 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 %
3692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3694 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3695 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3697 % The format of the GetVirtualPixelsCache() method is:
3699 % Quantum *GetVirtualPixelsCache(const Image *image)
3701 % A description of each parameter follows:
3703 % o image: the image.
3706 static const Quantum *GetVirtualPixelsCache(const Image *image)
3712 id = GetOpenMPThreadId();
3714 assert(image != (const Image *) NULL);
3715 assert(image->signature == MagickSignature);
3716 assert(image->cache != (Cache) NULL);
3717 cache_info=(CacheInfo *) image->cache;
3718 assert(cache_info->signature == MagickSignature);
3719 assert(id < (int) cache_info->number_threads);
3720 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3728 + G e t V i r t u a l P i x e l s N e x u s %
3732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3734 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3737 % The format of the GetVirtualPixelsNexus() method is:
3739 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3740 % NexusInfo *nexus_info)
3742 % A description of each parameter follows:
3744 % o cache: the pixel cache.
3746 % o nexus_info: the cache nexus to return the colormap pixels.
3749 MagickExport const Quantum *GetVirtualPixelsNexus(const Cache cache,
3750 NexusInfo *nexus_info)
3755 assert(cache != (Cache) NULL);
3756 cache_info=(CacheInfo *) cache;
3757 assert(cache_info->signature == MagickSignature);
3758 if (cache_info->storage_class == UndefinedClass)
3759 return((Quantum *) NULL);
3760 return((const Quantum *) nexus_info->pixels);
3764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768 + M a s k P i x e l C a c h e N e x u s %
3772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3774 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3775 % The method returns MagickTrue if the pixel region is masked, otherwise
3778 % The format of the MaskPixelCacheNexus() method is:
3780 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3781 % NexusInfo *nexus_info,ExceptionInfo *exception)
3783 % A description of each parameter follows:
3785 % o image: the image.
3787 % o nexus_info: the cache nexus to clip.
3789 % o exception: return any errors or warnings in this structure.
3793 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3794 const MagickRealType alpha,const PixelInfo *q,
3795 const MagickRealType beta,PixelInfo *composite)
3800 if (alpha == TransparentAlpha)
3805 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3806 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3807 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3808 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3809 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3810 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3811 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3814 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3815 ExceptionInfo *exception)
3831 register const Quantum
3844 if (image->debug != MagickFalse)
3845 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3846 if (image->mask == (Image *) NULL)
3847 return(MagickFalse);
3848 cache_info=(CacheInfo *) image->cache;
3849 if (cache_info == (Cache) NULL)
3850 return(MagickFalse);
3851 image_nexus=AcquirePixelCacheNexus(1);
3852 clip_nexus=AcquirePixelCacheNexus(1);
3853 if ((image_nexus == (NexusInfo **) NULL) ||
3854 (clip_nexus == (NexusInfo **) NULL))
3855 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3856 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3857 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3858 nexus_info->region.height,image_nexus[0],exception);
3859 q=nexus_info->pixels;
3860 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3861 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3862 nexus_info->region.height,clip_nexus[0],&image->exception);
3863 GetPixelInfo(image,&alpha);
3864 GetPixelInfo(image,&beta);
3865 number_pixels=(MagickSizeType) nexus_info->region.width*
3866 nexus_info->region.height;
3867 for (i=0; i < (ssize_t) number_pixels; i++)
3869 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3871 SetPixelInfo(image,p,&alpha);
3872 SetPixelInfo(image,q,&beta);
3873 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3874 &alpha,alpha.alpha,&beta);
3875 SetPixelRed(image,ClampToQuantum(beta.red),q);
3876 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3877 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3878 if (cache_info->colorspace == CMYKColorspace)
3879 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3880 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3885 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3886 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3887 if (i < (ssize_t) number_pixels)
3888 return(MagickFalse);
3893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3897 + O p e n P i x e l C a c h e %
3901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3903 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3904 % dimensions, allocating space for the image pixels and optionally the
3905 % metacontent, and memory mapping the cache if it is disk based. The cache
3906 % nexus array is initialized as well.
3908 % The format of the OpenPixelCache() method is:
3910 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3911 % ExceptionInfo *exception)
3913 % A description of each parameter follows:
3915 % o image: the image.
3917 % o mode: ReadMode, WriteMode, or IOMode.
3919 % o exception: return any errors or warnings in this structure.
3923 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3925 cache_info->mapped=MagickFalse;
3926 cache_info->pixels=(Quantum *) AcquireAlignedMemory(1,(size_t)
3927 cache_info->length);
3928 if (cache_info->pixels == (Quantum *) NULL)
3930 cache_info->mapped=MagickTrue;
3931 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3932 cache_info->length);
3936 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3946 cache_info=(CacheInfo *) image->cache;
3947 if (image->debug != MagickFalse)
3950 format[MaxTextExtent],
3951 message[MaxTextExtent];
3953 (void) FormatMagickSize(length,MagickFalse,format);
3954 (void) FormatLocaleString(message,MaxTextExtent,
3955 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3956 cache_info->cache_filename,cache_info->file,format);
3957 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3959 if (length != (MagickSizeType) ((MagickOffsetType) length))
3960 return(MagickFalse);
3961 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3963 return(MagickFalse);
3964 if ((MagickSizeType) extent >= length)
3966 offset=(MagickOffsetType) length-1;
3967 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3968 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3971 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3972 ExceptionInfo *exception)
3979 format[MaxTextExtent],
3980 message[MaxTextExtent];
3993 assert(image != (const Image *) NULL);
3994 assert(image->signature == MagickSignature);
3995 assert(image->cache != (Cache) NULL);
3996 if (image->debug != MagickFalse)
3997 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3998 if ((image->columns == 0) || (image->rows == 0))
3999 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
4000 cache_info=(CacheInfo *) image->cache;
4001 assert(cache_info->signature == MagickSignature);
4002 source_info=(*cache_info);
4003 source_info.file=(-1);
4004 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4005 image->filename,(double) GetImageIndexInList(image));
4006 cache_info->storage_class=image->storage_class;
4007 cache_info->colorspace=image->colorspace;
4008 cache_info->matte=image->matte;
4009 cache_info->rows=image->rows;
4010 cache_info->columns=image->columns;
4011 InitializePixelChannelMap(image);
4012 cache_info->number_channels=GetPixelChannels(image);
4013 cache_info->metacontent_extent=image->metacontent_extent;
4014 cache_info->mode=mode;
4015 if (image->ping != MagickFalse)
4017 cache_info->type=PingCache;
4018 cache_info->pixels=(Quantum *) NULL;
4019 cache_info->metacontent=(void *) NULL;
4020 cache_info->length=0;
4023 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4024 packet_size=cache_info->number_channels*sizeof(Quantum);
4025 if (image->metacontent_extent != 0)
4026 packet_size+=cache_info->metacontent_extent;
4027 length=number_pixels*packet_size;
4028 columns=(size_t) (length/cache_info->rows/packet_size);
4029 if (cache_info->columns != columns)
4030 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4032 cache_info->length=length;
4033 if ((cache_info->type != UndefinedCache) &&
4034 (cache_info->columns <= source_info.columns) &&
4035 (cache_info->rows <= source_info.rows) &&
4036 (cache_info->number_channels <= source_info.number_channels) &&
4037 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4040 Inline pixel cache clone optimization.
4042 if ((cache_info->columns == source_info.columns) &&
4043 (cache_info->rows == source_info.rows) &&
4044 (cache_info->number_channels == source_info.number_channels) &&
4045 (cache_info->metacontent_extent == source_info.metacontent_extent))
4047 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4049 status=AcquireMagickResource(AreaResource,cache_info->length);
4050 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4051 cache_info->metacontent_extent);
4052 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4054 status=AcquireMagickResource(MemoryResource,cache_info->length);
4055 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4056 (cache_info->type == MemoryCache))
4058 AllocatePixelCachePixels(cache_info);
4059 if (cache_info->pixels == (Quantum *) NULL)
4060 cache_info->pixels=source_info.pixels;
4064 Create memory pixel cache.
4067 if (image->debug != MagickFalse)
4069 (void) FormatMagickSize(cache_info->length,MagickTrue,
4071 (void) FormatLocaleString(message,MaxTextExtent,
4072 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4073 cache_info->filename,cache_info->mapped != MagickFalse ?
4074 "anonymous" : "heap",(double) cache_info->columns,(double)
4075 cache_info->rows,(double) cache_info->number_channels,
4077 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4080 cache_info->type=MemoryCache;
4081 cache_info->metacontent=(void *) NULL;
4082 if (cache_info->metacontent_extent != 0)
4083 cache_info->metacontent=(void *) (cache_info->pixels+
4084 number_pixels*cache_info->number_channels);
4085 if (source_info.storage_class != UndefinedClass)
4087 status=ClonePixelCachePixels(cache_info,&source_info,
4089 RelinquishPixelCachePixels(&source_info);
4094 RelinquishMagickResource(MemoryResource,cache_info->length);
4097 Create pixel cache on disk.
4099 status=AcquireMagickResource(DiskResource,cache_info->length);
4100 if (status == MagickFalse)
4102 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4103 "CacheResourcesExhausted","`%s'",image->filename);
4104 return(MagickFalse);
4106 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4108 RelinquishMagickResource(DiskResource,cache_info->length);
4109 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4111 return(MagickFalse);
4113 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4114 cache_info->length);
4115 if (status == MagickFalse)
4117 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4119 return(MagickFalse);
4121 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4122 cache_info->metacontent_extent);
4123 status=AcquireMagickResource(AreaResource,cache_info->length);
4124 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4125 cache_info->type=DiskCache;
4128 status=AcquireMagickResource(MapResource,cache_info->length);
4129 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4130 (cache_info->type != MemoryCache))
4131 cache_info->type=DiskCache;
4134 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4135 cache_info->offset,(size_t) cache_info->length);
4136 if (cache_info->pixels == (Quantum *) NULL)
4138 cache_info->type=DiskCache;
4139 cache_info->pixels=source_info.pixels;
4144 Create file-backed memory-mapped pixel cache.
4147 (void) ClosePixelCacheOnDisk(cache_info);
4148 cache_info->type=MapCache;
4149 cache_info->mapped=MagickTrue;
4150 cache_info->metacontent=(void *) NULL;
4151 if (cache_info->metacontent_extent != 0)
4152 cache_info->metacontent=(void *) (cache_info->pixels+
4153 number_pixels*cache_info->number_channels);
4154 if (source_info.storage_class != UndefinedClass)
4156 status=ClonePixelCachePixels(cache_info,&source_info,
4158 RelinquishPixelCachePixels(&source_info);
4160 if (image->debug != MagickFalse)
4162 (void) FormatMagickSize(cache_info->length,MagickTrue,
4164 (void) FormatLocaleString(message,MaxTextExtent,
4165 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4166 cache_info->filename,cache_info->cache_filename,
4167 cache_info->file,(double) cache_info->columns,(double)
4168 cache_info->rows,(double) cache_info->number_channels,
4170 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4176 RelinquishMagickResource(MapResource,cache_info->length);
4179 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4181 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4182 RelinquishPixelCachePixels(&source_info);
4184 if (image->debug != MagickFalse)
4186 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4187 (void) FormatLocaleString(message,MaxTextExtent,
4188 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4189 cache_info->cache_filename,cache_info->file,(double)
4190 cache_info->columns,(double) cache_info->rows,(double)
4191 cache_info->number_channels,format);
4192 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202 + P e r s i s t P i x e l C a c h e %
4206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4208 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4209 % persistent pixel cache is one that resides on disk and is not destroyed
4210 % when the program exits.
4212 % The format of the PersistPixelCache() method is:
4214 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4215 % const MagickBooleanType attach,MagickOffsetType *offset,
4216 % ExceptionInfo *exception)
4218 % A description of each parameter follows:
4220 % o image: the image.
4222 % o filename: the persistent pixel cache filename.
4224 % o attach: A value other than zero initializes the persistent pixel cache.
4226 % o initialize: A value other than zero initializes the persistent pixel
4229 % o offset: the offset in the persistent cache to store pixels.
4231 % o exception: return any errors or warnings in this structure.
4234 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4235 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4236 ExceptionInfo *exception)
4251 assert(image != (Image *) NULL);
4252 assert(image->signature == MagickSignature);
4253 if (image->debug != MagickFalse)
4254 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4255 assert(image->cache != (void *) NULL);
4256 assert(filename != (const char *) NULL);
4257 assert(offset != (MagickOffsetType *) NULL);
4258 page_size=GetMagickPageSize();
4259 cache_info=(CacheInfo *) image->cache;
4260 assert(cache_info->signature == MagickSignature);
4261 if (attach != MagickFalse)
4264 Attach existing persistent pixel cache.
4266 if (image->debug != MagickFalse)
4267 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4268 "attach persistent cache");
4269 (void) CopyMagickString(cache_info->cache_filename,filename,
4271 cache_info->type=DiskCache;
4272 cache_info->offset=(*offset);
4273 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4274 return(MagickFalse);
4275 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4278 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4279 (cache_info->reference_count == 1))
4281 LockSemaphoreInfo(cache_info->semaphore);
4282 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4283 (cache_info->reference_count == 1))
4289 Usurp existing persistent pixel cache.
4291 status=rename(cache_info->cache_filename,filename);
4294 (void) CopyMagickString(cache_info->cache_filename,filename,
4296 *offset+=cache_info->length+page_size-(cache_info->length %
4298 UnlockSemaphoreInfo(cache_info->semaphore);
4299 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4300 if (image->debug != MagickFalse)
4301 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4302 "Usurp resident persistent cache");
4306 UnlockSemaphoreInfo(cache_info->semaphore);
4309 Clone persistent pixel cache.
4311 clone_image=(*image);
4312 clone_info=(CacheInfo *) clone_image.cache;
4313 image->cache=ClonePixelCache(cache_info);
4314 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4315 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4316 cache_info->type=DiskCache;
4317 cache_info->offset=(*offset);
4318 cache_info=(CacheInfo *) image->cache;
4319 status=OpenPixelCache(image,IOMode,exception);
4320 if (status != MagickFalse)
4321 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4322 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4323 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4332 + Q u e u e A u t h e n t i c N e x u s %
4336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4338 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4339 % by the region rectangle and returns a pointer to the region. This region is
4340 % subsequently transferred from the pixel cache with
4341 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4342 % pixels are transferred, otherwise a NULL is returned.
4344 % The format of the QueueAuthenticNexus() method is:
4346 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4347 % const ssize_t y,const size_t columns,const size_t rows,
4348 % NexusInfo *nexus_info,ExceptionInfo *exception)
4350 % A description of each parameter follows:
4352 % o image: the image.
4354 % o x,y,columns,rows: These values define the perimeter of a region of
4357 % o nexus_info: the cache nexus to set.
4359 % o exception: return any errors or warnings in this structure.
4362 MagickExport Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4363 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4364 ExceptionInfo *exception)
4379 Validate pixel cache geometry.
4381 assert(image != (const Image *) NULL);
4382 assert(image->signature == MagickSignature);
4383 assert(image->cache != (Cache) NULL);
4384 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4385 assert(cache_info->signature == MagickSignature);
4386 if (cache_info == (Cache) NULL)
4387 return((Quantum *) NULL);
4388 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4390 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4391 "NoPixelsDefinedInCache","`%s'",image->filename);
4392 return((Quantum *) NULL);
4394 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4395 (y >= (ssize_t) cache_info->rows))
4397 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4398 "PixelsAreNotAuthentic","`%s'",image->filename);
4399 return((Quantum *) NULL);
4401 offset=(MagickOffsetType) y*cache_info->columns+x;
4403 return((Quantum *) NULL);
4404 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4405 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4406 if ((MagickSizeType) offset >= number_pixels)
4407 return((Quantum *) NULL);
4413 region.width=columns;
4415 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4423 + 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 %
4427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4429 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4430 % defined by the region rectangle and returns a pointer to the region. This
4431 % region is subsequently transferred from the pixel cache with
4432 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4433 % pixels are transferred, otherwise a NULL is returned.
4435 % The format of the QueueAuthenticPixelsCache() method is:
4437 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4438 % const ssize_t y,const size_t columns,const size_t rows,
4439 % ExceptionInfo *exception)
4441 % A description of each parameter follows:
4443 % o image: the image.
4445 % o x,y,columns,rows: These values define the perimeter of a region of
4448 % o exception: return any errors or warnings in this structure.
4451 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4452 const ssize_t y,const size_t columns,const size_t rows,
4453 ExceptionInfo *exception)
4459 id = GetOpenMPThreadId();
4464 assert(image != (const Image *) NULL);
4465 assert(image->signature == MagickSignature);
4466 assert(image->cache != (Cache) NULL);
4467 cache_info=(CacheInfo *) image->cache;
4468 assert(cache_info->signature == MagickSignature);
4469 assert(id < (int) cache_info->number_threads);
4470 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4480 % Q u e u e A u t h e n t i c P i x e l s %
4484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4486 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4487 % successfully initialized a pointer to a Quantum array representing the
4488 % region is returned, otherwise NULL is returned. The returned pointer may
4489 % point to a temporary working buffer for the pixels or it may point to the
4490 % final location of the pixels in memory.
4492 % Write-only access means that any existing pixel values corresponding to
4493 % the region are ignored. This is useful if the initial image is being
4494 % created from scratch, or if the existing pixel values are to be
4495 % completely replaced without need to refer to their pre-existing values.
4496 % The application is free to read and write the pixel buffer returned by
4497 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4498 % initialize the pixel array values. Initializing pixel array values is the
4499 % application's responsibility.
4501 % Performance is maximized if the selected region is part of one row, or
4502 % one or more full rows, since then there is opportunity to access the
4503 % pixels in-place (without a copy) if the image is in memory, or in a
4504 % memory-mapped file. The returned pointer must *never* be deallocated
4507 % Pixels accessed via the returned pointer represent a simple array of type
4508 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4509 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4510 % obtain the meta-content (of type void) corresponding to the region.
4511 % Once the Quantum (and/or Quantum) array has been updated, the
4512 % changes must be saved back to the underlying image using
4513 % SyncAuthenticPixels() or they may be lost.
4515 % The format of the QueueAuthenticPixels() method is:
4517 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4518 % const ssize_t y,const size_t columns,const size_t rows,
4519 % ExceptionInfo *exception)
4521 % A description of each parameter follows:
4523 % o image: the image.
4525 % o x,y,columns,rows: These values define the perimeter of a region of
4528 % o exception: return any errors or warnings in this structure.
4531 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4532 const ssize_t y,const size_t columns,const size_t rows,
4533 ExceptionInfo *exception)
4539 id = GetOpenMPThreadId();
4544 assert(image != (Image *) NULL);
4545 assert(image->signature == MagickSignature);
4546 assert(image->cache != (Cache) NULL);
4547 cache_info=(CacheInfo *) image->cache;
4548 assert(cache_info->signature == MagickSignature);
4549 if (cache_info->methods.queue_authentic_pixels_handler !=
4550 (QueueAuthenticPixelsHandler) NULL)
4552 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4553 columns,rows,exception);
4556 assert(id < (int) cache_info->number_threads);
4557 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4567 + 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 %
4571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4573 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4576 % The format of the ReadPixelCacheMetacontent() method is:
4578 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4579 % NexusInfo *nexus_info,ExceptionInfo *exception)
4581 % A description of each parameter follows:
4583 % o cache_info: the pixel cache.
4585 % o nexus_info: the cache nexus to read the metacontent.
4587 % o exception: return any errors or warnings in this structure.
4590 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4591 NexusInfo *nexus_info,ExceptionInfo *exception)
4604 register unsigned char
4610 if (cache_info->metacontent_extent == 0)
4611 return(MagickFalse);
4612 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4614 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4615 nexus_info->region.x;
4616 length=(MagickSizeType) nexus_info->region.width*
4617 cache_info->metacontent_extent;
4618 rows=nexus_info->region.height;
4620 q=(unsigned char *) nexus_info->metacontent;
4621 switch (cache_info->type)
4626 register unsigned char
4630 Read meta-content from memory.
4632 if ((cache_info->columns == nexus_info->region.width) &&
4633 (extent == (MagickSizeType) ((size_t) extent)))
4638 p=(unsigned char *) cache_info->metacontent+offset*
4639 cache_info->metacontent_extent;
4640 for (y=0; y < (ssize_t) rows; y++)
4642 (void) memcpy(q,p,(size_t) length);
4643 p+=cache_info->metacontent_extent*cache_info->columns;
4644 q+=cache_info->metacontent_extent*nexus_info->region.width;
4651 Read meta content from disk.
4653 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4655 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4656 cache_info->cache_filename);
4657 return(MagickFalse);
4659 if ((cache_info->columns == nexus_info->region.width) &&
4660 (extent <= MagickMaxBufferExtent))
4665 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4666 for (y=0; y < (ssize_t) rows; y++)
4668 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4669 cache_info->number_channels*sizeof(Quantum)+offset*
4670 cache_info->metacontent_extent,length,(unsigned char *) q);
4671 if ((MagickSizeType) count != length)
4673 offset+=cache_info->columns;
4674 q+=cache_info->metacontent_extent*nexus_info->region.width;
4676 if (y < (ssize_t) rows)
4678 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4679 cache_info->cache_filename);
4680 return(MagickFalse);
4687 if ((cache_info->debug != MagickFalse) &&
4688 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4689 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4690 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4691 nexus_info->region.width,(double) nexus_info->region.height,(double)
4692 nexus_info->region.x,(double) nexus_info->region.y);
4697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4701 + R e a d P i x e l C a c h e P i x e l s %
4705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4707 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4710 % The format of the ReadPixelCachePixels() method is:
4712 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4713 % NexusInfo *nexus_info,ExceptionInfo *exception)
4715 % A description of each parameter follows:
4717 % o cache_info: the pixel cache.
4719 % o nexus_info: the cache nexus to read the pixels.
4721 % o exception: return any errors or warnings in this structure.
4724 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4725 NexusInfo *nexus_info,ExceptionInfo *exception)
4744 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4746 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4747 nexus_info->region.x;
4748 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4750 rows=nexus_info->region.height;
4752 q=nexus_info->pixels;
4753 switch (cache_info->type)
4762 Read pixels from memory.
4764 if ((cache_info->columns == nexus_info->region.width) &&
4765 (extent == (MagickSizeType) ((size_t) extent)))
4770 p=cache_info->pixels+offset*cache_info->number_channels;
4771 for (y=0; y < (ssize_t) rows; y++)
4773 (void) memcpy(q,p,(size_t) length);
4774 p+=cache_info->number_channels*cache_info->columns;
4775 q+=cache_info->number_channels*nexus_info->region.width;
4782 Read pixels from disk.
4784 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4786 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4787 cache_info->cache_filename);
4788 return(MagickFalse);
4790 if ((cache_info->columns == nexus_info->region.width) &&
4791 (extent <= MagickMaxBufferExtent))
4796 for (y=0; y < (ssize_t) rows; y++)
4798 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4799 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4800 if ((MagickSizeType) count != length)
4802 offset+=cache_info->columns;
4803 q+=cache_info->number_channels*nexus_info->region.width;
4805 if (y < (ssize_t) rows)
4807 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4808 cache_info->cache_filename);
4809 return(MagickFalse);
4816 if ((cache_info->debug != MagickFalse) &&
4817 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4818 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4819 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4820 nexus_info->region.width,(double) nexus_info->region.height,(double)
4821 nexus_info->region.x,(double) nexus_info->region.y);
4826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4830 + R e f e r e n c e P i x e l C a c h e %
4834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4836 % ReferencePixelCache() increments the reference count associated with the
4837 % pixel cache returning a pointer to the cache.
4839 % The format of the ReferencePixelCache method is:
4841 % Cache ReferencePixelCache(Cache cache_info)
4843 % A description of each parameter follows:
4845 % o cache_info: the pixel cache.
4848 MagickExport Cache ReferencePixelCache(Cache cache)
4853 assert(cache != (Cache *) NULL);
4854 cache_info=(CacheInfo *) cache;
4855 assert(cache_info->signature == MagickSignature);
4856 LockSemaphoreInfo(cache_info->semaphore);
4857 cache_info->reference_count++;
4858 UnlockSemaphoreInfo(cache_info->semaphore);
4863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4867 + S e t P i x e l C a c h e M e t h o d s %
4871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4873 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4875 % The format of the SetPixelCacheMethods() method is:
4877 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4879 % A description of each parameter follows:
4881 % o cache: the pixel cache.
4883 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4886 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4891 GetOneAuthenticPixelFromHandler
4892 get_one_authentic_pixel_from_handler;
4894 GetOneVirtualPixelFromHandler
4895 get_one_virtual_pixel_from_handler;
4898 Set cache pixel methods.
4900 assert(cache != (Cache) NULL);
4901 assert(cache_methods != (CacheMethods *) NULL);
4902 cache_info=(CacheInfo *) cache;
4903 assert(cache_info->signature == MagickSignature);
4904 if (cache_info->debug != MagickFalse)
4905 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4906 cache_info->filename);
4907 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4908 cache_info->methods.get_virtual_pixel_handler=
4909 cache_methods->get_virtual_pixel_handler;
4910 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4911 cache_info->methods.destroy_pixel_handler=
4912 cache_methods->destroy_pixel_handler;
4913 if (cache_methods->get_virtual_metacontent_from_handler !=
4914 (GetVirtualMetacontentFromHandler) NULL)
4915 cache_info->methods.get_virtual_metacontent_from_handler=
4916 cache_methods->get_virtual_metacontent_from_handler;
4917 if (cache_methods->get_authentic_pixels_handler !=
4918 (GetAuthenticPixelsHandler) NULL)
4919 cache_info->methods.get_authentic_pixels_handler=
4920 cache_methods->get_authentic_pixels_handler;
4921 if (cache_methods->queue_authentic_pixels_handler !=
4922 (QueueAuthenticPixelsHandler) NULL)
4923 cache_info->methods.queue_authentic_pixels_handler=
4924 cache_methods->queue_authentic_pixels_handler;
4925 if (cache_methods->sync_authentic_pixels_handler !=
4926 (SyncAuthenticPixelsHandler) NULL)
4927 cache_info->methods.sync_authentic_pixels_handler=
4928 cache_methods->sync_authentic_pixels_handler;
4929 if (cache_methods->get_authentic_pixels_from_handler !=
4930 (GetAuthenticPixelsFromHandler) NULL)
4931 cache_info->methods.get_authentic_pixels_from_handler=
4932 cache_methods->get_authentic_pixels_from_handler;
4933 if (cache_methods->get_authentic_metacontent_from_handler !=
4934 (GetAuthenticMetacontentFromHandler) NULL)
4935 cache_info->methods.get_authentic_metacontent_from_handler=
4936 cache_methods->get_authentic_metacontent_from_handler;
4937 get_one_virtual_pixel_from_handler=
4938 cache_info->methods.get_one_virtual_pixel_from_handler;
4939 if (get_one_virtual_pixel_from_handler !=
4940 (GetOneVirtualPixelFromHandler) NULL)
4941 cache_info->methods.get_one_virtual_pixel_from_handler=
4942 cache_methods->get_one_virtual_pixel_from_handler;
4943 get_one_authentic_pixel_from_handler=
4944 cache_methods->get_one_authentic_pixel_from_handler;
4945 if (get_one_authentic_pixel_from_handler !=
4946 (GetOneAuthenticPixelFromHandler) NULL)
4947 cache_info->methods.get_one_authentic_pixel_from_handler=
4948 cache_methods->get_one_authentic_pixel_from_handler;
4952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4956 + S e t P i x e l C a c h e N e x u s P i x e l s %
4960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4962 % SetPixelCacheNexusPixels() defines the region of the cache for the
4963 % specified cache nexus.
4965 % The format of the SetPixelCacheNexusPixels() method is:
4967 % Quantum SetPixelCacheNexusPixels(const Image *image,
4968 % const RectangleInfo *region,NexusInfo *nexus_info,
4969 % ExceptionInfo *exception)
4971 % A description of each parameter follows:
4973 % o image: the image.
4975 % o region: A pointer to the RectangleInfo structure that defines the
4976 % region of this particular cache nexus.
4978 % o nexus_info: the cache nexus to set.
4980 % o exception: return any errors or warnings in this structure.
4984 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4985 NexusInfo *nexus_info,ExceptionInfo *exception)
4987 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4988 return(MagickFalse);
4989 nexus_info->mapped=MagickFalse;
4990 nexus_info->cache=(Quantum *) AcquireAlignedMemory(1,(size_t)
4991 nexus_info->length);
4992 if (nexus_info->cache == (Quantum *) NULL)
4994 nexus_info->mapped=MagickTrue;
4995 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4996 nexus_info->length);
4998 if (nexus_info->cache == (Quantum *) NULL)
5000 (void) ThrowMagickException(exception,GetMagickModule(),
5001 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5002 cache_info->filename);
5003 return(MagickFalse);
5008 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5009 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5021 cache_info=(CacheInfo *) image->cache;
5022 assert(cache_info->signature == MagickSignature);
5023 if (cache_info->type == UndefinedCache)
5024 return((Quantum *) NULL);
5025 nexus_info->region=(*region);
5026 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5027 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5033 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5034 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5035 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5036 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5037 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5038 ((nexus_info->region.width == cache_info->columns) ||
5039 ((nexus_info->region.width % cache_info->columns) == 0)))))
5045 Pixels are accessed directly from memory.
5047 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5048 nexus_info->region.x;
5049 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5051 nexus_info->metacontent=(void *) NULL;
5052 if (cache_info->metacontent_extent != 0)
5053 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5054 offset*cache_info->metacontent_extent;
5055 return(nexus_info->pixels);
5059 Pixels are stored in a cache region until they are synced to the cache.
5061 number_pixels=(MagickSizeType) nexus_info->region.width*
5062 nexus_info->region.height;
5063 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5064 if (cache_info->metacontent_extent != 0)
5065 length+=number_pixels*cache_info->metacontent_extent;
5066 if (nexus_info->cache == (Quantum *) NULL)
5068 nexus_info->length=length;
5069 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5070 if (status == MagickFalse)
5072 nexus_info->length=0;
5073 return((Quantum *) NULL);
5077 if (nexus_info->length != length)
5079 RelinquishCacheNexusPixels(nexus_info);
5080 nexus_info->length=length;
5081 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5082 if (status == MagickFalse)
5084 nexus_info->length=0;
5085 return((Quantum *) NULL);
5088 nexus_info->pixels=nexus_info->cache;
5089 nexus_info->metacontent=(void *) NULL;
5090 if (cache_info->metacontent_extent != 0)
5091 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5092 cache_info->number_channels);
5093 return(nexus_info->pixels);
5097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5101 % 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 %
5105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5107 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5108 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5109 % access that is outside the boundaries of the image cache.
5111 % The format of the SetPixelCacheVirtualMethod() method is:
5113 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5114 % const VirtualPixelMethod virtual_pixel_method)
5116 % A description of each parameter follows:
5118 % o image: the image.
5120 % o virtual_pixel_method: choose the type of virtual pixel.
5123 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5124 const VirtualPixelMethod virtual_pixel_method)
5132 assert(image != (Image *) NULL);
5133 assert(image->signature == MagickSignature);
5134 if (image->debug != MagickFalse)
5135 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5136 assert(image->cache != (Cache) NULL);
5137 cache_info=(CacheInfo *) image->cache;
5138 assert(cache_info->signature == MagickSignature);
5139 method=cache_info->virtual_pixel_method;
5140 cache_info->virtual_pixel_method=virtual_pixel_method;
5145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5149 + 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 %
5153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5155 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5156 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5157 % is synced, otherwise MagickFalse.
5159 % The format of the SyncAuthenticPixelCacheNexus() method is:
5161 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5162 % NexusInfo *nexus_info,ExceptionInfo *exception)
5164 % A description of each parameter follows:
5166 % o image: the image.
5168 % o nexus_info: the cache nexus to sync.
5170 % o exception: return any errors or warnings in this structure.
5173 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5174 NexusInfo *nexus_info,ExceptionInfo *exception)
5183 Transfer pixels to the cache.
5185 assert(image != (Image *) NULL);
5186 assert(image->signature == MagickSignature);
5187 if (image->cache == (Cache) NULL)
5188 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5189 cache_info=(CacheInfo *) image->cache;
5190 assert(cache_info->signature == MagickSignature);
5191 if (cache_info->type == UndefinedCache)
5192 return(MagickFalse);
5193 if ((image->clip_mask != (Image *) NULL) &&
5194 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5195 return(MagickFalse);
5196 if ((image->mask != (Image *) NULL) &&
5197 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5198 return(MagickFalse);
5199 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5201 assert(cache_info->signature == MagickSignature);
5202 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5203 if ((cache_info->metacontent_extent != 0) &&
5204 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5205 return(MagickFalse);
5210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5214 + S y n c A u t h e n t i c P i x e l C a c h e %
5218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5220 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5221 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5222 % otherwise MagickFalse.
5224 % The format of the SyncAuthenticPixelsCache() method is:
5226 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5227 % ExceptionInfo *exception)
5229 % A description of each parameter follows:
5231 % o image: the image.
5233 % o exception: return any errors or warnings in this structure.
5236 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5237 ExceptionInfo *exception)
5243 id = GetOpenMPThreadId();
5248 assert(image != (Image *) NULL);
5249 assert(image->signature == MagickSignature);
5250 assert(image->cache != (Cache) NULL);
5251 cache_info=(CacheInfo *) image->cache;
5252 assert(cache_info->signature == MagickSignature);
5253 assert(id < (int) cache_info->number_threads);
5254 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5264 % S y n c A u t h e n t i c P i x e l s %
5268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5270 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5271 % The method returns MagickTrue if the pixel region is flushed, otherwise
5274 % The format of the SyncAuthenticPixels() method is:
5276 % MagickBooleanType SyncAuthenticPixels(Image *image,
5277 % ExceptionInfo *exception)
5279 % A description of each parameter follows:
5281 % o image: the image.
5283 % o exception: return any errors or warnings in this structure.
5286 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5287 ExceptionInfo *exception)
5293 id = GetOpenMPThreadId();
5298 assert(image != (Image *) NULL);
5299 assert(image->signature == MagickSignature);
5300 assert(image->cache != (Cache) NULL);
5301 cache_info=(CacheInfo *) image->cache;
5302 assert(cache_info->signature == MagickSignature);
5303 if (cache_info->methods.sync_authentic_pixels_handler !=
5304 (SyncAuthenticPixelsHandler) NULL)
5306 status=cache_info->methods.sync_authentic_pixels_handler(image,
5310 assert(id < (int) cache_info->number_threads);
5311 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5321 % S y n c I m a g e P i x e l C a c h e %
5325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5327 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5328 % The method returns MagickTrue if the pixel region is flushed, otherwise
5331 % The format of the SyncImagePixelCache() method is:
5333 % MagickBooleanType SyncImagePixelCache(Image *image,
5334 % ExceptionInfo *exception)
5336 % A description of each parameter follows:
5338 % o image: the image.
5340 % o exception: return any errors or warnings in this structure.
5343 MagickExport MagickBooleanType SyncImagePixelCache(Image *image,
5344 ExceptionInfo *exception)
5349 assert(image != (Image *) NULL);
5350 assert(exception != (ExceptionInfo *) NULL);
5351 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5352 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5360 + 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 %
5364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5366 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5367 % of the pixel cache.
5369 % The format of the WritePixelCacheMetacontent() method is:
5371 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5372 % NexusInfo *nexus_info,ExceptionInfo *exception)
5374 % A description of each parameter follows:
5376 % o cache_info: the pixel cache.
5378 % o nexus_info: the cache nexus to write the meta-content.
5380 % o exception: return any errors or warnings in this structure.
5383 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5384 NexusInfo *nexus_info,ExceptionInfo *exception)
5394 register const unsigned char
5403 if (cache_info->metacontent_extent == 0)
5404 return(MagickFalse);
5405 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5407 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5408 nexus_info->region.x;
5409 length=(MagickSizeType) nexus_info->region.width*
5410 cache_info->metacontent_extent;
5411 rows=nexus_info->region.height;
5412 extent=(MagickSizeType) length*rows;
5413 p=(unsigned char *) nexus_info->metacontent;
5414 switch (cache_info->type)
5419 register unsigned char
5423 Write associated pixels to memory.
5425 if ((cache_info->columns == nexus_info->region.width) &&
5426 (extent == (MagickSizeType) ((size_t) extent)))
5431 q=(unsigned char *) cache_info->metacontent+offset*
5432 cache_info->metacontent_extent;
5433 for (y=0; y < (ssize_t) rows; y++)
5435 (void) memcpy(q,p,(size_t) length);
5436 p+=nexus_info->region.width*cache_info->metacontent_extent;
5437 q+=cache_info->columns*cache_info->metacontent_extent;
5444 Write associated pixels to disk.
5446 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5448 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5449 cache_info->cache_filename);
5450 return(MagickFalse);
5452 if ((cache_info->columns == nexus_info->region.width) &&
5453 (extent <= MagickMaxBufferExtent))
5458 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5459 for (y=0; y < (ssize_t) rows; y++)
5461 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5462 cache_info->number_channels*sizeof(Quantum)+offset*
5463 cache_info->metacontent_extent,length,(const unsigned char *) p);
5464 if ((MagickSizeType) count != length)
5466 p+=nexus_info->region.width*cache_info->metacontent_extent;
5467 offset+=cache_info->columns;
5469 if (y < (ssize_t) rows)
5471 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5472 cache_info->cache_filename);
5473 return(MagickFalse);
5480 if ((cache_info->debug != MagickFalse) &&
5481 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5482 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5483 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5484 nexus_info->region.width,(double) nexus_info->region.height,(double)
5485 nexus_info->region.x,(double) nexus_info->region.y);
5490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5494 + W r i t e C a c h e P i x e l s %
5498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5500 % WritePixelCachePixels() writes image pixels to the specified region of the
5503 % The format of the WritePixelCachePixels() method is:
5505 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5506 % NexusInfo *nexus_info,ExceptionInfo *exception)
5508 % A description of each parameter follows:
5510 % o cache_info: the pixel cache.
5512 % o nexus_info: the cache nexus to write the pixels.
5514 % o exception: return any errors or warnings in this structure.
5517 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5518 NexusInfo *nexus_info,ExceptionInfo *exception)
5528 register const Quantum
5537 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5539 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5540 nexus_info->region.x;
5541 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5543 rows=nexus_info->region.height;
5545 p=nexus_info->pixels;
5546 switch (cache_info->type)
5555 Write pixels to memory.
5557 if ((cache_info->columns == nexus_info->region.width) &&
5558 (extent == (MagickSizeType) ((size_t) extent)))
5563 q=cache_info->pixels+offset*cache_info->number_channels;
5564 for (y=0; y < (ssize_t) rows; y++)
5566 (void) memcpy(q,p,(size_t) length);
5567 p+=nexus_info->region.width*cache_info->number_channels;
5568 q+=cache_info->columns*cache_info->number_channels;
5575 Write pixels to disk.
5577 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5579 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5580 cache_info->cache_filename);
5581 return(MagickFalse);
5583 if ((cache_info->columns == nexus_info->region.width) &&
5584 (extent <= MagickMaxBufferExtent))
5589 for (y=0; y < (ssize_t) rows; y++)
5591 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5592 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5594 if ((MagickSizeType) count != length)
5596 p+=nexus_info->region.width*cache_info->number_channels;
5597 offset+=cache_info->columns;
5599 if (y < (ssize_t) rows)
5601 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5602 cache_info->cache_filename);
5603 return(MagickFalse);
5610 if ((cache_info->debug != MagickFalse) &&
5611 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5612 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5613 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5614 nexus_info->region.width,(double) nexus_info->region.height,(double)
5615 nexus_info->region.x,(double) nexus_info->region.y);