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,
1031 if ((MagickSizeType) count != length)
1037 clone_offset+=length;
1040 length=clone_info->number_channels*sizeof(Quantum);
1041 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1042 for ( ; x < (ssize_t) clone_info->columns; x++)
1045 Set remaining columns with transparent pixel channels.
1047 if (clone_info->type != DiskCache)
1048 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1052 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1053 if ((MagickSizeType) count != length)
1059 clone_offset+=length;
1062 length=clone_info->number_channels*sizeof(Quantum);
1063 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1064 for ( ; y < (ssize_t) clone_info->rows; y++)
1067 Set remaining rows with transparent pixels.
1069 for (x=0; x < (ssize_t) clone_info->columns; x++)
1071 if (clone_info->type != DiskCache)
1072 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
1076 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1077 if ((MagickSizeType) count != length)
1083 clone_offset+=length;
1086 if ((cache_info->metacontent_extent != 0) &&
1087 (clone_info->metacontent_extent != 0))
1092 for (y=0; y < (ssize_t) cache_info->rows; y++)
1094 for (x=0; x < (ssize_t) cache_info->columns; x++)
1097 Read a set of metacontent.
1099 length=cache_info->metacontent_extent;
1100 if (cache_info->type != DiskCache)
1101 (void) memcpy(blob,(unsigned char *) cache_info->pixels+
1102 cache_offset,length);
1105 count=ReadPixelCacheRegion(cache_info,cache_offset,length,blob);
1106 if ((MagickSizeType) count != length)
1112 cache_offset+=length;
1113 if ((y < (ssize_t) clone_info->rows) &&
1114 (x < (ssize_t) clone_info->columns))
1117 Write a set of metacontent.
1119 length=clone_info->metacontent_extent;
1120 if (clone_info->type != DiskCache)
1121 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1125 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1127 if ((MagickSizeType) count != length)
1133 clone_offset+=length;
1136 length=clone_info->metacontent_extent;
1137 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1138 for ( ; x < (ssize_t) clone_info->columns; x++)
1141 Set remaining columns with metacontent.
1143 if (clone_info->type != DiskCache)
1144 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1148 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1150 if ((MagickSizeType) count != length)
1156 clone_offset+=length;
1159 length=clone_info->metacontent_extent;
1160 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1161 for ( ; y < (ssize_t) clone_info->rows; y++)
1164 Set remaining rows with metacontent.
1166 for (x=0; x < (ssize_t) clone_info->columns; x++)
1168 if (clone_info->type != DiskCache)
1169 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1173 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1174 if ((MagickSizeType) count != length)
1180 clone_offset+=length;
1184 if (clone_info->type == DiskCache)
1185 (void) ClosePixelCacheOnDisk(clone_info);
1186 if (cache_info->type == DiskCache)
1187 (void) ClosePixelCacheOnDisk(cache_info);
1188 blob=(unsigned char *) RelinquishMagickMemory(blob);
1192 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1193 CacheInfo *cache_info,ExceptionInfo *exception)
1195 if (cache_info->type == PingCache)
1197 if ((cache_info->columns == clone_info->columns) &&
1198 (cache_info->rows == clone_info->rows) &&
1199 (cache_info->number_channels == clone_info->number_channels) &&
1200 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1201 return(OptimizedPixelCacheClone(clone_info,cache_info,exception));
1202 return(UnoptimizedPixelCacheClone(clone_info,cache_info,exception));
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 + C l o n e P i x e l C a c h e M e t h o d s %
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1219 % The format of the ClonePixelCacheMethods() method is:
1221 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1223 % A description of each parameter follows:
1225 % o clone: Specifies a pointer to a Cache structure.
1227 % o cache: the pixel cache.
1230 MagickExport void ClonePixelCacheMethods(Cache clone,const Cache cache)
1236 assert(clone != (Cache) NULL);
1237 source_info=(CacheInfo *) clone;
1238 assert(source_info->signature == MagickSignature);
1239 if (source_info->debug != MagickFalse)
1240 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1241 source_info->filename);
1242 assert(cache != (Cache) NULL);
1243 cache_info=(CacheInfo *) cache;
1244 assert(cache_info->signature == MagickSignature);
1245 source_info->methods=cache_info->methods;
1249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1253 + D e s t r o y I m a g e P i x e l C a c h e %
1257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1261 % The format of the DestroyImagePixelCache() method is:
1263 % void DestroyImagePixelCache(Image *image)
1265 % A description of each parameter follows:
1267 % o image: the image.
1270 static void DestroyImagePixelCache(Image *image)
1272 assert(image != (Image *) NULL);
1273 assert(image->signature == MagickSignature);
1274 if (image->debug != MagickFalse)
1275 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1276 if (image->cache == (void *) NULL)
1278 image->cache=DestroyPixelCache(image->cache);
1282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1286 + D e s t r o y I m a g e P i x e l s %
1290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1294 % The format of the DestroyImagePixels() method is:
1296 % void DestroyImagePixels(Image *image)
1298 % A description of each parameter follows:
1300 % o image: the image.
1303 MagickExport void DestroyImagePixels(Image *image)
1308 assert(image != (const Image *) NULL);
1309 assert(image->signature == MagickSignature);
1310 if (image->debug != MagickFalse)
1311 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1312 assert(image->cache != (Cache) NULL);
1313 cache_info=(CacheInfo *) image->cache;
1314 assert(cache_info->signature == MagickSignature);
1315 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1317 cache_info->methods.destroy_pixel_handler(image);
1320 image->cache=DestroyPixelCache(image->cache);
1324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328 + D e s t r o y P i x e l C a c h e %
1332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1334 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1336 % The format of the DestroyPixelCache() method is:
1338 % Cache DestroyPixelCache(Cache cache)
1340 % A description of each parameter follows:
1342 % o cache: the pixel cache.
1346 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1348 switch (cache_info->type)
1352 if (cache_info->mapped == MagickFalse)
1353 cache_info->pixels=(Quantum *) RelinquishMagickMemory(
1354 cache_info->pixels);
1356 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1357 (size_t) cache_info->length);
1358 RelinquishMagickResource(MemoryResource,cache_info->length);
1363 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1364 cache_info->length);
1365 RelinquishMagickResource(MapResource,cache_info->length);
1369 if (cache_info->file != -1)
1370 (void) ClosePixelCacheOnDisk(cache_info);
1371 RelinquishMagickResource(DiskResource,cache_info->length);
1377 cache_info->type=UndefinedCache;
1378 cache_info->mapped=MagickFalse;
1379 cache_info->metacontent=(void *) NULL;
1382 MagickExport Cache DestroyPixelCache(Cache cache)
1387 assert(cache != (Cache) NULL);
1388 cache_info=(CacheInfo *) cache;
1389 assert(cache_info->signature == MagickSignature);
1390 if (cache_info->debug != MagickFalse)
1391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1392 cache_info->filename);
1393 LockSemaphoreInfo(cache_info->semaphore);
1394 cache_info->reference_count--;
1395 if (cache_info->reference_count != 0)
1397 UnlockSemaphoreInfo(cache_info->semaphore);
1398 return((Cache) NULL);
1400 UnlockSemaphoreInfo(cache_info->semaphore);
1401 if (cache_resources != (SplayTreeInfo *) NULL)
1402 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
1403 if (cache_info->debug != MagickFalse)
1406 message[MaxTextExtent];
1408 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1409 cache_info->filename);
1410 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1412 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1413 (cache_info->type != DiskCache)))
1414 RelinquishPixelCachePixels(cache_info);
1417 RelinquishPixelCachePixels(cache_info);
1418 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1420 *cache_info->cache_filename='\0';
1421 if (cache_info->nexus_info != (NexusInfo **) NULL)
1422 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1423 cache_info->number_threads);
1424 if (cache_info->random_info != (RandomInfo *) NULL)
1425 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1426 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1427 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1428 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1429 DestroySemaphoreInfo(&cache_info->semaphore);
1430 cache_info->signature=(~MagickSignature);
1431 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 + D e s t r o y P i x e l C a c h e N e x u s %
1445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1447 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1449 % The format of the DestroyPixelCacheNexus() method is:
1451 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1452 % const size_t number_threads)
1454 % A description of each parameter follows:
1456 % o nexus_info: the nexus to destroy.
1458 % o number_threads: the number of nexus threads.
1462 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1464 if (nexus_info->mapped == MagickFalse)
1465 (void) RelinquishMagickMemory(nexus_info->cache);
1467 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1468 nexus_info->cache=(Quantum *) NULL;
1469 nexus_info->pixels=(Quantum *) NULL;
1470 nexus_info->metacontent=(void *) NULL;
1471 nexus_info->length=0;
1472 nexus_info->mapped=MagickFalse;
1475 MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1476 const size_t number_threads)
1481 assert(nexus_info != (NexusInfo **) NULL);
1482 for (i=0; i < (ssize_t) number_threads; i++)
1484 if (nexus_info[i]->cache != (Quantum *) NULL)
1485 RelinquishCacheNexusPixels(nexus_info[i]);
1486 nexus_info[i]->signature=(~MagickSignature);
1487 nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]);
1489 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
1494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1498 % G e t A u t h e n t i c M e t a c o n t e n t %
1502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1505 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1506 % returned if the associated pixels are not available.
1508 % The format of the GetAuthenticMetacontent() method is:
1510 % void *GetAuthenticMetacontent(const Image *image)
1512 % A description of each parameter follows:
1514 % o image: the image.
1517 MagickExport void *GetAuthenticMetacontent(const Image *image)
1523 id = GetOpenMPThreadId();
1528 assert(image != (const Image *) NULL);
1529 assert(image->signature == MagickSignature);
1530 assert(image->cache != (Cache) NULL);
1531 cache_info=(CacheInfo *) image->cache;
1532 assert(cache_info->signature == MagickSignature);
1533 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1534 (GetAuthenticMetacontentFromHandler) NULL)
1536 metacontent=cache_info->methods.
1537 get_authentic_metacontent_from_handler(image);
1538 return(metacontent);
1540 assert(id < (int) cache_info->number_threads);
1541 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1542 cache_info->nexus_info[id]);
1543 return(metacontent);
1547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1551 + 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 %
1555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1557 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1558 % with the last call to QueueAuthenticPixelsCache() or
1559 % GetAuthenticPixelsCache().
1561 % The format of the GetAuthenticMetacontentFromCache() method is:
1563 % void *GetAuthenticMetacontentFromCache(const Image *image)
1565 % A description of each parameter follows:
1567 % o image: the image.
1570 static void *GetAuthenticMetacontentFromCache(const Image *image)
1576 id = GetOpenMPThreadId();
1581 assert(image != (const Image *) NULL);
1582 assert(image->signature == MagickSignature);
1583 assert(image->cache != (Cache) NULL);
1584 cache_info=(CacheInfo *) image->cache;
1585 assert(cache_info->signature == MagickSignature);
1586 assert(id < (int) cache_info->number_threads);
1587 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1588 cache_info->nexus_info[id]);
1589 return(metacontent);
1593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597 + 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 %
1601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1603 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1604 % disk pixel cache as defined by the geometry parameters. A pointer to the
1605 % pixels is returned if the pixels are transferred, otherwise a NULL is
1608 % The format of the GetAuthenticPixelCacheNexus() method is:
1610 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1611 % const ssize_t y,const size_t columns,const size_t rows,
1612 % NexusInfo *nexus_info,ExceptionInfo *exception)
1614 % A description of each parameter follows:
1616 % o image: the image.
1618 % o x,y,columns,rows: These values define the perimeter of a region of
1621 % o nexus_info: the cache nexus to return.
1623 % o exception: return any errors or warnings in this structure.
1627 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info,
1628 NexusInfo *nexus_info)
1636 if (cache_info->type == PingCache)
1638 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1639 nexus_info->region.x;
1640 status=nexus_info->pixels == (cache_info->pixels+offset*
1641 cache_info->number_channels) ? MagickTrue : MagickFalse;
1645 MagickExport Quantum *GetAuthenticPixelCacheNexus(Image *image,
1646 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1647 NexusInfo *nexus_info,ExceptionInfo *exception)
1656 Transfer pixels from the cache.
1658 assert(image != (Image *) NULL);
1659 assert(image->signature == MagickSignature);
1660 pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
1661 if (pixels == (Quantum *) NULL)
1662 return((Quantum *) NULL);
1663 cache_info=(CacheInfo *) image->cache;
1664 assert(cache_info->signature == MagickSignature);
1665 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1667 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1668 return((Quantum *) NULL);
1669 if (cache_info->metacontent_extent != 0)
1670 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1671 return((Quantum *) NULL);
1676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1680 + 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 %
1684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1687 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1689 % The format of the GetAuthenticPixelsFromCache() method is:
1691 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1693 % A description of each parameter follows:
1695 % o image: the image.
1698 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1704 id = GetOpenMPThreadId();
1706 assert(image != (const Image *) NULL);
1707 assert(image->signature == MagickSignature);
1708 assert(image->cache != (Cache) NULL);
1709 cache_info=(CacheInfo *) image->cache;
1710 assert(cache_info->signature == MagickSignature);
1711 assert(id < (int) cache_info->number_threads);
1712 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1720 % G e t A u t h e n t i c P i x e l Q u e u e %
1724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1726 % GetAuthenticPixelQueue() returns the authentic pixels associated
1727 % corresponding with the last call to QueueAuthenticPixels() or
1728 % GetAuthenticPixels().
1730 % The format of the GetAuthenticPixelQueue() method is:
1732 % Quantum *GetAuthenticPixelQueue(const Image image)
1734 % A description of each parameter follows:
1736 % o image: the image.
1739 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1745 id = GetOpenMPThreadId();
1747 assert(image != (const Image *) NULL);
1748 assert(image->signature == MagickSignature);
1749 assert(image->cache != (Cache) NULL);
1750 cache_info=(CacheInfo *) image->cache;
1751 assert(cache_info->signature == MagickSignature);
1752 if (cache_info->methods.get_authentic_pixels_from_handler !=
1753 (GetAuthenticPixelsFromHandler) NULL)
1754 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1755 assert(id < (int) cache_info->number_threads);
1756 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1764 % G e t A u t h e n t i c P i x e l s %
1767 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1769 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1770 % region is successfully accessed, a pointer to a Quantum array
1771 % representing the region is returned, otherwise NULL is returned.
1773 % The returned pointer may point to a temporary working copy of the pixels
1774 % or it may point to the original pixels in memory. Performance is maximized
1775 % if the selected region is part of one row, or one or more full rows, since
1776 % then there is opportunity to access the pixels in-place (without a copy)
1777 % if the image is in memory, or in a memory-mapped file. The returned pointer
1778 % must *never* be deallocated by the user.
1780 % Pixels accessed via the returned pointer represent a simple array of type
1781 % Quantum. If the image has corresponding metacontent,call
1782 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1783 % meta-content corresponding to the region. Once the Quantum array has
1784 % been updated, the changes must be saved back to the underlying image using
1785 % SyncAuthenticPixels() or they may be lost.
1787 % The format of the GetAuthenticPixels() method is:
1789 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1790 % const ssize_t y,const size_t columns,const size_t rows,
1791 % ExceptionInfo *exception)
1793 % A description of each parameter follows:
1795 % o image: the image.
1797 % o x,y,columns,rows: These values define the perimeter of a region of
1800 % o exception: return any errors or warnings in this structure.
1803 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1804 const ssize_t y,const size_t columns,const size_t rows,
1805 ExceptionInfo *exception)
1811 id = GetOpenMPThreadId();
1816 assert(image != (Image *) NULL);
1817 assert(image->signature == MagickSignature);
1818 assert(image->cache != (Cache) NULL);
1819 cache_info=(CacheInfo *) image->cache;
1820 assert(cache_info->signature == MagickSignature);
1821 if (cache_info->methods.get_authentic_pixels_handler !=
1822 (GetAuthenticPixelsHandler) NULL)
1824 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1828 assert(id < (int) cache_info->number_threads);
1829 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1830 cache_info->nexus_info[id],exception);
1835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1839 + G e t A u t h e n t i c P i x e l s C a c h e %
1843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1845 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1846 % as defined by the geometry parameters. A pointer to the pixels is returned
1847 % if the pixels are transferred, otherwise a NULL is returned.
1849 % The format of the GetAuthenticPixelsCache() method is:
1851 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1852 % const ssize_t y,const size_t columns,const size_t rows,
1853 % ExceptionInfo *exception)
1855 % A description of each parameter follows:
1857 % o image: the image.
1859 % o x,y,columns,rows: These values define the perimeter of a region of
1862 % o exception: return any errors or warnings in this structure.
1865 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1866 const ssize_t y,const size_t columns,const size_t rows,
1867 ExceptionInfo *exception)
1873 id = GetOpenMPThreadId();
1878 assert(image != (const Image *) NULL);
1879 assert(image->signature == MagickSignature);
1880 assert(image->cache != (Cache) NULL);
1881 cache_info=(CacheInfo *) image->cache;
1882 if (cache_info == (Cache) NULL)
1883 return((Quantum *) NULL);
1884 assert(cache_info->signature == MagickSignature);
1885 assert(id < (int) cache_info->number_threads);
1886 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1887 cache_info->nexus_info[id],exception);
1892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1896 + G e t I m a g e E x t e n t %
1900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1902 % GetImageExtent() returns the extent of the pixels associated corresponding
1903 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1905 % The format of the GetImageExtent() method is:
1907 % MagickSizeType GetImageExtent(const Image *image)
1909 % A description of each parameter follows:
1911 % o image: the image.
1914 MagickExport MagickSizeType GetImageExtent(const Image *image)
1920 id = GetOpenMPThreadId();
1922 assert(image != (Image *) NULL);
1923 assert(image->signature == MagickSignature);
1924 if (image->debug != MagickFalse)
1925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1926 assert(image->cache != (Cache) NULL);
1927 cache_info=(CacheInfo *) image->cache;
1928 assert(cache_info->signature == MagickSignature);
1929 assert(id < (int) cache_info->number_threads);
1930 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1938 + G e t I m a g e P i x e l C a c h e %
1942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1944 % GetImagePixelCache() ensures that there is only a single reference to the
1945 % pixel cache to be modified, updating the provided cache pointer to point to
1946 % a clone of the original pixel cache if necessary.
1948 % The format of the GetImagePixelCache method is:
1950 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1951 % ExceptionInfo *exception)
1953 % A description of each parameter follows:
1955 % o image: the image.
1957 % o clone: any value other than MagickFalse clones the cache pixels.
1959 % o exception: return any errors or warnings in this structure.
1962 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
1968 Does the image match the pixel cache morphology?
1970 cache_info=(CacheInfo *) image->cache;
1971 if ((image->storage_class != cache_info->storage_class) ||
1972 (image->colorspace != cache_info->colorspace) ||
1973 (image->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
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_genesis=time((time_t *) NULL);
2031 if ((time_limit != MagickResourceInfinity) &&
2032 ((MagickSizeType) (time((time_t *) NULL)-cache_genesis) >= 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)
2064 image->cache=clone_image.cache;
2067 DestroySemaphoreInfo(&clone_image.semaphore);
2069 UnlockSemaphoreInfo(cache_info->semaphore);
2071 if (destroy != MagickFalse)
2072 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
2073 if (status != MagickFalse)
2076 Ensure the image matches the pixel cache morphology.
2078 image->taint=MagickTrue;
2079 image->type=UndefinedType;
2080 if (image->colorspace == GRAYColorspace)
2081 image->colorspace=RGBColorspace;
2082 if (ValidatePixelCacheMorphology(image) == MagickFalse)
2083 status=OpenPixelCache(image,IOMode,exception);
2085 UnlockSemaphoreInfo(image->semaphore);
2086 if (status == MagickFalse)
2087 return((Cache) NULL);
2088 return(image->cache);
2092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096 % G e t O n e A u t h e n t i c P i x e l %
2100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2102 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2103 % location. The image background color is returned if an error occurs.
2105 % The format of the GetOneAuthenticPixel() method is:
2107 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2108 % const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2110 % A description of each parameter follows:
2112 % o image: the image.
2114 % o x,y: These values define the location of the pixel to return.
2116 % o pixel: return a pixel at the specified (x,y) location.
2118 % o exception: return any errors or warnings in this structure.
2121 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2122 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2130 assert(image != (Image *) NULL);
2131 assert(image->signature == MagickSignature);
2132 assert(image->cache != (Cache) NULL);
2133 cache_info=(CacheInfo *) image->cache;
2134 assert(cache_info->signature == MagickSignature);
2135 *pixel=image->background_color;
2136 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2137 (GetOneAuthenticPixelFromHandler) NULL)
2138 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2140 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2141 if (q == (Quantum *) NULL)
2142 return(MagickFalse);
2143 GetPixelPacket(image,q,pixel);
2148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2152 + G e t O n e A u t h e n t i c P i x e l F r o m C a c h e %
2156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2158 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2159 % location. The image background color is returned if an error occurs.
2161 % The format of the GetOneAuthenticPixelFromCache() method is:
2163 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2164 % const ssize_t x,const ssize_t y,PixelPacket *pixel,
2165 % ExceptionInfo *exception)
2167 % A description of each parameter follows:
2169 % o image: the image.
2171 % o x,y: These values define the location of the pixel to return.
2173 % o pixel: return a pixel at the specified (x,y) location.
2175 % o exception: return any errors or warnings in this structure.
2178 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2179 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2185 id = GetOpenMPThreadId();
2190 assert(image != (const Image *) NULL);
2191 assert(image->signature == MagickSignature);
2192 assert(image->cache != (Cache) NULL);
2193 cache_info=(CacheInfo *) image->cache;
2194 assert(cache_info->signature == MagickSignature);
2195 assert(id < (int) cache_info->number_threads);
2196 *pixel=image->background_color;
2197 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2199 if (q == (Quantum *) NULL)
2200 return(MagickFalse);
2201 GetPixelPacket(image,q,pixel);
2206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2210 % G e t O n e V i r t u a l M a g i c k P i x e l %
2214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2216 % GetOneVirtualMagickPixel() returns a single pixel at the specified (x,y)
2217 % location. The image background color is returned if an error occurs. If
2218 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2220 % The format of the GetOneVirtualMagickPixel() method is:
2222 % MagickBooleanType GetOneVirtualMagickPixel(const Image image,
2223 % const ssize_t x,const ssize_t y,PixelInfo *pixel,
2224 % ExceptionInfo exception)
2226 % A description of each parameter follows:
2228 % o image: the image.
2230 % o x,y: these values define the location of the pixel to return.
2232 % o pixel: return a pixel at the specified (x,y) location.
2234 % o exception: return any errors or warnings in this structure.
2237 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
2238 const ssize_t x,const ssize_t y,PixelInfo *pixel,
2239 ExceptionInfo *exception)
2245 id = GetOpenMPThreadId();
2247 register const Quantum
2250 assert(image != (const Image *) NULL);
2251 assert(image->signature == MagickSignature);
2252 assert(image->cache != (Cache) NULL);
2253 cache_info=(CacheInfo *) image->cache;
2254 assert(cache_info->signature == MagickSignature);
2255 assert(id < (int) cache_info->number_threads);
2256 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2257 1UL,1UL,cache_info->nexus_info[id],exception);
2258 GetPixelInfo(image,pixel);
2259 if (pixels == (const Quantum *) NULL)
2260 return(MagickFalse);
2261 SetPixelInfo(image,pixels,pixel);
2266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270 % G e t O n e V i r t u a l M e t h o d P i x e l %
2274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2276 % GetOneVirtualMethodPixel() returns a single pixel at the specified (x,y)
2277 % location as defined by specified pixel method. The image background color
2278 % is returned if an error occurs. If you plan to modify the pixel, use
2279 % GetOneAuthenticPixel() instead.
2281 % The format of the GetOneVirtualMethodPixel() method is:
2283 % MagickBooleanType GetOneVirtualMethodPixel(const Image image,
2284 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2285 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2287 % A description of each parameter follows:
2289 % o image: the image.
2291 % o virtual_pixel_method: the virtual pixel method.
2293 % o x,y: These values define the location of the pixel to return.
2295 % o pixel: return a pixel at the specified (x,y) location.
2297 % o exception: return any errors or warnings in this structure.
2300 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
2301 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2302 PixelPacket *pixel,ExceptionInfo *exception)
2308 id = GetOpenMPThreadId();
2313 assert(image != (const Image *) NULL);
2314 assert(image->signature == MagickSignature);
2315 assert(image->cache != (Cache) NULL);
2316 cache_info=(CacheInfo *) image->cache;
2317 assert(cache_info->signature == MagickSignature);
2318 *pixel=image->background_color;
2319 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2320 (GetOneVirtualPixelFromHandler) NULL)
2321 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2322 virtual_pixel_method,x,y,pixel,exception));
2323 assert(id < (int) cache_info->number_threads);
2324 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2325 cache_info->nexus_info[id],exception);
2326 if (p == (const Quantum *) NULL)
2327 return(MagickFalse);
2328 GetPixelPacket(image,p,pixel);
2329 if (image->colorspace == CMYKColorspace)
2330 pixel->black=GetPixelBlack(image,p);
2335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2339 % G e t O n e V i r t u a l P i x e l %
2343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2345 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2346 % (x,y) location. The image background color is returned if an error occurs.
2347 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2349 % The format of the GetOneVirtualPixel() method is:
2351 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2352 % const ssize_t y,PixelPacket *pixel,ExceptionInfo exception)
2354 % A description of each parameter follows:
2356 % o image: the image.
2358 % o x,y: These values define the location of the pixel to return.
2360 % o pixel: return a pixel at the specified (x,y) location.
2362 % o exception: return any errors or warnings in this structure.
2365 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2366 const ssize_t x,const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2372 id = GetOpenMPThreadId();
2377 assert(image != (const Image *) NULL);
2378 assert(image->signature == MagickSignature);
2379 assert(image->cache != (Cache) NULL);
2380 cache_info=(CacheInfo *) image->cache;
2381 assert(cache_info->signature == MagickSignature);
2382 *pixel=image->background_color;
2383 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2384 (GetOneVirtualPixelFromHandler) NULL)
2385 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2386 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2387 assert(id < (int) cache_info->number_threads);
2388 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2389 1UL,1UL,cache_info->nexus_info[id],exception);
2390 if (p == (const Quantum *) NULL)
2391 return(MagickFalse);
2392 GetPixelPacket(image,p,pixel);
2393 if (image->colorspace == CMYKColorspace)
2394 pixel->black=GetPixelBlack(image,p);
2399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2403 + G e t O n e V i r t u a l P i x e l F r o m C a c h e %
2407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2409 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2410 % specified (x,y) location. The image background color is returned if an
2413 % The format of the GetOneVirtualPixelFromCache() method is:
2415 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2416 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2417 % PixelPacket *pixel,ExceptionInfo *exception)
2419 % A description of each parameter follows:
2421 % o image: the image.
2423 % o virtual_pixel_method: the virtual pixel method.
2425 % o x,y: These values define the location of the pixel to return.
2427 % o pixel: return a pixel at the specified (x,y) location.
2429 % o exception: return any errors or warnings in this structure.
2432 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2433 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2434 PixelPacket *pixel,ExceptionInfo *exception)
2440 id = GetOpenMPThreadId();
2445 assert(image != (const Image *) NULL);
2446 assert(image->signature == MagickSignature);
2447 assert(image->cache != (Cache) NULL);
2448 cache_info=(CacheInfo *) image->cache;
2449 assert(cache_info->signature == MagickSignature);
2450 assert(id < (int) cache_info->number_threads);
2451 *pixel=image->background_color;
2452 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2453 cache_info->nexus_info[id],exception);
2454 if (p == (const Quantum *) NULL)
2455 return(MagickFalse);
2456 GetPixelPacket(image,p,pixel);
2457 if (image->colorspace == CMYKColorspace)
2458 pixel->black=GetPixelBlack(image,p);
2463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2467 + G e t P i x e l C a c h e C o l o r s p a c e %
2471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2473 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2475 % The format of the GetPixelCacheColorspace() method is:
2477 % Colorspace GetPixelCacheColorspace(Cache cache)
2479 % A description of each parameter follows:
2481 % o cache: the pixel cache.
2484 MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
2489 assert(cache != (Cache) NULL);
2490 cache_info=(CacheInfo *) cache;
2491 assert(cache_info->signature == MagickSignature);
2492 if (cache_info->debug != MagickFalse)
2493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2494 cache_info->filename);
2495 return(cache_info->colorspace);
2499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2503 + G e t P i x e l C a c h e M e t h o d s %
2507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2509 % GetPixelCacheMethods() initializes the CacheMethods structure.
2511 % The format of the GetPixelCacheMethods() method is:
2513 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2515 % A description of each parameter follows:
2517 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2520 MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
2522 assert(cache_methods != (CacheMethods *) NULL);
2523 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2524 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2525 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2526 cache_methods->get_virtual_metacontent_from_handler=
2527 GetVirtualMetacontentFromCache;
2528 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2529 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2530 cache_methods->get_authentic_metacontent_from_handler=
2531 GetAuthenticMetacontentFromCache;
2532 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2533 cache_methods->get_one_authentic_pixel_from_handler=
2534 GetOneAuthenticPixelFromCache;
2535 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2536 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2537 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2545 + G e t P i x e l C a c h e N e x u s E x t e n t %
2549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2551 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2552 % corresponding with the last call to SetPixelCacheNexusPixels() or
2553 % GetPixelCacheNexusPixels().
2555 % The format of the GetPixelCacheNexusExtent() method is:
2557 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2558 % NexusInfo *nexus_info)
2560 % A description of each parameter follows:
2562 % o nexus_info: the nexus info.
2565 MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2566 NexusInfo *nexus_info)
2574 assert(cache != (const Cache) NULL);
2575 cache_info=(CacheInfo *) cache;
2576 assert(cache_info->signature == MagickSignature);
2577 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2579 return((MagickSizeType) cache_info->columns*cache_info->rows);
2584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2588 + G e t P i x e l C a c h e N e x u s M e t a c o n t e n t %
2592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2594 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2597 % The format of the GetPixelCacheNexusMetacontent() method is:
2599 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2600 % NexusInfo *nexus_info)
2602 % A description of each parameter follows:
2604 % o cache: the pixel cache.
2606 % o nexus_info: the cache nexus to return the meta-content.
2609 MagickExport void *GetPixelCacheNexusMetacontent(const Cache cache,
2610 NexusInfo *nexus_info)
2615 assert(cache != (const Cache) NULL);
2616 cache_info=(CacheInfo *) cache;
2617 assert(cache_info->signature == MagickSignature);
2618 if (cache_info->storage_class == UndefinedClass)
2619 return((void *) NULL);
2620 return(nexus_info->metacontent);
2624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2628 + G e t P i x e l C a c h e N e x u s P i x e l s %
2632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2637 % The format of the GetPixelCacheNexusPixels() method is:
2639 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2640 % NexusInfo *nexus_info)
2642 % A description of each parameter follows:
2644 % o cache: the pixel cache.
2646 % o nexus_info: the cache nexus to return the pixels.
2649 MagickExport Quantum *GetPixelCacheNexusPixels(const Cache cache,
2650 NexusInfo *nexus_info)
2655 assert(cache != (const Cache) NULL);
2656 cache_info=(CacheInfo *) cache;
2657 assert(cache_info->signature == MagickSignature);
2658 if (cache_info->storage_class == UndefinedClass)
2659 return((Quantum *) NULL);
2660 return(nexus_info->pixels);
2664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2668 + G e t P i x e l C a c h e P i x e l s %
2672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2674 % GetPixelCachePixels() returns the pixels associated with the specified image.
2676 % The format of the GetPixelCachePixels() method is:
2678 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2679 % ExceptionInfo *exception)
2681 % A description of each parameter follows:
2683 % o image: the image.
2685 % o length: the pixel cache length.
2687 % o exception: return any errors or warnings in this structure.
2690 MagickExport void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2691 ExceptionInfo *exception)
2696 assert(image != (const Image *) NULL);
2697 assert(image->signature == MagickSignature);
2698 assert(image->cache != (Cache) NULL);
2699 assert(length != (MagickSizeType *) NULL);
2700 assert(exception != (ExceptionInfo *) NULL);
2701 assert(exception->signature == MagickSignature);
2702 cache_info=(CacheInfo *) image->cache;
2703 assert(cache_info->signature == MagickSignature);
2705 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2706 return((void *) NULL);
2707 *length=cache_info->length;
2708 return((void *) cache_info->pixels);
2712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2716 + G e t P i x e l C a c h e S t o r a g e C l a s s %
2720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2722 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2724 % The format of the GetPixelCacheStorageClass() method is:
2726 % ClassType GetPixelCacheStorageClass(Cache cache)
2728 % A description of each parameter follows:
2730 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2732 % o cache: the pixel cache.
2735 MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
2740 assert(cache != (Cache) NULL);
2741 cache_info=(CacheInfo *) cache;
2742 assert(cache_info->signature == MagickSignature);
2743 if (cache_info->debug != MagickFalse)
2744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2745 cache_info->filename);
2746 return(cache_info->storage_class);
2750 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2754 + G e t P i x e l C a c h e T i l e S i z e %
2758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2760 % GetPixelCacheTileSize() returns the pixel cache tile size.
2762 % The format of the GetPixelCacheTileSize() method is:
2764 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2767 % A description of each parameter follows:
2769 % o image: the image.
2771 % o width: the optimize cache tile width in pixels.
2773 % o height: the optimize cache tile height in pixels.
2776 MagickExport void GetPixelCacheTileSize(const Image *image,size_t *width,
2782 assert(image != (Image *) NULL);
2783 assert(image->signature == MagickSignature);
2784 if (image->debug != MagickFalse)
2785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2786 cache_info=(CacheInfo *) image->cache;
2787 assert(cache_info->signature == MagickSignature);
2788 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2789 if (GetPixelCacheType(image) == DiskCache)
2790 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2799 + G e t P i x e l C a c h e T y p e %
2803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2805 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.).
2807 % The format of the GetPixelCacheType() method is:
2809 % CacheType GetPixelCacheType(const Image *image)
2811 % A description of each parameter follows:
2813 % o image: the image.
2816 MagickExport CacheType GetPixelCacheType(const Image *image)
2821 assert(image != (Image *) NULL);
2822 assert(image->signature == MagickSignature);
2823 assert(image->cache != (Cache) NULL);
2824 cache_info=(CacheInfo *) image->cache;
2825 assert(cache_info->signature == MagickSignature);
2826 return(cache_info->type);
2830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2834 + G e t P i x e l C a c h e V i r t u a l M e t h o d %
2838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2840 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2841 % pixel cache. A virtual pixel is any pixel access that is outside the
2842 % boundaries of the image cache.
2844 % The format of the GetPixelCacheVirtualMethod() method is:
2846 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2848 % A description of each parameter follows:
2850 % o image: the image.
2853 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2858 assert(image != (Image *) NULL);
2859 assert(image->signature == MagickSignature);
2860 assert(image->cache != (Cache) NULL);
2861 cache_info=(CacheInfo *) image->cache;
2862 assert(cache_info->signature == MagickSignature);
2863 return(cache_info->virtual_pixel_method);
2867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2871 + G e t V i r t u a l M e t a c o n t e n t F r o m C a c h e %
2875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2878 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2880 % The format of the GetVirtualMetacontentFromCache() method is:
2882 % void *GetVirtualMetacontentFromCache(const Image *image)
2884 % A description of each parameter follows:
2886 % o image: the image.
2889 static const void *GetVirtualMetacontentFromCache(const Image *image)
2895 id = GetOpenMPThreadId();
2900 assert(image != (const Image *) NULL);
2901 assert(image->signature == MagickSignature);
2902 assert(image->cache != (Cache) NULL);
2903 cache_info=(CacheInfo *) image->cache;
2904 assert(cache_info->signature == MagickSignature);
2905 assert(id < (int) cache_info->number_threads);
2906 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2907 cache_info->nexus_info[id]);
2908 return(metacontent);
2912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2916 + G e t V i r t u a l M e t a c o n t e n t F r o m N e x u s %
2920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2922 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2925 % The format of the GetVirtualMetacontentFromNexus() method is:
2927 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2928 % NexusInfo *nexus_info)
2930 % A description of each parameter follows:
2932 % o cache: the pixel cache.
2934 % o nexus_info: the cache nexus to return the meta-content.
2937 MagickExport const void *GetVirtualMetacontentFromNexus(const Cache cache,
2938 NexusInfo *nexus_info)
2943 assert(cache != (Cache) NULL);
2944 cache_info=(CacheInfo *) cache;
2945 assert(cache_info->signature == MagickSignature);
2946 if (cache_info->storage_class == UndefinedClass)
2947 return((void *) NULL);
2948 return(nexus_info->metacontent);
2952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956 % G e t V i r t u a l M e t a c o n t e n t %
2960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2962 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2963 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2964 % returned if the meta-content are not available.
2966 % The format of the GetVirtualMetacontent() method is:
2968 % const void *GetVirtualMetacontent(const Image *image)
2970 % A description of each parameter follows:
2972 % o image: the image.
2975 MagickExport const void *GetVirtualMetacontent(const Image *image)
2981 id = GetOpenMPThreadId();
2986 assert(image != (const Image *) NULL);
2987 assert(image->signature == MagickSignature);
2988 assert(image->cache != (Cache) NULL);
2989 cache_info=(CacheInfo *) image->cache;
2990 assert(cache_info->signature == MagickSignature);
2991 if (cache_info->methods.get_virtual_metacontent_from_handler !=
2992 (GetVirtualMetacontentFromHandler) NULL)
2994 metacontent=cache_info->methods.
2995 get_virtual_metacontent_from_handler(image);
2996 return(metacontent);
2998 assert(id < (int) cache_info->number_threads);
2999 metacontent=GetVirtualMetacontentFromNexus(cache_info,
3000 cache_info->nexus_info[id]);
3001 return(metacontent);
3005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3009 + G e t V i r t u a l P i x e l s F r o m N e x u s %
3013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3015 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
3016 % pixel cache as defined by the geometry parameters. A pointer to the pixels
3017 % is returned if the pixels are transferred, otherwise a NULL is returned.
3019 % The format of the GetVirtualPixelsFromNexus() method is:
3021 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
3022 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
3023 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
3024 % ExceptionInfo *exception)
3026 % A description of each parameter follows:
3028 % o image: the image.
3030 % o virtual_pixel_method: the virtual pixel method.
3032 % o x,y,columns,rows: These values define the perimeter of a region of
3035 % o nexus_info: the cache nexus to acquire.
3037 % o exception: return any errors or warnings in this structure.
3044 0, 48, 12, 60, 3, 51, 15, 63,
3045 32, 16, 44, 28, 35, 19, 47, 31,
3046 8, 56, 4, 52, 11, 59, 7, 55,
3047 40, 24, 36, 20, 43, 27, 39, 23,
3048 2, 50, 14, 62, 1, 49, 13, 61,
3049 34, 18, 46, 30, 33, 17, 45, 29,
3050 10, 58, 6, 54, 9, 57, 5, 53,
3051 42, 26, 38, 22, 41, 25, 37, 21
3054 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
3059 index=x+DitherMatrix[x & 0x07]-32L;
3062 if (index >= (ssize_t) columns)
3063 return((ssize_t) columns-1L);
3067 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
3072 index=y+DitherMatrix[y & 0x07]-32L;
3075 if (index >= (ssize_t) rows)
3076 return((ssize_t) rows-1L);
3080 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
3084 if (x >= (ssize_t) columns)
3085 return((ssize_t) (columns-1));
3089 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
3093 if (y >= (ssize_t) rows)
3094 return((ssize_t) (rows-1));
3098 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
3100 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
3103 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
3105 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
3108 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3109 const size_t extent)
3115 Compute the remainder of dividing offset by extent. It returns not only
3116 the quotient (tile the offset falls in) but also the positive remainer
3117 within that tile such that 0 <= remainder < extent. This method is
3118 essentially a ldiv() using a floored modulo division rather than the
3119 normal default truncated modulo division.
3121 modulo.quotient=offset/(ssize_t) extent;
3124 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3128 MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3129 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3130 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3131 ExceptionInfo *exception)
3148 virtual_pixel[MaxPixelChannels];
3153 register const Quantum
3166 register unsigned char
3173 *virtual_metacontent;
3178 assert(image != (const Image *) NULL);
3179 assert(image->signature == MagickSignature);
3180 assert(image->cache != (Cache) NULL);
3181 cache_info=(CacheInfo *) image->cache;
3182 assert(cache_info->signature == MagickSignature);
3183 if (cache_info->type == UndefinedCache)
3184 return((const Quantum *) NULL);
3187 region.width=columns;
3189 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3190 if (pixels == (Quantum *) NULL)
3191 return((const Quantum *) NULL);
3192 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3193 nexus_info->region.x;
3194 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3195 nexus_info->region.width-1L;
3196 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3197 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3198 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3199 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3205 Pixel request is inside cache extents.
3207 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3209 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3210 if (status == MagickFalse)
3211 return((const Quantum *) NULL);
3212 if (cache_info->metacontent_extent != 0)
3214 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3215 if (status == MagickFalse)
3216 return((const Quantum *) NULL);
3221 Pixel request is outside cache extents.
3224 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3225 virtual_nexus=AcquirePixelCacheNexus(1);
3226 if (virtual_nexus == (NexusInfo **) NULL)
3228 if (virtual_nexus != (NexusInfo **) NULL)
3229 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3230 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3231 "UnableToGetCacheNexus","`%s'",image->filename);
3232 return((const Quantum *) NULL);
3234 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3235 sizeof(*virtual_pixel));
3236 virtual_metacontent=(void *) NULL;
3237 switch (virtual_pixel_method)
3239 case BackgroundVirtualPixelMethod:
3240 case BlackVirtualPixelMethod:
3241 case GrayVirtualPixelMethod:
3242 case TransparentVirtualPixelMethod:
3243 case MaskVirtualPixelMethod:
3244 case WhiteVirtualPixelMethod:
3245 case EdgeVirtualPixelMethod:
3246 case CheckerTileVirtualPixelMethod:
3247 case HorizontalTileVirtualPixelMethod:
3248 case VerticalTileVirtualPixelMethod:
3250 if (cache_info->metacontent_extent != 0)
3253 Acquire a metacontent buffer.
3255 virtual_metacontent=(void *) AcquireAlignedMemory(1,
3256 cache_info->metacontent_extent);
3257 if (virtual_metacontent == (void *) NULL)
3259 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3260 (void) ThrowMagickException(exception,GetMagickModule(),
3261 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3262 return((const Quantum *) NULL);
3264 (void) ResetMagickMemory(virtual_metacontent,0,
3265 cache_info->metacontent_extent);
3267 switch (virtual_pixel_method)
3269 case BlackVirtualPixelMethod:
3271 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3272 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3273 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3276 case GrayVirtualPixelMethod:
3278 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3279 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,virtual_pixel);
3280 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3283 case TransparentVirtualPixelMethod:
3285 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3286 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3287 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3290 case MaskVirtualPixelMethod:
3291 case WhiteVirtualPixelMethod:
3293 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3294 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3295 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3300 SetPixelRed(image,image->background_color.red,virtual_pixel);
3301 SetPixelGreen(image,image->background_color.green,virtual_pixel);
3302 SetPixelBlue(image,image->background_color.blue,virtual_pixel);
3303 if (image->colorspace == CMYKColorspace)
3304 SetPixelBlack(image,image->background_color.black,virtual_pixel);
3305 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3314 for (v=0; v < (ssize_t) rows; v++)
3316 for (u=0; u < (ssize_t) columns; u+=length)
3318 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3319 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3320 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3328 Transfer a single pixel.
3330 length=(MagickSizeType) 1;
3331 switch (virtual_pixel_method)
3335 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3336 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3337 1UL,1UL,*virtual_nexus,exception);
3338 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3341 case RandomVirtualPixelMethod:
3343 if (cache_info->random_info == (RandomInfo *) NULL)
3344 cache_info->random_info=AcquireRandomInfo();
3345 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3346 RandomX(cache_info->random_info,cache_info->columns),
3347 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3348 *virtual_nexus,exception);
3349 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3352 case DitherVirtualPixelMethod:
3354 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3355 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3356 1UL,1UL,*virtual_nexus,exception);
3357 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3360 case TileVirtualPixelMethod:
3362 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3363 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3364 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3365 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3367 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3370 case MirrorVirtualPixelMethod:
3372 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3373 if ((x_modulo.quotient & 0x01) == 1L)
3374 x_modulo.remainder=(ssize_t) cache_info->columns-
3375 x_modulo.remainder-1L;
3376 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3377 if ((y_modulo.quotient & 0x01) == 1L)
3378 y_modulo.remainder=(ssize_t) cache_info->rows-
3379 y_modulo.remainder-1L;
3380 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3381 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3383 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3386 case HorizontalTileEdgeVirtualPixelMethod:
3388 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3389 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3390 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3391 *virtual_nexus,exception);
3392 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3395 case VerticalTileEdgeVirtualPixelMethod:
3397 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3398 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3399 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3400 *virtual_nexus,exception);
3401 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3404 case BackgroundVirtualPixelMethod:
3405 case BlackVirtualPixelMethod:
3406 case GrayVirtualPixelMethod:
3407 case TransparentVirtualPixelMethod:
3408 case MaskVirtualPixelMethod:
3409 case WhiteVirtualPixelMethod:
3412 r=virtual_metacontent;
3415 case EdgeVirtualPixelMethod:
3416 case CheckerTileVirtualPixelMethod:
3418 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3419 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3420 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3423 r=virtual_metacontent;
3426 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3427 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3429 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3432 case HorizontalTileVirtualPixelMethod:
3434 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3437 r=virtual_metacontent;
3440 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3441 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3442 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3443 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3445 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3448 case VerticalTileVirtualPixelMethod:
3450 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3453 r=virtual_metacontent;
3456 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3457 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3458 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3459 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3461 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3465 if (p == (const Quantum *) NULL)
3467 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3469 q+=cache_info->number_channels;
3470 if ((s != (void *) NULL) && (r != (const void *) NULL))
3472 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3473 s+=cache_info->metacontent_extent;
3478 Transfer a run of pixels.
3480 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3481 length,1UL,*virtual_nexus,exception);
3482 if (p == (const Quantum *) NULL)
3484 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3485 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3486 q+=length*cache_info->number_channels;
3487 if ((r != (void *) NULL) && (s != (const void *) NULL))
3489 (void) memcpy(s,r,(size_t) length);
3490 s+=length*cache_info->metacontent_extent;
3497 if (virtual_metacontent != (void *) NULL)
3498 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3499 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3508 + G e t V i r t u a l P i x e l C a c h e %
3512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3514 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3515 % cache as defined by the geometry parameters. A pointer to the pixels
3516 % is returned if the pixels are transferred, otherwise a NULL is returned.
3518 % The format of the GetVirtualPixelCache() method is:
3520 % const Quantum *GetVirtualPixelCache(const Image *image,
3521 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3522 % const ssize_t y,const size_t columns,const size_t rows,
3523 % ExceptionInfo *exception)
3525 % A description of each parameter follows:
3527 % o image: the image.
3529 % o virtual_pixel_method: the virtual pixel method.
3531 % o x,y,columns,rows: These values define the perimeter of a region of
3534 % o exception: return any errors or warnings in this structure.
3537 static const Quantum *GetVirtualPixelCache(const Image *image,
3538 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3539 const size_t columns,const size_t rows,ExceptionInfo *exception)
3545 id = GetOpenMPThreadId();
3550 assert(image != (const Image *) NULL);
3551 assert(image->signature == MagickSignature);
3552 assert(image->cache != (Cache) NULL);
3553 cache_info=(CacheInfo *) image->cache;
3554 assert(cache_info->signature == MagickSignature);
3555 assert(id < (int) cache_info->number_threads);
3556 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3557 cache_info->nexus_info[id],exception);
3562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3566 % G e t V i r t u a l P i x e l Q u e u e %
3570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3572 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3573 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3575 % The format of the GetVirtualPixelQueue() method is:
3577 % const Quantum *GetVirtualPixelQueue(const Image image)
3579 % A description of each parameter follows:
3581 % o image: the image.
3584 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3590 id = GetOpenMPThreadId();
3592 assert(image != (const Image *) NULL);
3593 assert(image->signature == MagickSignature);
3594 assert(image->cache != (Cache) NULL);
3595 cache_info=(CacheInfo *) image->cache;
3596 assert(cache_info->signature == MagickSignature);
3597 if (cache_info->methods.get_virtual_pixels_handler !=
3598 (GetVirtualPixelsHandler) NULL)
3599 return(cache_info->methods.get_virtual_pixels_handler(image));
3600 assert(id < (int) cache_info->number_threads);
3601 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3609 % G e t V i r t u a l P i x e l s %
3613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3615 % GetVirtualPixels() returns an immutable pixel region. If the
3616 % region is successfully accessed, a pointer to it is returned, otherwise
3617 % NULL is returned. The returned pointer may point to a temporary working
3618 % copy of the pixels or it may point to the original pixels in memory.
3619 % Performance is maximized if the selected region is part of one row, or one
3620 % or more full rows, since there is opportunity to access the pixels in-place
3621 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3622 % returned pointer must *never* be deallocated by the user.
3624 % Pixels accessed via the returned pointer represent a simple array of type
3625 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3626 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3627 % access the meta-content (of type void) corresponding to the the
3630 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3632 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3633 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3634 % GetCacheViewAuthenticPixels() instead.
3636 % The format of the GetVirtualPixels() method is:
3638 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3639 % const ssize_t y,const size_t columns,const size_t rows,
3640 % ExceptionInfo *exception)
3642 % A description of each parameter follows:
3644 % o image: the image.
3646 % o x,y,columns,rows: These values define the perimeter of a region of
3649 % o exception: return any errors or warnings in this structure.
3652 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3653 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3654 ExceptionInfo *exception)
3660 id = GetOpenMPThreadId();
3665 assert(image != (const Image *) NULL);
3666 assert(image->signature == MagickSignature);
3667 assert(image->cache != (Cache) NULL);
3668 cache_info=(CacheInfo *) image->cache;
3669 assert(cache_info->signature == MagickSignature);
3670 if (cache_info->methods.get_virtual_pixel_handler !=
3671 (GetVirtualPixelHandler) NULL)
3672 return(cache_info->methods.get_virtual_pixel_handler(image,
3673 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3674 assert(id < (int) cache_info->number_threads);
3675 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3676 columns,rows,cache_info->nexus_info[id],exception);
3681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3685 + 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 %
3689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3691 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3692 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3694 % The format of the GetVirtualPixelsCache() method is:
3696 % Quantum *GetVirtualPixelsCache(const Image *image)
3698 % A description of each parameter follows:
3700 % o image: the image.
3703 static const Quantum *GetVirtualPixelsCache(const Image *image)
3709 id = GetOpenMPThreadId();
3711 assert(image != (const Image *) NULL);
3712 assert(image->signature == MagickSignature);
3713 assert(image->cache != (Cache) NULL);
3714 cache_info=(CacheInfo *) image->cache;
3715 assert(cache_info->signature == MagickSignature);
3716 assert(id < (int) cache_info->number_threads);
3717 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3725 + G e t V i r t u a l P i x e l s N e x u s %
3729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3731 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3734 % The format of the GetVirtualPixelsNexus() method is:
3736 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3737 % NexusInfo *nexus_info)
3739 % A description of each parameter follows:
3741 % o cache: the pixel cache.
3743 % o nexus_info: the cache nexus to return the colormap pixels.
3746 MagickExport const Quantum *GetVirtualPixelsNexus(const Cache cache,
3747 NexusInfo *nexus_info)
3752 assert(cache != (Cache) NULL);
3753 cache_info=(CacheInfo *) cache;
3754 assert(cache_info->signature == MagickSignature);
3755 if (cache_info->storage_class == UndefinedClass)
3756 return((Quantum *) NULL);
3757 return((const Quantum *) nexus_info->pixels);
3761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3765 + M a s k P i x e l C a c h e N e x u s %
3769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3771 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3772 % The method returns MagickTrue if the pixel region is masked, otherwise
3775 % The format of the MaskPixelCacheNexus() method is:
3777 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3778 % NexusInfo *nexus_info,ExceptionInfo *exception)
3780 % A description of each parameter follows:
3782 % o image: the image.
3784 % o nexus_info: the cache nexus to clip.
3786 % o exception: return any errors or warnings in this structure.
3790 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3791 const MagickRealType alpha,const PixelInfo *q,
3792 const MagickRealType beta,PixelInfo *composite)
3797 if (alpha == TransparentAlpha)
3802 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3803 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3804 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3805 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3806 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3807 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3808 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3811 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3812 ExceptionInfo *exception)
3828 register const Quantum
3841 if (image->debug != MagickFalse)
3842 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3843 if (image->mask == (Image *) NULL)
3844 return(MagickFalse);
3845 cache_info=(CacheInfo *) image->cache;
3846 if (cache_info == (Cache) NULL)
3847 return(MagickFalse);
3848 image_nexus=AcquirePixelCacheNexus(1);
3849 clip_nexus=AcquirePixelCacheNexus(1);
3850 if ((image_nexus == (NexusInfo **) NULL) ||
3851 (clip_nexus == (NexusInfo **) NULL))
3852 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3853 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3854 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3855 nexus_info->region.height,image_nexus[0],exception);
3856 q=nexus_info->pixels;
3857 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3858 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3859 nexus_info->region.height,clip_nexus[0],&image->exception);
3860 GetPixelInfo(image,&alpha);
3861 GetPixelInfo(image,&beta);
3862 number_pixels=(MagickSizeType) nexus_info->region.width*
3863 nexus_info->region.height;
3864 for (i=0; i < (ssize_t) number_pixels; i++)
3866 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3868 SetPixelInfo(image,p,&alpha);
3869 SetPixelInfo(image,q,&beta);
3870 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3871 &alpha,alpha.alpha,&beta);
3872 SetPixelRed(image,ClampToQuantum(beta.red),q);
3873 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3874 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3875 if (cache_info->colorspace == CMYKColorspace)
3876 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3877 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3882 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3883 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3884 if (i < (ssize_t) number_pixels)
3885 return(MagickFalse);
3890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3894 + O p e n P i x e l C a c h e %
3898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3900 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3901 % dimensions, allocating space for the image pixels and optionally the
3902 % metacontent, and memory mapping the cache if it is disk based. The cache
3903 % nexus array is initialized as well.
3905 % The format of the OpenPixelCache() method is:
3907 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3908 % ExceptionInfo *exception)
3910 % A description of each parameter follows:
3912 % o image: the image.
3914 % o mode: ReadMode, WriteMode, or IOMode.
3916 % o exception: return any errors or warnings in this structure.
3920 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3922 cache_info->mapped=MagickFalse;
3923 cache_info->pixels=(Quantum *) AcquireAlignedMemory(1,(size_t)
3924 cache_info->length);
3925 if (cache_info->pixels == (Quantum *) NULL)
3927 cache_info->mapped=MagickTrue;
3928 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3929 cache_info->length);
3933 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3943 cache_info=(CacheInfo *) image->cache;
3944 if (image->debug != MagickFalse)
3947 format[MaxTextExtent],
3948 message[MaxTextExtent];
3950 (void) FormatMagickSize(length,MagickFalse,format);
3951 (void) FormatLocaleString(message,MaxTextExtent,
3952 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3953 cache_info->cache_filename,cache_info->file,format);
3954 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3956 if (length != (MagickSizeType) ((MagickOffsetType) length))
3957 return(MagickFalse);
3958 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3960 return(MagickFalse);
3961 if ((MagickSizeType) extent >= length)
3963 offset=(MagickOffsetType) length-1;
3964 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3965 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3968 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3969 ExceptionInfo *exception)
3976 format[MaxTextExtent],
3977 message[MaxTextExtent];
3990 assert(image != (const Image *) NULL);
3991 assert(image->signature == MagickSignature);
3992 assert(image->cache != (Cache) NULL);
3993 if (image->debug != MagickFalse)
3994 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3995 if ((image->columns == 0) || (image->rows == 0))
3996 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3997 StandardPixelChannelMap(image);
3998 cache_info=(CacheInfo *) image->cache;
3999 assert(cache_info->signature == MagickSignature);
4000 source_info=(*cache_info);
4001 source_info.file=(-1);
4002 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4003 image->filename,(double) GetImageIndexInList(image));
4004 cache_info->storage_class=image->storage_class;
4005 cache_info->colorspace=image->colorspace;
4006 cache_info->mode=mode;
4007 cache_info->rows=image->rows;
4008 cache_info->columns=image->columns;
4009 cache_info->number_channels=GetPixelChannels(image);
4010 cache_info->metacontent_extent=image->metacontent_extent;
4011 if (image->ping != MagickFalse)
4013 cache_info->type=PingCache;
4014 cache_info->pixels=(Quantum *) NULL;
4015 cache_info->metacontent=(void *) NULL;
4016 cache_info->length=0;
4019 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4020 packet_size=cache_info->number_channels*sizeof(Quantum);
4021 if (image->metacontent_extent != 0)
4022 packet_size+=cache_info->metacontent_extent;
4023 length=number_pixels*packet_size;
4024 columns=(size_t) (length/cache_info->rows/packet_size);
4025 if (cache_info->columns != columns)
4026 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4028 cache_info->length=length;
4029 if ((cache_info->type != UndefinedCache) &&
4030 (cache_info->columns <= source_info.columns) &&
4031 (cache_info->rows <= source_info.rows) &&
4032 (cache_info->number_channels <= source_info.number_channels) &&
4033 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4036 Inline pixel cache clone optimization.
4038 if ((cache_info->columns == source_info.columns) &&
4039 (cache_info->rows == source_info.rows) &&
4040 (cache_info->number_channels == source_info.number_channels) &&
4041 (cache_info->metacontent_extent == source_info.metacontent_extent))
4043 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4045 status=AcquireMagickResource(AreaResource,cache_info->length);
4046 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4047 cache_info->metacontent_extent);
4048 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4050 status=AcquireMagickResource(MemoryResource,cache_info->length);
4051 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4052 (cache_info->type == MemoryCache))
4054 AllocatePixelCachePixels(cache_info);
4055 if (cache_info->pixels == (Quantum *) NULL)
4056 cache_info->pixels=source_info.pixels;
4060 Create memory pixel cache.
4063 if (image->debug != MagickFalse)
4065 (void) FormatMagickSize(cache_info->length,MagickTrue,
4067 (void) FormatLocaleString(message,MaxTextExtent,
4068 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4069 cache_info->filename,cache_info->mapped != MagickFalse ?
4070 "anonymous" : "heap",(double) cache_info->columns,(double)
4071 cache_info->rows,(double) cache_info->number_channels,
4073 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4076 cache_info->type=MemoryCache;
4077 cache_info->metacontent=(void *) NULL;
4078 if (cache_info->metacontent_extent != 0)
4079 cache_info->metacontent=(void *) (cache_info->pixels+
4080 number_pixels*cache_info->number_channels);
4081 if (source_info.storage_class != UndefinedClass)
4083 status=ClonePixelCachePixels(cache_info,&source_info,
4085 RelinquishPixelCachePixels(&source_info);
4090 RelinquishMagickResource(MemoryResource,cache_info->length);
4093 Create pixel cache on disk.
4095 status=AcquireMagickResource(DiskResource,cache_info->length);
4096 if (status == MagickFalse)
4098 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4099 "CacheResourcesExhausted","`%s'",image->filename);
4100 return(MagickFalse);
4102 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4104 RelinquishMagickResource(DiskResource,cache_info->length);
4105 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4107 return(MagickFalse);
4109 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4110 cache_info->length);
4111 if (status == MagickFalse)
4113 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4115 return(MagickFalse);
4117 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4118 cache_info->metacontent_extent);
4119 status=AcquireMagickResource(AreaResource,cache_info->length);
4120 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4121 cache_info->type=DiskCache;
4124 status=AcquireMagickResource(MapResource,cache_info->length);
4125 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4126 (cache_info->type != MemoryCache))
4127 cache_info->type=DiskCache;
4130 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4131 cache_info->offset,(size_t) cache_info->length);
4132 if (cache_info->pixels == (Quantum *) NULL)
4134 cache_info->type=DiskCache;
4135 cache_info->pixels=source_info.pixels;
4140 Create file-backed memory-mapped pixel cache.
4143 (void) ClosePixelCacheOnDisk(cache_info);
4144 cache_info->type=MapCache;
4145 cache_info->mapped=MagickTrue;
4146 cache_info->metacontent=(void *) NULL;
4147 if (cache_info->metacontent_extent != 0)
4148 cache_info->metacontent=(void *) (cache_info->pixels+
4149 number_pixels*cache_info->number_channels);
4150 if (source_info.storage_class != UndefinedClass)
4152 status=ClonePixelCachePixels(cache_info,&source_info,
4154 RelinquishPixelCachePixels(&source_info);
4156 if (image->debug != MagickFalse)
4158 (void) FormatMagickSize(cache_info->length,MagickTrue,
4160 (void) FormatLocaleString(message,MaxTextExtent,
4161 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4162 cache_info->filename,cache_info->cache_filename,
4163 cache_info->file,(double) cache_info->columns,(double)
4164 cache_info->rows,(double) cache_info->number_channels,
4166 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4172 RelinquishMagickResource(MapResource,cache_info->length);
4175 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4177 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4178 RelinquishPixelCachePixels(&source_info);
4180 if (image->debug != MagickFalse)
4182 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4183 (void) FormatLocaleString(message,MaxTextExtent,
4184 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4185 cache_info->cache_filename,cache_info->file,(double)
4186 cache_info->columns,(double) cache_info->rows,(double)
4187 cache_info->number_channels,format);
4188 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4198 + P e r s i s t P i x e l C a c h e %
4202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4204 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4205 % persistent pixel cache is one that resides on disk and is not destroyed
4206 % when the program exits.
4208 % The format of the PersistPixelCache() method is:
4210 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4211 % const MagickBooleanType attach,MagickOffsetType *offset,
4212 % ExceptionInfo *exception)
4214 % A description of each parameter follows:
4216 % o image: the image.
4218 % o filename: the persistent pixel cache filename.
4220 % o attach: A value other than zero initializes the persistent pixel cache.
4222 % o initialize: A value other than zero initializes the persistent pixel
4225 % o offset: the offset in the persistent cache to store pixels.
4227 % o exception: return any errors or warnings in this structure.
4230 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4231 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4232 ExceptionInfo *exception)
4247 assert(image != (Image *) NULL);
4248 assert(image->signature == MagickSignature);
4249 if (image->debug != MagickFalse)
4250 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4251 assert(image->cache != (void *) NULL);
4252 assert(filename != (const char *) NULL);
4253 assert(offset != (MagickOffsetType *) NULL);
4254 page_size=GetMagickPageSize();
4255 cache_info=(CacheInfo *) image->cache;
4256 assert(cache_info->signature == MagickSignature);
4257 if (attach != MagickFalse)
4260 Attach existing persistent pixel cache.
4262 if (image->debug != MagickFalse)
4263 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4264 "attach persistent cache");
4265 (void) CopyMagickString(cache_info->cache_filename,filename,
4267 cache_info->type=DiskCache;
4268 cache_info->offset=(*offset);
4269 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4270 return(MagickFalse);
4271 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4274 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4275 (cache_info->reference_count == 1))
4277 LockSemaphoreInfo(cache_info->semaphore);
4278 if ((cache_info->mode != ReadMode) &&
4279 (cache_info->type != MemoryCache) &&
4280 (cache_info->reference_count == 1))
4286 Usurp existing persistent pixel cache.
4288 status=rename(cache_info->cache_filename,filename);
4291 (void) CopyMagickString(cache_info->cache_filename,filename,
4293 *offset+=cache_info->length+page_size-(cache_info->length %
4295 UnlockSemaphoreInfo(cache_info->semaphore);
4296 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4297 if (image->debug != MagickFalse)
4298 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4299 "Usurp resident persistent cache");
4303 UnlockSemaphoreInfo(cache_info->semaphore);
4306 Clone persistent pixel cache.
4308 clone_image=(*image);
4309 clone_info=(CacheInfo *) clone_image.cache;
4310 image->cache=ClonePixelCache(cache_info);
4311 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4312 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4313 cache_info->type=DiskCache;
4314 cache_info->offset=(*offset);
4315 cache_info=(CacheInfo *) image->cache;
4316 status=OpenPixelCache(image,IOMode,exception);
4317 if (status != MagickFalse)
4318 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4319 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4320 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4329 + Q u e u e A u t h e n t i c N e x u s %
4333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4335 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4336 % by the region rectangle and returns a pointer to the region. This region is
4337 % subsequently transferred from the pixel cache with
4338 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4339 % pixels are transferred, otherwise a NULL is returned.
4341 % The format of the QueueAuthenticNexus() method is:
4343 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4344 % const ssize_t y,const size_t columns,const size_t rows,
4345 % NexusInfo *nexus_info,ExceptionInfo *exception)
4347 % A description of each parameter follows:
4349 % o image: the image.
4351 % o x,y,columns,rows: These values define the perimeter of a region of
4354 % o nexus_info: the cache nexus to set.
4356 % o exception: return any errors or warnings in this structure.
4359 MagickExport Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4360 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4361 ExceptionInfo *exception)
4376 Validate pixel cache geometry.
4378 assert(image != (const Image *) NULL);
4379 assert(image->signature == MagickSignature);
4380 assert(image->cache != (Cache) NULL);
4381 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4382 assert(cache_info->signature == MagickSignature);
4383 if (cache_info == (Cache) NULL)
4384 return((Quantum *) NULL);
4385 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4387 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4388 "NoPixelsDefinedInCache","`%s'",image->filename);
4389 return((Quantum *) NULL);
4391 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4392 (y >= (ssize_t) cache_info->rows))
4394 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4395 "PixelsAreNotAuthentic","`%s'",image->filename);
4396 return((Quantum *) NULL);
4398 offset=(MagickOffsetType) y*cache_info->columns+x;
4400 return((Quantum *) NULL);
4401 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4402 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4403 if ((MagickSizeType) offset >= number_pixels)
4404 return((Quantum *) NULL);
4410 region.width=columns;
4412 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4420 + 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 %
4424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4426 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4427 % defined by the region rectangle and returns a pointer to the region. This
4428 % region is subsequently transferred from the pixel cache with
4429 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4430 % pixels are transferred, otherwise a NULL is returned.
4432 % The format of the QueueAuthenticPixelsCache() method is:
4434 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4435 % const ssize_t y,const size_t columns,const size_t rows,
4436 % ExceptionInfo *exception)
4438 % A description of each parameter follows:
4440 % o image: the image.
4442 % o x,y,columns,rows: These values define the perimeter of a region of
4445 % o exception: return any errors or warnings in this structure.
4448 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4449 const ssize_t y,const size_t columns,const size_t rows,
4450 ExceptionInfo *exception)
4456 id = GetOpenMPThreadId();
4461 assert(image != (const Image *) NULL);
4462 assert(image->signature == MagickSignature);
4463 assert(image->cache != (Cache) NULL);
4464 cache_info=(CacheInfo *) image->cache;
4465 assert(cache_info->signature == MagickSignature);
4466 assert(id < (int) cache_info->number_threads);
4467 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4477 % Q u e u e A u t h e n t i c P i x e l s %
4481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4483 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4484 % successfully initialized a pointer to a Quantum array representing the
4485 % region is returned, otherwise NULL is returned. The returned pointer may
4486 % point to a temporary working buffer for the pixels or it may point to the
4487 % final location of the pixels in memory.
4489 % Write-only access means that any existing pixel values corresponding to
4490 % the region are ignored. This is useful if the initial image is being
4491 % created from scratch, or if the existing pixel values are to be
4492 % completely replaced without need to refer to their pre-existing values.
4493 % The application is free to read and write the pixel buffer returned by
4494 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4495 % initialize the pixel array values. Initializing pixel array values is the
4496 % application's responsibility.
4498 % Performance is maximized if the selected region is part of one row, or
4499 % one or more full rows, since then there is opportunity to access the
4500 % pixels in-place (without a copy) if the image is in memory, or in a
4501 % memory-mapped file. The returned pointer must *never* be deallocated
4504 % Pixels accessed via the returned pointer represent a simple array of type
4505 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4506 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4507 % obtain the meta-content (of type void) corresponding to the region.
4508 % Once the Quantum (and/or Quantum) array has been updated, the
4509 % changes must be saved back to the underlying image using
4510 % SyncAuthenticPixels() or they may be lost.
4512 % The format of the QueueAuthenticPixels() method is:
4514 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4515 % const ssize_t y,const size_t columns,const size_t rows,
4516 % ExceptionInfo *exception)
4518 % A description of each parameter follows:
4520 % o image: the image.
4522 % o x,y,columns,rows: These values define the perimeter of a region of
4525 % o exception: return any errors or warnings in this structure.
4528 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4529 const ssize_t y,const size_t columns,const size_t rows,
4530 ExceptionInfo *exception)
4536 id = GetOpenMPThreadId();
4541 assert(image != (Image *) NULL);
4542 assert(image->signature == MagickSignature);
4543 assert(image->cache != (Cache) NULL);
4544 cache_info=(CacheInfo *) image->cache;
4545 assert(cache_info->signature == MagickSignature);
4546 if (cache_info->methods.queue_authentic_pixels_handler !=
4547 (QueueAuthenticPixelsHandler) NULL)
4549 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4550 columns,rows,exception);
4553 assert(id < (int) cache_info->number_threads);
4554 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4564 + 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 %
4568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4570 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4573 % The format of the ReadPixelCacheMetacontent() method is:
4575 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4576 % NexusInfo *nexus_info,ExceptionInfo *exception)
4578 % A description of each parameter follows:
4580 % o cache_info: the pixel cache.
4582 % o nexus_info: the cache nexus to read the metacontent.
4584 % o exception: return any errors or warnings in this structure.
4587 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4588 NexusInfo *nexus_info,ExceptionInfo *exception)
4601 register unsigned char
4607 if (cache_info->metacontent_extent == 0)
4608 return(MagickFalse);
4609 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4611 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4612 nexus_info->region.x;
4613 length=(MagickSizeType) nexus_info->region.width*
4614 cache_info->metacontent_extent;
4615 rows=nexus_info->region.height;
4617 q=(unsigned char *) nexus_info->metacontent;
4618 switch (cache_info->type)
4623 register unsigned char
4627 Read meta-content from memory.
4629 if ((cache_info->columns == nexus_info->region.width) &&
4630 (extent == (MagickSizeType) ((size_t) extent)))
4635 p=(unsigned char *) cache_info->metacontent+offset*
4636 cache_info->metacontent_extent;
4637 for (y=0; y < (ssize_t) rows; y++)
4639 (void) memcpy(q,p,(size_t) length);
4640 p+=cache_info->metacontent_extent*cache_info->columns;
4641 q+=cache_info->metacontent_extent*nexus_info->region.width;
4648 Read meta content from disk.
4650 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4652 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4653 cache_info->cache_filename);
4654 return(MagickFalse);
4656 if ((cache_info->columns == nexus_info->region.width) &&
4657 (extent <= MagickMaxBufferExtent))
4662 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4663 for (y=0; y < (ssize_t) rows; y++)
4665 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4666 cache_info->number_channels*sizeof(Quantum)+offset*
4667 cache_info->metacontent_extent,length,(unsigned char *) q);
4668 if ((MagickSizeType) count != length)
4670 offset+=cache_info->columns;
4671 q+=cache_info->metacontent_extent*nexus_info->region.width;
4673 if (y < (ssize_t) rows)
4675 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4676 cache_info->cache_filename);
4677 return(MagickFalse);
4684 if ((cache_info->debug != MagickFalse) &&
4685 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4686 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4687 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4688 nexus_info->region.width,(double) nexus_info->region.height,(double)
4689 nexus_info->region.x,(double) nexus_info->region.y);
4694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698 + R e a d P i x e l C a c h e P i x e l s %
4702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4704 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4707 % The format of the ReadPixelCachePixels() method is:
4709 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4710 % NexusInfo *nexus_info,ExceptionInfo *exception)
4712 % A description of each parameter follows:
4714 % o cache_info: the pixel cache.
4716 % o nexus_info: the cache nexus to read the pixels.
4718 % o exception: return any errors or warnings in this structure.
4721 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4722 NexusInfo *nexus_info,ExceptionInfo *exception)
4741 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4743 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4744 nexus_info->region.x;
4745 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4747 rows=nexus_info->region.height;
4749 q=nexus_info->pixels;
4750 switch (cache_info->type)
4759 Read pixels from memory.
4761 if ((cache_info->columns == nexus_info->region.width) &&
4762 (extent == (MagickSizeType) ((size_t) extent)))
4767 p=cache_info->pixels+offset*cache_info->number_channels;
4768 for (y=0; y < (ssize_t) rows; y++)
4770 (void) memcpy(q,p,(size_t) length);
4771 p+=cache_info->number_channels*cache_info->columns;
4772 q+=cache_info->number_channels*nexus_info->region.width;
4779 Read pixels from disk.
4781 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4783 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4784 cache_info->cache_filename);
4785 return(MagickFalse);
4787 if ((cache_info->columns == nexus_info->region.width) &&
4788 (extent <= MagickMaxBufferExtent))
4793 for (y=0; y < (ssize_t) rows; y++)
4795 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4796 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4797 if ((MagickSizeType) count != length)
4799 offset+=cache_info->columns;
4800 q+=cache_info->number_channels*nexus_info->region.width;
4802 if (y < (ssize_t) rows)
4804 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4805 cache_info->cache_filename);
4806 return(MagickFalse);
4813 if ((cache_info->debug != MagickFalse) &&
4814 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4815 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4816 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4817 nexus_info->region.width,(double) nexus_info->region.height,(double)
4818 nexus_info->region.x,(double) nexus_info->region.y);
4823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4827 + R e f e r e n c e P i x e l C a c h e %
4831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4833 % ReferencePixelCache() increments the reference count associated with the
4834 % pixel cache returning a pointer to the cache.
4836 % The format of the ReferencePixelCache method is:
4838 % Cache ReferencePixelCache(Cache cache_info)
4840 % A description of each parameter follows:
4842 % o cache_info: the pixel cache.
4845 MagickExport Cache ReferencePixelCache(Cache cache)
4850 assert(cache != (Cache *) NULL);
4851 cache_info=(CacheInfo *) cache;
4852 assert(cache_info->signature == MagickSignature);
4853 LockSemaphoreInfo(cache_info->semaphore);
4854 cache_info->reference_count++;
4855 UnlockSemaphoreInfo(cache_info->semaphore);
4860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4864 + S e t P i x e l C a c h e M e t h o d s %
4868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4870 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4872 % The format of the SetPixelCacheMethods() method is:
4874 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4876 % A description of each parameter follows:
4878 % o cache: the pixel cache.
4880 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4883 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4888 GetOneAuthenticPixelFromHandler
4889 get_one_authentic_pixel_from_handler;
4891 GetOneVirtualPixelFromHandler
4892 get_one_virtual_pixel_from_handler;
4895 Set cache pixel methods.
4897 assert(cache != (Cache) NULL);
4898 assert(cache_methods != (CacheMethods *) NULL);
4899 cache_info=(CacheInfo *) cache;
4900 assert(cache_info->signature == MagickSignature);
4901 if (cache_info->debug != MagickFalse)
4902 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4903 cache_info->filename);
4904 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4905 cache_info->methods.get_virtual_pixel_handler=
4906 cache_methods->get_virtual_pixel_handler;
4907 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4908 cache_info->methods.destroy_pixel_handler=
4909 cache_methods->destroy_pixel_handler;
4910 if (cache_methods->get_virtual_metacontent_from_handler !=
4911 (GetVirtualMetacontentFromHandler) NULL)
4912 cache_info->methods.get_virtual_metacontent_from_handler=
4913 cache_methods->get_virtual_metacontent_from_handler;
4914 if (cache_methods->get_authentic_pixels_handler !=
4915 (GetAuthenticPixelsHandler) NULL)
4916 cache_info->methods.get_authentic_pixels_handler=
4917 cache_methods->get_authentic_pixels_handler;
4918 if (cache_methods->queue_authentic_pixels_handler !=
4919 (QueueAuthenticPixelsHandler) NULL)
4920 cache_info->methods.queue_authentic_pixels_handler=
4921 cache_methods->queue_authentic_pixels_handler;
4922 if (cache_methods->sync_authentic_pixels_handler !=
4923 (SyncAuthenticPixelsHandler) NULL)
4924 cache_info->methods.sync_authentic_pixels_handler=
4925 cache_methods->sync_authentic_pixels_handler;
4926 if (cache_methods->get_authentic_pixels_from_handler !=
4927 (GetAuthenticPixelsFromHandler) NULL)
4928 cache_info->methods.get_authentic_pixels_from_handler=
4929 cache_methods->get_authentic_pixels_from_handler;
4930 if (cache_methods->get_authentic_metacontent_from_handler !=
4931 (GetAuthenticMetacontentFromHandler) NULL)
4932 cache_info->methods.get_authentic_metacontent_from_handler=
4933 cache_methods->get_authentic_metacontent_from_handler;
4934 get_one_virtual_pixel_from_handler=
4935 cache_info->methods.get_one_virtual_pixel_from_handler;
4936 if (get_one_virtual_pixel_from_handler !=
4937 (GetOneVirtualPixelFromHandler) NULL)
4938 cache_info->methods.get_one_virtual_pixel_from_handler=
4939 cache_methods->get_one_virtual_pixel_from_handler;
4940 get_one_authentic_pixel_from_handler=
4941 cache_methods->get_one_authentic_pixel_from_handler;
4942 if (get_one_authentic_pixel_from_handler !=
4943 (GetOneAuthenticPixelFromHandler) NULL)
4944 cache_info->methods.get_one_authentic_pixel_from_handler=
4945 cache_methods->get_one_authentic_pixel_from_handler;
4949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4953 + S e t P i x e l C a c h e N e x u s P i x e l s %
4957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4959 % SetPixelCacheNexusPixels() defines the region of the cache for the
4960 % specified cache nexus.
4962 % The format of the SetPixelCacheNexusPixels() method is:
4964 % Quantum SetPixelCacheNexusPixels(const Image *image,
4965 % const RectangleInfo *region,NexusInfo *nexus_info,
4966 % ExceptionInfo *exception)
4968 % A description of each parameter follows:
4970 % o image: the image.
4972 % o region: A pointer to the RectangleInfo structure that defines the
4973 % region of this particular cache nexus.
4975 % o nexus_info: the cache nexus to set.
4977 % o exception: return any errors or warnings in this structure.
4981 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4982 NexusInfo *nexus_info,ExceptionInfo *exception)
4984 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4985 return(MagickFalse);
4986 nexus_info->mapped=MagickFalse;
4987 nexus_info->cache=(Quantum *) AcquireAlignedMemory(1,(size_t)
4988 nexus_info->length);
4989 if (nexus_info->cache == (Quantum *) NULL)
4991 nexus_info->mapped=MagickTrue;
4992 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4993 nexus_info->length);
4995 if (nexus_info->cache == (Quantum *) NULL)
4997 (void) ThrowMagickException(exception,GetMagickModule(),
4998 ResourceLimitError,"MemoryAllocationFailed","`%s'",
4999 cache_info->filename);
5000 return(MagickFalse);
5005 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5006 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5018 cache_info=(CacheInfo *) image->cache;
5019 assert(cache_info->signature == MagickSignature);
5020 if (cache_info->type == UndefinedCache)
5021 return((Quantum *) NULL);
5022 nexus_info->region=(*region);
5023 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5024 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5030 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5031 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5032 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5033 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5034 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5035 ((nexus_info->region.width == cache_info->columns) ||
5036 ((nexus_info->region.width % cache_info->columns) == 0)))))
5042 Pixels are accessed directly from memory.
5044 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5045 nexus_info->region.x;
5046 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5048 nexus_info->metacontent=(void *) NULL;
5049 if (cache_info->metacontent_extent != 0)
5050 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5051 offset*cache_info->metacontent_extent;
5052 return(nexus_info->pixels);
5056 Pixels are stored in a cache region until they are synced to the cache.
5058 number_pixels=(MagickSizeType) nexus_info->region.width*
5059 nexus_info->region.height;
5060 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5061 if (cache_info->metacontent_extent != 0)
5062 length+=number_pixels*cache_info->metacontent_extent;
5063 if (nexus_info->cache == (Quantum *) NULL)
5065 nexus_info->length=length;
5066 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5067 if (status == MagickFalse)
5069 nexus_info->length=0;
5070 return((Quantum *) NULL);
5074 if (nexus_info->length != length)
5076 RelinquishCacheNexusPixels(nexus_info);
5077 nexus_info->length=length;
5078 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5079 if (status == MagickFalse)
5081 nexus_info->length=0;
5082 return((Quantum *) NULL);
5085 nexus_info->pixels=nexus_info->cache;
5086 nexus_info->metacontent=(void *) NULL;
5087 if (cache_info->metacontent_extent != 0)
5088 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5089 cache_info->number_channels);
5090 return(nexus_info->pixels);
5094 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5098 % 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 %
5102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5104 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5105 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5106 % access that is outside the boundaries of the image cache.
5108 % The format of the SetPixelCacheVirtualMethod() method is:
5110 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5111 % const VirtualPixelMethod virtual_pixel_method)
5113 % A description of each parameter follows:
5115 % o image: the image.
5117 % o virtual_pixel_method: choose the type of virtual pixel.
5120 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5121 const VirtualPixelMethod virtual_pixel_method)
5129 assert(image != (Image *) NULL);
5130 assert(image->signature == MagickSignature);
5131 if (image->debug != MagickFalse)
5132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5133 assert(image->cache != (Cache) NULL);
5134 cache_info=(CacheInfo *) image->cache;
5135 assert(cache_info->signature == MagickSignature);
5136 method=cache_info->virtual_pixel_method;
5137 cache_info->virtual_pixel_method=virtual_pixel_method;
5142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5146 + 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 %
5150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5152 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5153 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5154 % is synced, otherwise MagickFalse.
5156 % The format of the SyncAuthenticPixelCacheNexus() method is:
5158 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5159 % NexusInfo *nexus_info,ExceptionInfo *exception)
5161 % A description of each parameter follows:
5163 % o image: the image.
5165 % o nexus_info: the cache nexus to sync.
5167 % o exception: return any errors or warnings in this structure.
5170 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5171 NexusInfo *nexus_info,ExceptionInfo *exception)
5180 Transfer pixels to the cache.
5182 assert(image != (Image *) NULL);
5183 assert(image->signature == MagickSignature);
5184 if (image->cache == (Cache) NULL)
5185 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5186 cache_info=(CacheInfo *) image->cache;
5187 assert(cache_info->signature == MagickSignature);
5188 if (cache_info->type == UndefinedCache)
5189 return(MagickFalse);
5190 if ((image->clip_mask != (Image *) NULL) &&
5191 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5192 return(MagickFalse);
5193 if ((image->mask != (Image *) NULL) &&
5194 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5195 return(MagickFalse);
5196 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5198 assert(cache_info->signature == MagickSignature);
5199 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5200 if ((cache_info->metacontent_extent != 0) &&
5201 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5202 return(MagickFalse);
5207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5211 + S y n c A u t h e n t i c P i x e l C a c h e %
5215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5217 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5218 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5219 % otherwise MagickFalse.
5221 % The format of the SyncAuthenticPixelsCache() method is:
5223 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5224 % ExceptionInfo *exception)
5226 % A description of each parameter follows:
5228 % o image: the image.
5230 % o exception: return any errors or warnings in this structure.
5233 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5234 ExceptionInfo *exception)
5240 id = GetOpenMPThreadId();
5245 assert(image != (Image *) NULL);
5246 assert(image->signature == MagickSignature);
5247 assert(image->cache != (Cache) NULL);
5248 cache_info=(CacheInfo *) image->cache;
5249 assert(cache_info->signature == MagickSignature);
5250 assert(id < (int) cache_info->number_threads);
5251 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5261 % S y n c A u t h e n t i c P i x e l s %
5265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5267 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5268 % The method returns MagickTrue if the pixel region is flushed, otherwise
5271 % The format of the SyncAuthenticPixels() method is:
5273 % MagickBooleanType SyncAuthenticPixels(Image *image,
5274 % ExceptionInfo *exception)
5276 % A description of each parameter follows:
5278 % o image: the image.
5280 % o exception: return any errors or warnings in this structure.
5283 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5284 ExceptionInfo *exception)
5290 id = GetOpenMPThreadId();
5295 assert(image != (Image *) NULL);
5296 assert(image->signature == MagickSignature);
5297 assert(image->cache != (Cache) NULL);
5298 cache_info=(CacheInfo *) image->cache;
5299 assert(cache_info->signature == MagickSignature);
5300 if (cache_info->methods.sync_authentic_pixels_handler !=
5301 (SyncAuthenticPixelsHandler) NULL)
5303 status=cache_info->methods.sync_authentic_pixels_handler(image,
5307 assert(id < (int) cache_info->number_threads);
5308 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5318 + 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 %
5322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5324 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5325 % of the pixel cache.
5327 % The format of the WritePixelCacheMetacontent() method is:
5329 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5330 % NexusInfo *nexus_info,ExceptionInfo *exception)
5332 % A description of each parameter follows:
5334 % o cache_info: the pixel cache.
5336 % o nexus_info: the cache nexus to write the meta-content.
5338 % o exception: return any errors or warnings in this structure.
5341 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5342 NexusInfo *nexus_info,ExceptionInfo *exception)
5352 register const unsigned char
5361 if (cache_info->metacontent_extent == 0)
5362 return(MagickFalse);
5363 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5365 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5366 nexus_info->region.x;
5367 length=(MagickSizeType) nexus_info->region.width*
5368 cache_info->metacontent_extent;
5369 rows=nexus_info->region.height;
5370 extent=(MagickSizeType) length*rows;
5371 p=(unsigned char *) nexus_info->metacontent;
5372 switch (cache_info->type)
5377 register unsigned char
5381 Write associated pixels to memory.
5383 if ((cache_info->columns == nexus_info->region.width) &&
5384 (extent == (MagickSizeType) ((size_t) extent)))
5389 q=(unsigned char *) cache_info->metacontent+offset*
5390 cache_info->metacontent_extent;
5391 for (y=0; y < (ssize_t) rows; y++)
5393 (void) memcpy(q,p,(size_t) length);
5394 p+=nexus_info->region.width*cache_info->metacontent_extent;
5395 q+=cache_info->columns*cache_info->metacontent_extent;
5402 Write associated pixels to disk.
5404 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5406 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5407 cache_info->cache_filename);
5408 return(MagickFalse);
5410 if ((cache_info->columns == nexus_info->region.width) &&
5411 (extent <= MagickMaxBufferExtent))
5416 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5417 for (y=0; y < (ssize_t) rows; y++)
5419 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5420 cache_info->number_channels*sizeof(Quantum)+offset*
5421 cache_info->metacontent_extent,length,(const unsigned char *) p);
5422 if ((MagickSizeType) count != length)
5424 p+=nexus_info->region.width*cache_info->metacontent_extent;
5425 offset+=cache_info->columns;
5427 if (y < (ssize_t) rows)
5429 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5430 cache_info->cache_filename);
5431 return(MagickFalse);
5438 if ((cache_info->debug != MagickFalse) &&
5439 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5440 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5441 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5442 nexus_info->region.width,(double) nexus_info->region.height,(double)
5443 nexus_info->region.x,(double) nexus_info->region.y);
5448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5452 + W r i t e C a c h e P i x e l s %
5456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5458 % WritePixelCachePixels() writes image pixels to the specified region of the
5461 % The format of the WritePixelCachePixels() method is:
5463 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5464 % NexusInfo *nexus_info,ExceptionInfo *exception)
5466 % A description of each parameter follows:
5468 % o cache_info: the pixel cache.
5470 % o nexus_info: the cache nexus to write the pixels.
5472 % o exception: return any errors or warnings in this structure.
5475 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5476 NexusInfo *nexus_info,ExceptionInfo *exception)
5486 register const Quantum
5495 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5497 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5498 nexus_info->region.x;
5499 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5501 rows=nexus_info->region.height;
5503 p=nexus_info->pixels;
5504 switch (cache_info->type)
5513 Write pixels to memory.
5515 if ((cache_info->columns == nexus_info->region.width) &&
5516 (extent == (MagickSizeType) ((size_t) extent)))
5521 q=cache_info->pixels+offset*cache_info->number_channels;
5522 for (y=0; y < (ssize_t) rows; y++)
5524 (void) memcpy(q,p,(size_t) length);
5525 p+=nexus_info->region.width*cache_info->number_channels;
5526 q+=cache_info->columns*cache_info->number_channels;
5533 Write pixels to disk.
5535 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5537 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5538 cache_info->cache_filename);
5539 return(MagickFalse);
5541 if ((cache_info->columns == nexus_info->region.width) &&
5542 (extent <= MagickMaxBufferExtent))
5547 for (y=0; y < (ssize_t) rows; y++)
5549 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5550 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5552 if ((MagickSizeType) count != length)
5554 p+=nexus_info->region.width*cache_info->number_channels;
5555 offset+=cache_info->columns;
5557 if (y < (ssize_t) rows)
5559 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5560 cache_info->cache_filename);
5561 return(MagickFalse);
5568 if ((cache_info->debug != MagickFalse) &&
5569 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5570 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5571 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5572 nexus_info->region.width,(double) nexus_info->region.height,(double)
5573 nexus_info->region.x,(double) nexus_info->region.y);