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(
2938 const Cache cache,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)));
3109 VirtualPixelModulo() computes the remainder of dividing offset by extent. It
3110 returns not only the quotient (tile the offset falls in) but also the positive
3111 remainer within that tile such that 0 <= remainder < extent. This method is
3112 essentially a ldiv() using a floored modulo division rather than the normal
3113 default truncated modulo division.
3115 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
3116 const size_t extent)
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:
3251 Acquire virtual pixel and associated channels.
3253 if (cache_info->metacontent_extent != 0)
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 < cache_info->number_channels; i++)
3272 SetPixelChannel(image,i,0,virtual_pixel);
3273 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3276 case GrayVirtualPixelMethod:
3278 for (i=0; i < cache_info->number_channels; i++)
3279 SetPixelChannel(image,i,QuantumRange/2,virtual_pixel);
3280 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3283 case TransparentVirtualPixelMethod:
3285 for (i=0; i < cache_info->number_channels; i++)
3286 SetPixelChannel(image,i,0,virtual_pixel);
3287 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3290 case MaskVirtualPixelMethod:
3291 case WhiteVirtualPixelMethod:
3293 for (i=0; i < cache_info->number_channels; i++)
3294 SetPixelChannel(image,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 SetPixelBlack(image,image->background_color.black,virtual_pixel);
3304 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3313 for (v=0; v < (ssize_t) rows; v++)
3315 for (u=0; u < (ssize_t) columns; u+=length)
3317 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3318 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3319 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3327 Transfer a single pixel.
3329 length=(MagickSizeType) 1;
3330 switch (virtual_pixel_method)
3334 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3335 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3336 1UL,1UL,*virtual_nexus,exception);
3337 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3340 case RandomVirtualPixelMethod:
3342 if (cache_info->random_info == (RandomInfo *) NULL)
3343 cache_info->random_info=AcquireRandomInfo();
3344 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3345 RandomX(cache_info->random_info,cache_info->columns),
3346 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3347 *virtual_nexus,exception);
3348 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3351 case DitherVirtualPixelMethod:
3353 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3354 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3355 1UL,1UL,*virtual_nexus,exception);
3356 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3359 case TileVirtualPixelMethod:
3361 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3362 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3363 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3364 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3366 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3369 case MirrorVirtualPixelMethod:
3371 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3372 if ((x_modulo.quotient & 0x01) == 1L)
3373 x_modulo.remainder=(ssize_t) cache_info->columns-
3374 x_modulo.remainder-1L;
3375 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3376 if ((y_modulo.quotient & 0x01) == 1L)
3377 y_modulo.remainder=(ssize_t) cache_info->rows-
3378 y_modulo.remainder-1L;
3379 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3380 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3382 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3385 case HorizontalTileEdgeVirtualPixelMethod:
3387 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3388 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3389 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3390 *virtual_nexus,exception);
3391 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3394 case VerticalTileEdgeVirtualPixelMethod:
3396 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3397 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3398 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3399 *virtual_nexus,exception);
3400 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3403 case BackgroundVirtualPixelMethod:
3404 case BlackVirtualPixelMethod:
3405 case GrayVirtualPixelMethod:
3406 case TransparentVirtualPixelMethod:
3407 case MaskVirtualPixelMethod:
3408 case WhiteVirtualPixelMethod:
3411 r=virtual_metacontent;
3414 case EdgeVirtualPixelMethod:
3415 case CheckerTileVirtualPixelMethod:
3417 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3418 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3419 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3422 r=virtual_metacontent;
3425 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3426 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3428 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3431 case HorizontalTileVirtualPixelMethod:
3433 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3436 r=virtual_metacontent;
3439 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3440 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3441 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3442 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3444 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3447 case VerticalTileVirtualPixelMethod:
3449 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3452 r=virtual_metacontent;
3455 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3456 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3457 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3458 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3460 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3464 if (p == (const Quantum *) NULL)
3466 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3468 q+=cache_info->number_channels;
3469 if ((s != (void *) NULL) && (r != (const void *) NULL))
3471 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3472 s+=cache_info->metacontent_extent;
3477 Transfer a run of pixels.
3479 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3480 length,1UL,*virtual_nexus,exception);
3481 if (p == (const Quantum *) NULL)
3483 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3484 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3485 q+=length*cache_info->number_channels;
3486 if ((r != (void *) NULL) && (s != (const void *) NULL))
3488 (void) memcpy(s,r,(size_t) length);
3489 s+=length*cache_info->metacontent_extent;
3496 if (virtual_metacontent != (void *) NULL)
3497 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3498 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3507 + G e t V i r t u a l P i x e l C a c h e %
3511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3513 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3514 % cache as defined by the geometry parameters. A pointer to the pixels
3515 % is returned if the pixels are transferred, otherwise a NULL is returned.
3517 % The format of the GetVirtualPixelCache() method is:
3519 % const Quantum *GetVirtualPixelCache(const Image *image,
3520 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3521 % const ssize_t y,const size_t columns,const size_t rows,
3522 % ExceptionInfo *exception)
3524 % A description of each parameter follows:
3526 % o image: the image.
3528 % o virtual_pixel_method: the virtual pixel method.
3530 % o x,y,columns,rows: These values define the perimeter of a region of
3533 % o exception: return any errors or warnings in this structure.
3536 static const Quantum *GetVirtualPixelCache(const Image *image,
3537 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3538 const size_t columns,const size_t rows,ExceptionInfo *exception)
3544 id = GetOpenMPThreadId();
3549 assert(image != (const Image *) NULL);
3550 assert(image->signature == MagickSignature);
3551 assert(image->cache != (Cache) NULL);
3552 cache_info=(CacheInfo *) image->cache;
3553 assert(cache_info->signature == MagickSignature);
3554 assert(id < (int) cache_info->number_threads);
3555 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3556 cache_info->nexus_info[id],exception);
3561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3565 % G e t V i r t u a l P i x e l Q u e u e %
3569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3571 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3572 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3574 % The format of the GetVirtualPixelQueue() method is:
3576 % const Quantum *GetVirtualPixelQueue(const Image image)
3578 % A description of each parameter follows:
3580 % o image: the image.
3583 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3589 id = GetOpenMPThreadId();
3591 assert(image != (const Image *) NULL);
3592 assert(image->signature == MagickSignature);
3593 assert(image->cache != (Cache) NULL);
3594 cache_info=(CacheInfo *) image->cache;
3595 assert(cache_info->signature == MagickSignature);
3596 if (cache_info->methods.get_virtual_pixels_handler !=
3597 (GetVirtualPixelsHandler) NULL)
3598 return(cache_info->methods.get_virtual_pixels_handler(image));
3599 assert(id < (int) cache_info->number_threads);
3600 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3608 % G e t V i r t u a l P i x e l s %
3612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3614 % GetVirtualPixels() returns an immutable pixel region. If the
3615 % region is successfully accessed, a pointer to it is returned, otherwise
3616 % NULL is returned. The returned pointer may point to a temporary working
3617 % copy of the pixels or it may point to the original pixels in memory.
3618 % Performance is maximized if the selected region is part of one row, or one
3619 % or more full rows, since there is opportunity to access the pixels in-place
3620 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3621 % returned pointer must *never* be deallocated by the user.
3623 % Pixels accessed via the returned pointer represent a simple array of type
3624 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3625 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3626 % access the meta-content (of type void) corresponding to the the
3629 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3631 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3632 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3633 % GetCacheViewAuthenticPixels() instead.
3635 % The format of the GetVirtualPixels() method is:
3637 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3638 % const ssize_t y,const size_t columns,const size_t rows,
3639 % ExceptionInfo *exception)
3641 % A description of each parameter follows:
3643 % o image: the image.
3645 % o x,y,columns,rows: These values define the perimeter of a region of
3648 % o exception: return any errors or warnings in this structure.
3651 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3652 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3653 ExceptionInfo *exception)
3659 id = GetOpenMPThreadId();
3664 assert(image != (const Image *) NULL);
3665 assert(image->signature == MagickSignature);
3666 assert(image->cache != (Cache) NULL);
3667 cache_info=(CacheInfo *) image->cache;
3668 assert(cache_info->signature == MagickSignature);
3669 if (cache_info->methods.get_virtual_pixel_handler !=
3670 (GetVirtualPixelHandler) NULL)
3671 return(cache_info->methods.get_virtual_pixel_handler(image,
3672 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3673 assert(id < (int) cache_info->number_threads);
3674 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3675 columns,rows,cache_info->nexus_info[id],exception);
3680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3684 + 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 %
3688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3690 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3691 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3693 % The format of the GetVirtualPixelsCache() method is:
3695 % Quantum *GetVirtualPixelsCache(const Image *image)
3697 % A description of each parameter follows:
3699 % o image: the image.
3702 static const Quantum *GetVirtualPixelsCache(const Image *image)
3708 id = GetOpenMPThreadId();
3710 assert(image != (const Image *) NULL);
3711 assert(image->signature == MagickSignature);
3712 assert(image->cache != (Cache) NULL);
3713 cache_info=(CacheInfo *) image->cache;
3714 assert(cache_info->signature == MagickSignature);
3715 assert(id < (int) cache_info->number_threads);
3716 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3724 + G e t V i r t u a l P i x e l s N e x u s %
3728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3730 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3733 % The format of the GetVirtualPixelsNexus() method is:
3735 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3736 % NexusInfo *nexus_info)
3738 % A description of each parameter follows:
3740 % o cache: the pixel cache.
3742 % o nexus_info: the cache nexus to return the colormap pixels.
3745 MagickExport const Quantum *GetVirtualPixelsNexus(const Cache cache,
3746 NexusInfo *nexus_info)
3751 assert(cache != (Cache) NULL);
3752 cache_info=(CacheInfo *) cache;
3753 assert(cache_info->signature == MagickSignature);
3754 if (cache_info->storage_class == UndefinedClass)
3755 return((Quantum *) NULL);
3756 return((const Quantum *) nexus_info->pixels);
3760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3764 + M a s k P i x e l C a c h e N e x u s %
3768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3770 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3771 % The method returns MagickTrue if the pixel region is masked, otherwise
3774 % The format of the MaskPixelCacheNexus() method is:
3776 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3777 % NexusInfo *nexus_info,ExceptionInfo *exception)
3779 % A description of each parameter follows:
3781 % o image: the image.
3783 % o nexus_info: the cache nexus to clip.
3785 % o exception: return any errors or warnings in this structure.
3789 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3790 const MagickRealType alpha,const PixelInfo *q,
3791 const MagickRealType beta,PixelInfo *composite)
3796 if (alpha == TransparentAlpha)
3801 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3802 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3803 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3804 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3805 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3806 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3807 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3810 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3811 ExceptionInfo *exception)
3827 register const Quantum
3840 if (image->debug != MagickFalse)
3841 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3842 if (image->mask == (Image *) NULL)
3843 return(MagickFalse);
3844 cache_info=(CacheInfo *) image->cache;
3845 if (cache_info == (Cache) NULL)
3846 return(MagickFalse);
3847 image_nexus=AcquirePixelCacheNexus(1);
3848 clip_nexus=AcquirePixelCacheNexus(1);
3849 if ((image_nexus == (NexusInfo **) NULL) ||
3850 (clip_nexus == (NexusInfo **) NULL))
3851 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3852 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3853 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3854 nexus_info->region.height,image_nexus[0],exception);
3855 q=nexus_info->pixels;
3856 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3857 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3858 nexus_info->region.height,clip_nexus[0],&image->exception);
3859 GetPixelInfo(image,&alpha);
3860 GetPixelInfo(image,&beta);
3861 number_pixels=(MagickSizeType) nexus_info->region.width*
3862 nexus_info->region.height;
3863 for (i=0; i < (ssize_t) number_pixels; i++)
3865 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3867 SetPixelInfo(image,p,&alpha);
3868 SetPixelInfo(image,q,&beta);
3869 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3870 &alpha,alpha.alpha,&beta);
3871 SetPixelRed(image,ClampToQuantum(beta.red),q);
3872 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3873 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3874 if (cache_info->colorspace == CMYKColorspace)
3875 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3876 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3881 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3882 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3883 if (i < (ssize_t) number_pixels)
3884 return(MagickFalse);
3889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3893 + O p e n P i x e l C a c h e %
3897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3899 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3900 % dimensions, allocating space for the image pixels and optionally the
3901 % metacontent, and memory mapping the cache if it is disk based. The cache
3902 % nexus array is initialized as well.
3904 % The format of the OpenPixelCache() method is:
3906 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3907 % ExceptionInfo *exception)
3909 % A description of each parameter follows:
3911 % o image: the image.
3913 % o mode: ReadMode, WriteMode, or IOMode.
3915 % o exception: return any errors or warnings in this structure.
3919 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3921 cache_info->mapped=MagickFalse;
3922 cache_info->pixels=(Quantum *) AcquireAlignedMemory(1,(size_t)
3923 cache_info->length);
3924 if (cache_info->pixels == (Quantum *) NULL)
3926 cache_info->mapped=MagickTrue;
3927 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3928 cache_info->length);
3932 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3942 cache_info=(CacheInfo *) image->cache;
3943 if (image->debug != MagickFalse)
3946 format[MaxTextExtent],
3947 message[MaxTextExtent];
3949 (void) FormatMagickSize(length,MagickFalse,format);
3950 (void) FormatLocaleString(message,MaxTextExtent,
3951 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3952 cache_info->cache_filename,cache_info->file,format);
3953 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3955 if (length != (MagickSizeType) ((MagickOffsetType) length))
3956 return(MagickFalse);
3957 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3959 return(MagickFalse);
3960 if ((MagickSizeType) extent >= length)
3962 offset=(MagickOffsetType) length-1;
3963 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3964 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3967 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3968 ExceptionInfo *exception)
3975 format[MaxTextExtent],
3976 message[MaxTextExtent];
3989 assert(image != (const Image *) NULL);
3990 assert(image->signature == MagickSignature);
3991 assert(image->cache != (Cache) NULL);
3992 if (image->debug != MagickFalse)
3993 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3994 if ((image->columns == 0) || (image->rows == 0))
3995 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3996 StandardPixelChannelMap(image);
3997 cache_info=(CacheInfo *) image->cache;
3998 assert(cache_info->signature == MagickSignature);
3999 source_info=(*cache_info);
4000 source_info.file=(-1);
4001 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4002 image->filename,(double) GetImageIndexInList(image));
4003 cache_info->storage_class=image->storage_class;
4004 cache_info->colorspace=image->colorspace;
4005 cache_info->mode=mode;
4006 cache_info->rows=image->rows;
4007 cache_info->columns=image->columns;
4008 cache_info->number_channels=GetPixelChannels(image);
4009 cache_info->metacontent_extent=image->metacontent_extent;
4010 if (image->ping != MagickFalse)
4012 cache_info->type=PingCache;
4013 cache_info->pixels=(Quantum *) NULL;
4014 cache_info->metacontent=(void *) NULL;
4015 cache_info->length=0;
4018 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4019 packet_size=cache_info->number_channels*sizeof(Quantum);
4020 if (image->metacontent_extent != 0)
4021 packet_size+=cache_info->metacontent_extent;
4022 length=number_pixels*packet_size;
4023 columns=(size_t) (length/cache_info->rows/packet_size);
4024 if (cache_info->columns != columns)
4025 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4027 cache_info->length=length;
4028 if ((cache_info->type != UndefinedCache) &&
4029 (cache_info->columns <= source_info.columns) &&
4030 (cache_info->rows <= source_info.rows) &&
4031 (cache_info->number_channels <= source_info.number_channels) &&
4032 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4035 Inline pixel cache clone optimization.
4037 if ((cache_info->columns == source_info.columns) &&
4038 (cache_info->rows == source_info.rows) &&
4039 (cache_info->number_channels == source_info.number_channels) &&
4040 (cache_info->metacontent_extent == source_info.metacontent_extent))
4042 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4044 status=AcquireMagickResource(AreaResource,cache_info->length);
4045 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4046 cache_info->metacontent_extent);
4047 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4049 status=AcquireMagickResource(MemoryResource,cache_info->length);
4050 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4051 (cache_info->type == MemoryCache))
4053 AllocatePixelCachePixels(cache_info);
4054 if (cache_info->pixels == (Quantum *) NULL)
4055 cache_info->pixels=source_info.pixels;
4059 Create memory pixel cache.
4062 if (image->debug != MagickFalse)
4064 (void) FormatMagickSize(cache_info->length,MagickTrue,
4066 (void) FormatLocaleString(message,MaxTextExtent,
4067 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4068 cache_info->filename,cache_info->mapped != MagickFalse ?
4069 "anonymous" : "heap",(double) cache_info->columns,(double)
4070 cache_info->rows,(double) cache_info->number_channels,
4072 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4075 cache_info->type=MemoryCache;
4076 cache_info->metacontent=(void *) NULL;
4077 if (cache_info->metacontent_extent != 0)
4078 cache_info->metacontent=(void *) (cache_info->pixels+
4079 number_pixels*cache_info->number_channels);
4080 if (source_info.storage_class != UndefinedClass)
4082 status=ClonePixelCachePixels(cache_info,&source_info,
4084 RelinquishPixelCachePixels(&source_info);
4089 RelinquishMagickResource(MemoryResource,cache_info->length);
4092 Create pixel cache on disk.
4094 status=AcquireMagickResource(DiskResource,cache_info->length);
4095 if (status == MagickFalse)
4097 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4098 "CacheResourcesExhausted","`%s'",image->filename);
4099 return(MagickFalse);
4101 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4103 RelinquishMagickResource(DiskResource,cache_info->length);
4104 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4106 return(MagickFalse);
4108 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4109 cache_info->length);
4110 if (status == MagickFalse)
4112 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4114 return(MagickFalse);
4116 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
4117 cache_info->metacontent_extent);
4118 status=AcquireMagickResource(AreaResource,cache_info->length);
4119 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4120 cache_info->type=DiskCache;
4123 status=AcquireMagickResource(MapResource,cache_info->length);
4124 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4125 (cache_info->type != MemoryCache))
4126 cache_info->type=DiskCache;
4129 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4130 cache_info->offset,(size_t) cache_info->length);
4131 if (cache_info->pixels == (Quantum *) NULL)
4133 cache_info->type=DiskCache;
4134 cache_info->pixels=source_info.pixels;
4139 Create file-backed memory-mapped pixel cache.
4142 (void) ClosePixelCacheOnDisk(cache_info);
4143 cache_info->type=MapCache;
4144 cache_info->mapped=MagickTrue;
4145 cache_info->metacontent=(void *) NULL;
4146 if (cache_info->metacontent_extent != 0)
4147 cache_info->metacontent=(void *) (cache_info->pixels+
4148 number_pixels*cache_info->number_channels);
4149 if (source_info.storage_class != UndefinedClass)
4151 status=ClonePixelCachePixels(cache_info,&source_info,
4153 RelinquishPixelCachePixels(&source_info);
4155 if (image->debug != MagickFalse)
4157 (void) FormatMagickSize(cache_info->length,MagickTrue,
4159 (void) FormatLocaleString(message,MaxTextExtent,
4160 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4161 cache_info->filename,cache_info->cache_filename,
4162 cache_info->file,(double) cache_info->columns,(double)
4163 cache_info->rows,(double) cache_info->number_channels,
4165 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4171 RelinquishMagickResource(MapResource,cache_info->length);
4174 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4176 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4177 RelinquishPixelCachePixels(&source_info);
4179 if (image->debug != MagickFalse)
4181 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4182 (void) FormatLocaleString(message,MaxTextExtent,
4183 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4184 cache_info->cache_filename,cache_info->file,(double)
4185 cache_info->columns,(double) cache_info->rows,(double)
4186 cache_info->number_channels,format);
4187 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4197 + P e r s i s t P i x e l C a c h e %
4201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4203 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4204 % persistent pixel cache is one that resides on disk and is not destroyed
4205 % when the program exits.
4207 % The format of the PersistPixelCache() method is:
4209 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4210 % const MagickBooleanType attach,MagickOffsetType *offset,
4211 % ExceptionInfo *exception)
4213 % A description of each parameter follows:
4215 % o image: the image.
4217 % o filename: the persistent pixel cache filename.
4219 % o attach: A value other than zero initializes the persistent pixel cache.
4221 % o initialize: A value other than zero initializes the persistent pixel
4224 % o offset: the offset in the persistent cache to store pixels.
4226 % o exception: return any errors or warnings in this structure.
4229 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4230 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4231 ExceptionInfo *exception)
4246 assert(image != (Image *) NULL);
4247 assert(image->signature == MagickSignature);
4248 if (image->debug != MagickFalse)
4249 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4250 assert(image->cache != (void *) NULL);
4251 assert(filename != (const char *) NULL);
4252 assert(offset != (MagickOffsetType *) NULL);
4253 page_size=GetMagickPageSize();
4254 cache_info=(CacheInfo *) image->cache;
4255 assert(cache_info->signature == MagickSignature);
4256 if (attach != MagickFalse)
4259 Attach existing persistent pixel cache.
4261 if (image->debug != MagickFalse)
4262 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4263 "attach persistent cache");
4264 (void) CopyMagickString(cache_info->cache_filename,filename,
4266 cache_info->type=DiskCache;
4267 cache_info->offset=(*offset);
4268 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4269 return(MagickFalse);
4270 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4273 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4274 (cache_info->reference_count == 1))
4276 LockSemaphoreInfo(cache_info->semaphore);
4277 if ((cache_info->mode != ReadMode) &&
4278 (cache_info->type != MemoryCache) &&
4279 (cache_info->reference_count == 1))
4285 Usurp existing persistent pixel cache.
4287 status=rename(cache_info->cache_filename,filename);
4290 (void) CopyMagickString(cache_info->cache_filename,filename,
4292 *offset+=cache_info->length+page_size-(cache_info->length %
4294 UnlockSemaphoreInfo(cache_info->semaphore);
4295 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4296 if (image->debug != MagickFalse)
4297 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4298 "Usurp resident persistent cache");
4302 UnlockSemaphoreInfo(cache_info->semaphore);
4305 Clone persistent pixel cache.
4307 clone_image=(*image);
4308 clone_info=(CacheInfo *) clone_image.cache;
4309 image->cache=ClonePixelCache(cache_info);
4310 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4311 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4312 cache_info->type=DiskCache;
4313 cache_info->offset=(*offset);
4314 cache_info=(CacheInfo *) image->cache;
4315 status=OpenPixelCache(image,IOMode,exception);
4316 if (status != MagickFalse)
4317 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4318 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4319 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4328 + Q u e u e A u t h e n t i c N e x u s %
4332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4334 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4335 % by the region rectangle and returns a pointer to the region. This region is
4336 % subsequently transferred from the pixel cache with
4337 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4338 % pixels are transferred, otherwise a NULL is returned.
4340 % The format of the QueueAuthenticNexus() method is:
4342 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4343 % const ssize_t y,const size_t columns,const size_t rows,
4344 % NexusInfo *nexus_info,ExceptionInfo *exception)
4346 % A description of each parameter follows:
4348 % o image: the image.
4350 % o x,y,columns,rows: These values define the perimeter of a region of
4353 % o nexus_info: the cache nexus to set.
4355 % o exception: return any errors or warnings in this structure.
4358 MagickExport Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4359 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4360 ExceptionInfo *exception)
4375 Validate pixel cache geometry.
4377 assert(image != (const Image *) NULL);
4378 assert(image->signature == MagickSignature);
4379 assert(image->cache != (Cache) NULL);
4380 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4381 assert(cache_info->signature == MagickSignature);
4382 if (cache_info == (Cache) NULL)
4383 return((Quantum *) NULL);
4384 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4386 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4387 "NoPixelsDefinedInCache","`%s'",image->filename);
4388 return((Quantum *) NULL);
4390 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4391 (y >= (ssize_t) cache_info->rows))
4393 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4394 "PixelsAreNotAuthentic","`%s'",image->filename);
4395 return((Quantum *) NULL);
4397 offset=(MagickOffsetType) y*cache_info->columns+x;
4399 return((Quantum *) NULL);
4400 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4401 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4402 if ((MagickSizeType) offset >= number_pixels)
4403 return((Quantum *) NULL);
4409 region.width=columns;
4411 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4419 + 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 %
4423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4425 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4426 % defined by the region rectangle and returns a pointer to the region. This
4427 % region is subsequently transferred from the pixel cache with
4428 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4429 % pixels are transferred, otherwise a NULL is returned.
4431 % The format of the QueueAuthenticPixelsCache() method is:
4433 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4434 % const ssize_t y,const size_t columns,const size_t rows,
4435 % ExceptionInfo *exception)
4437 % A description of each parameter follows:
4439 % o image: the image.
4441 % o x,y,columns,rows: These values define the perimeter of a region of
4444 % o exception: return any errors or warnings in this structure.
4447 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4448 const ssize_t y,const size_t columns,const size_t rows,
4449 ExceptionInfo *exception)
4455 id = GetOpenMPThreadId();
4460 assert(image != (const Image *) NULL);
4461 assert(image->signature == MagickSignature);
4462 assert(image->cache != (Cache) NULL);
4463 cache_info=(CacheInfo *) image->cache;
4464 assert(cache_info->signature == MagickSignature);
4465 assert(id < (int) cache_info->number_threads);
4466 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4476 % Q u e u e A u t h e n t i c P i x e l s %
4480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4482 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4483 % successfully initialized a pointer to a Quantum array representing the
4484 % region is returned, otherwise NULL is returned. The returned pointer may
4485 % point to a temporary working buffer for the pixels or it may point to the
4486 % final location of the pixels in memory.
4488 % Write-only access means that any existing pixel values corresponding to
4489 % the region are ignored. This is useful if the initial image is being
4490 % created from scratch, or if the existing pixel values are to be
4491 % completely replaced without need to refer to their pre-existing values.
4492 % The application is free to read and write the pixel buffer returned by
4493 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4494 % initialize the pixel array values. Initializing pixel array values is the
4495 % application's responsibility.
4497 % Performance is maximized if the selected region is part of one row, or
4498 % one or more full rows, since then there is opportunity to access the
4499 % pixels in-place (without a copy) if the image is in memory, or in a
4500 % memory-mapped file. The returned pointer must *never* be deallocated
4503 % Pixels accessed via the returned pointer represent a simple array of type
4504 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4505 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4506 % obtain the meta-content (of type void) corresponding to the region.
4507 % Once the Quantum (and/or Quantum) array has been updated, the
4508 % changes must be saved back to the underlying image using
4509 % SyncAuthenticPixels() or they may be lost.
4511 % The format of the QueueAuthenticPixels() method is:
4513 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4514 % const ssize_t y,const size_t columns,const size_t rows,
4515 % ExceptionInfo *exception)
4517 % A description of each parameter follows:
4519 % o image: the image.
4521 % o x,y,columns,rows: These values define the perimeter of a region of
4524 % o exception: return any errors or warnings in this structure.
4527 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4528 const ssize_t y,const size_t columns,const size_t rows,
4529 ExceptionInfo *exception)
4535 id = GetOpenMPThreadId();
4540 assert(image != (Image *) NULL);
4541 assert(image->signature == MagickSignature);
4542 assert(image->cache != (Cache) NULL);
4543 cache_info=(CacheInfo *) image->cache;
4544 assert(cache_info->signature == MagickSignature);
4545 if (cache_info->methods.queue_authentic_pixels_handler !=
4546 (QueueAuthenticPixelsHandler) NULL)
4548 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4549 columns,rows,exception);
4552 assert(id < (int) cache_info->number_threads);
4553 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4563 + 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 %
4567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4569 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4572 % The format of the ReadPixelCacheMetacontent() method is:
4574 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4575 % NexusInfo *nexus_info,ExceptionInfo *exception)
4577 % A description of each parameter follows:
4579 % o cache_info: the pixel cache.
4581 % o nexus_info: the cache nexus to read the metacontent.
4583 % o exception: return any errors or warnings in this structure.
4586 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4587 NexusInfo *nexus_info,ExceptionInfo *exception)
4600 register unsigned char
4606 if (cache_info->metacontent_extent == 0)
4607 return(MagickFalse);
4608 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4610 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4611 nexus_info->region.x;
4612 length=(MagickSizeType) nexus_info->region.width*
4613 cache_info->metacontent_extent;
4614 rows=nexus_info->region.height;
4616 q=(unsigned char *) nexus_info->metacontent;
4617 switch (cache_info->type)
4622 register unsigned char
4626 Read meta-content from memory.
4628 if ((cache_info->columns == nexus_info->region.width) &&
4629 (extent == (MagickSizeType) ((size_t) extent)))
4634 p=(unsigned char *) cache_info->metacontent+offset*
4635 cache_info->metacontent_extent;
4636 for (y=0; y < (ssize_t) rows; y++)
4638 (void) memcpy(q,p,(size_t) length);
4639 p+=cache_info->metacontent_extent*cache_info->columns;
4640 q+=cache_info->metacontent_extent*nexus_info->region.width;
4647 Read meta content from disk.
4649 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4651 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4652 cache_info->cache_filename);
4653 return(MagickFalse);
4655 if ((cache_info->columns == nexus_info->region.width) &&
4656 (extent <= MagickMaxBufferExtent))
4661 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4662 for (y=0; y < (ssize_t) rows; y++)
4664 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4665 cache_info->number_channels*sizeof(Quantum)+offset*
4666 cache_info->metacontent_extent,length,(unsigned char *) q);
4667 if ((MagickSizeType) count != length)
4669 offset+=cache_info->columns;
4670 q+=cache_info->metacontent_extent*nexus_info->region.width;
4672 if (y < (ssize_t) rows)
4674 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4675 cache_info->cache_filename);
4676 return(MagickFalse);
4683 if ((cache_info->debug != MagickFalse) &&
4684 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4685 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4686 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4687 nexus_info->region.width,(double) nexus_info->region.height,(double)
4688 nexus_info->region.x,(double) nexus_info->region.y);
4693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4697 + R e a d P i x e l C a c h e P i x e l s %
4701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4703 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4706 % The format of the ReadPixelCachePixels() method is:
4708 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4709 % NexusInfo *nexus_info,ExceptionInfo *exception)
4711 % A description of each parameter follows:
4713 % o cache_info: the pixel cache.
4715 % o nexus_info: the cache nexus to read the pixels.
4717 % o exception: return any errors or warnings in this structure.
4720 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4721 NexusInfo *nexus_info,ExceptionInfo *exception)
4740 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4742 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4743 nexus_info->region.x;
4744 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4746 rows=nexus_info->region.height;
4748 q=nexus_info->pixels;
4749 switch (cache_info->type)
4758 Read pixels from memory.
4760 if ((cache_info->columns == nexus_info->region.width) &&
4761 (extent == (MagickSizeType) ((size_t) extent)))
4766 p=cache_info->pixels+offset*cache_info->number_channels;
4767 for (y=0; y < (ssize_t) rows; y++)
4769 (void) memcpy(q,p,(size_t) length);
4770 p+=cache_info->number_channels*cache_info->columns;
4771 q+=cache_info->number_channels*nexus_info->region.width;
4778 Read pixels from disk.
4780 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4782 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4783 cache_info->cache_filename);
4784 return(MagickFalse);
4786 if ((cache_info->columns == nexus_info->region.width) &&
4787 (extent <= MagickMaxBufferExtent))
4792 for (y=0; y < (ssize_t) rows; y++)
4794 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4795 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4796 if ((MagickSizeType) count != length)
4798 offset+=cache_info->columns;
4799 q+=cache_info->number_channels*nexus_info->region.width;
4801 if (y < (ssize_t) rows)
4803 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4804 cache_info->cache_filename);
4805 return(MagickFalse);
4812 if ((cache_info->debug != MagickFalse) &&
4813 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4814 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4815 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4816 nexus_info->region.width,(double) nexus_info->region.height,(double)
4817 nexus_info->region.x,(double) nexus_info->region.y);
4822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4826 + R e f e r e n c e P i x e l C a c h e %
4830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4832 % ReferencePixelCache() increments the reference count associated with the
4833 % pixel cache returning a pointer to the cache.
4835 % The format of the ReferencePixelCache method is:
4837 % Cache ReferencePixelCache(Cache cache_info)
4839 % A description of each parameter follows:
4841 % o cache_info: the pixel cache.
4844 MagickExport Cache ReferencePixelCache(Cache cache)
4849 assert(cache != (Cache *) NULL);
4850 cache_info=(CacheInfo *) cache;
4851 assert(cache_info->signature == MagickSignature);
4852 LockSemaphoreInfo(cache_info->semaphore);
4853 cache_info->reference_count++;
4854 UnlockSemaphoreInfo(cache_info->semaphore);
4859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4863 + S e t P i x e l C a c h e M e t h o d s %
4867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4869 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4871 % The format of the SetPixelCacheMethods() method is:
4873 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4875 % A description of each parameter follows:
4877 % o cache: the pixel cache.
4879 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4882 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4887 GetOneAuthenticPixelFromHandler
4888 get_one_authentic_pixel_from_handler;
4890 GetOneVirtualPixelFromHandler
4891 get_one_virtual_pixel_from_handler;
4894 Set cache pixel methods.
4896 assert(cache != (Cache) NULL);
4897 assert(cache_methods != (CacheMethods *) NULL);
4898 cache_info=(CacheInfo *) cache;
4899 assert(cache_info->signature == MagickSignature);
4900 if (cache_info->debug != MagickFalse)
4901 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4902 cache_info->filename);
4903 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4904 cache_info->methods.get_virtual_pixel_handler=
4905 cache_methods->get_virtual_pixel_handler;
4906 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4907 cache_info->methods.destroy_pixel_handler=
4908 cache_methods->destroy_pixel_handler;
4909 if (cache_methods->get_virtual_metacontent_from_handler !=
4910 (GetVirtualMetacontentFromHandler) NULL)
4911 cache_info->methods.get_virtual_metacontent_from_handler=
4912 cache_methods->get_virtual_metacontent_from_handler;
4913 if (cache_methods->get_authentic_pixels_handler !=
4914 (GetAuthenticPixelsHandler) NULL)
4915 cache_info->methods.get_authentic_pixels_handler=
4916 cache_methods->get_authentic_pixels_handler;
4917 if (cache_methods->queue_authentic_pixels_handler !=
4918 (QueueAuthenticPixelsHandler) NULL)
4919 cache_info->methods.queue_authentic_pixels_handler=
4920 cache_methods->queue_authentic_pixels_handler;
4921 if (cache_methods->sync_authentic_pixels_handler !=
4922 (SyncAuthenticPixelsHandler) NULL)
4923 cache_info->methods.sync_authentic_pixels_handler=
4924 cache_methods->sync_authentic_pixels_handler;
4925 if (cache_methods->get_authentic_pixels_from_handler !=
4926 (GetAuthenticPixelsFromHandler) NULL)
4927 cache_info->methods.get_authentic_pixels_from_handler=
4928 cache_methods->get_authentic_pixels_from_handler;
4929 if (cache_methods->get_authentic_metacontent_from_handler !=
4930 (GetAuthenticMetacontentFromHandler) NULL)
4931 cache_info->methods.get_authentic_metacontent_from_handler=
4932 cache_methods->get_authentic_metacontent_from_handler;
4933 get_one_virtual_pixel_from_handler=
4934 cache_info->methods.get_one_virtual_pixel_from_handler;
4935 if (get_one_virtual_pixel_from_handler !=
4936 (GetOneVirtualPixelFromHandler) NULL)
4937 cache_info->methods.get_one_virtual_pixel_from_handler=
4938 cache_methods->get_one_virtual_pixel_from_handler;
4939 get_one_authentic_pixel_from_handler=
4940 cache_methods->get_one_authentic_pixel_from_handler;
4941 if (get_one_authentic_pixel_from_handler !=
4942 (GetOneAuthenticPixelFromHandler) NULL)
4943 cache_info->methods.get_one_authentic_pixel_from_handler=
4944 cache_methods->get_one_authentic_pixel_from_handler;
4948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4952 + S e t P i x e l C a c h e N e x u s P i x e l s %
4956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4958 % SetPixelCacheNexusPixels() defines the region of the cache for the
4959 % specified cache nexus.
4961 % The format of the SetPixelCacheNexusPixels() method is:
4963 % Quantum SetPixelCacheNexusPixels(const Image *image,
4964 % const RectangleInfo *region,NexusInfo *nexus_info,
4965 % ExceptionInfo *exception)
4967 % A description of each parameter follows:
4969 % o image: the image.
4971 % o region: A pointer to the RectangleInfo structure that defines the
4972 % region of this particular cache nexus.
4974 % o nexus_info: the cache nexus to set.
4976 % o exception: return any errors or warnings in this structure.
4980 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4981 NexusInfo *nexus_info,ExceptionInfo *exception)
4983 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4984 return(MagickFalse);
4985 nexus_info->mapped=MagickFalse;
4986 nexus_info->cache=(Quantum *) AcquireAlignedMemory(1,(size_t)
4987 nexus_info->length);
4988 if (nexus_info->cache == (Quantum *) NULL)
4990 nexus_info->mapped=MagickTrue;
4991 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4992 nexus_info->length);
4994 if (nexus_info->cache == (Quantum *) NULL)
4996 (void) ThrowMagickException(exception,GetMagickModule(),
4997 ResourceLimitError,"MemoryAllocationFailed","`%s'",
4998 cache_info->filename);
4999 return(MagickFalse);
5004 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5005 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5017 cache_info=(CacheInfo *) image->cache;
5018 assert(cache_info->signature == MagickSignature);
5019 if (cache_info->type == UndefinedCache)
5020 return((Quantum *) NULL);
5021 nexus_info->region=(*region);
5022 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5023 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5029 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5030 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5031 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5032 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5033 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5034 ((nexus_info->region.width == cache_info->columns) ||
5035 ((nexus_info->region.width % cache_info->columns) == 0)))))
5041 Pixels are accessed directly from memory.
5043 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5044 nexus_info->region.x;
5045 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5047 nexus_info->metacontent=(void *) NULL;
5048 if (cache_info->metacontent_extent != 0)
5049 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5050 offset*cache_info->metacontent_extent;
5051 return(nexus_info->pixels);
5055 Pixels are stored in a cache region until they are synced to the cache.
5057 number_pixels=(MagickSizeType) nexus_info->region.width*
5058 nexus_info->region.height;
5059 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5060 if (cache_info->metacontent_extent != 0)
5061 length+=number_pixels*cache_info->metacontent_extent;
5062 if (nexus_info->cache == (Quantum *) NULL)
5064 nexus_info->length=length;
5065 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5066 if (status == MagickFalse)
5068 nexus_info->length=0;
5069 return((Quantum *) NULL);
5073 if (nexus_info->length != length)
5075 RelinquishCacheNexusPixels(nexus_info);
5076 nexus_info->length=length;
5077 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5078 if (status == MagickFalse)
5080 nexus_info->length=0;
5081 return((Quantum *) NULL);
5084 nexus_info->pixels=nexus_info->cache;
5085 nexus_info->metacontent=(void *) NULL;
5086 if (cache_info->metacontent_extent != 0)
5087 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5088 cache_info->number_channels);
5089 return(nexus_info->pixels);
5093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5097 % 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 %
5101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5103 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5104 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5105 % access that is outside the boundaries of the image cache.
5107 % The format of the SetPixelCacheVirtualMethod() method is:
5109 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5110 % const VirtualPixelMethod virtual_pixel_method)
5112 % A description of each parameter follows:
5114 % o image: the image.
5116 % o virtual_pixel_method: choose the type of virtual pixel.
5119 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5120 const VirtualPixelMethod virtual_pixel_method)
5128 assert(image != (Image *) NULL);
5129 assert(image->signature == MagickSignature);
5130 if (image->debug != MagickFalse)
5131 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5132 assert(image->cache != (Cache) NULL);
5133 cache_info=(CacheInfo *) image->cache;
5134 assert(cache_info->signature == MagickSignature);
5135 method=cache_info->virtual_pixel_method;
5136 cache_info->virtual_pixel_method=virtual_pixel_method;
5141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5145 + 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 %
5149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5151 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5152 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5153 % is synced, otherwise MagickFalse.
5155 % The format of the SyncAuthenticPixelCacheNexus() method is:
5157 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5158 % NexusInfo *nexus_info,ExceptionInfo *exception)
5160 % A description of each parameter follows:
5162 % o image: the image.
5164 % o nexus_info: the cache nexus to sync.
5166 % o exception: return any errors or warnings in this structure.
5169 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5170 NexusInfo *nexus_info,ExceptionInfo *exception)
5179 Transfer pixels to the cache.
5181 assert(image != (Image *) NULL);
5182 assert(image->signature == MagickSignature);
5183 if (image->cache == (Cache) NULL)
5184 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5185 cache_info=(CacheInfo *) image->cache;
5186 assert(cache_info->signature == MagickSignature);
5187 if (cache_info->type == UndefinedCache)
5188 return(MagickFalse);
5189 if ((image->clip_mask != (Image *) NULL) &&
5190 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5191 return(MagickFalse);
5192 if ((image->mask != (Image *) NULL) &&
5193 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5194 return(MagickFalse);
5195 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5197 assert(cache_info->signature == MagickSignature);
5198 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5199 if ((cache_info->metacontent_extent != 0) &&
5200 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5201 return(MagickFalse);
5206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5210 + S y n c A u t h e n t i c P i x e l C a c h e %
5214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5216 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5217 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5218 % otherwise MagickFalse.
5220 % The format of the SyncAuthenticPixelsCache() method is:
5222 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5223 % ExceptionInfo *exception)
5225 % A description of each parameter follows:
5227 % o image: the image.
5229 % o exception: return any errors or warnings in this structure.
5232 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5233 ExceptionInfo *exception)
5239 id = GetOpenMPThreadId();
5244 assert(image != (Image *) NULL);
5245 assert(image->signature == MagickSignature);
5246 assert(image->cache != (Cache) NULL);
5247 cache_info=(CacheInfo *) image->cache;
5248 assert(cache_info->signature == MagickSignature);
5249 assert(id < (int) cache_info->number_threads);
5250 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5260 % S y n c A u t h e n t i c P i x e l s %
5264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5266 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5267 % The method returns MagickTrue if the pixel region is flushed, otherwise
5270 % The format of the SyncAuthenticPixels() method is:
5272 % MagickBooleanType SyncAuthenticPixels(Image *image,
5273 % ExceptionInfo *exception)
5275 % A description of each parameter follows:
5277 % o image: the image.
5279 % o exception: return any errors or warnings in this structure.
5282 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5283 ExceptionInfo *exception)
5289 id = GetOpenMPThreadId();
5294 assert(image != (Image *) NULL);
5295 assert(image->signature == MagickSignature);
5296 assert(image->cache != (Cache) NULL);
5297 cache_info=(CacheInfo *) image->cache;
5298 assert(cache_info->signature == MagickSignature);
5299 if (cache_info->methods.sync_authentic_pixels_handler !=
5300 (SyncAuthenticPixelsHandler) NULL)
5302 status=cache_info->methods.sync_authentic_pixels_handler(image,
5306 assert(id < (int) cache_info->number_threads);
5307 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5317 + 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 %
5321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5323 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5324 % of the pixel cache.
5326 % The format of the WritePixelCacheMetacontent() method is:
5328 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5329 % NexusInfo *nexus_info,ExceptionInfo *exception)
5331 % A description of each parameter follows:
5333 % o cache_info: the pixel cache.
5335 % o nexus_info: the cache nexus to write the meta-content.
5337 % o exception: return any errors or warnings in this structure.
5340 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5341 NexusInfo *nexus_info,ExceptionInfo *exception)
5351 register const unsigned char
5360 if (cache_info->metacontent_extent == 0)
5361 return(MagickFalse);
5362 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5364 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5365 nexus_info->region.x;
5366 length=(MagickSizeType) nexus_info->region.width*
5367 cache_info->metacontent_extent;
5368 rows=nexus_info->region.height;
5369 extent=(MagickSizeType) length*rows;
5370 p=(unsigned char *) nexus_info->metacontent;
5371 switch (cache_info->type)
5376 register unsigned char
5380 Write associated pixels to memory.
5382 if ((cache_info->columns == nexus_info->region.width) &&
5383 (extent == (MagickSizeType) ((size_t) extent)))
5388 q=(unsigned char *) cache_info->metacontent+offset*
5389 cache_info->metacontent_extent;
5390 for (y=0; y < (ssize_t) rows; y++)
5392 (void) memcpy(q,p,(size_t) length);
5393 p+=nexus_info->region.width*cache_info->metacontent_extent;
5394 q+=cache_info->columns*cache_info->metacontent_extent;
5401 Write associated pixels to disk.
5403 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5405 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5406 cache_info->cache_filename);
5407 return(MagickFalse);
5409 if ((cache_info->columns == nexus_info->region.width) &&
5410 (extent <= MagickMaxBufferExtent))
5415 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5416 for (y=0; y < (ssize_t) rows; y++)
5418 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5419 cache_info->number_channels*sizeof(Quantum)+offset*
5420 cache_info->metacontent_extent,length,(const unsigned char *) p);
5421 if ((MagickSizeType) count != length)
5423 p+=nexus_info->region.width*cache_info->metacontent_extent;
5424 offset+=cache_info->columns;
5426 if (y < (ssize_t) rows)
5428 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5429 cache_info->cache_filename);
5430 return(MagickFalse);
5437 if ((cache_info->debug != MagickFalse) &&
5438 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5439 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5440 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5441 nexus_info->region.width,(double) nexus_info->region.height,(double)
5442 nexus_info->region.x,(double) nexus_info->region.y);
5447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5451 + W r i t e C a c h e P i x e l s %
5455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5457 % WritePixelCachePixels() writes image pixels to the specified region of the
5460 % The format of the WritePixelCachePixels() method is:
5462 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5463 % NexusInfo *nexus_info,ExceptionInfo *exception)
5465 % A description of each parameter follows:
5467 % o cache_info: the pixel cache.
5469 % o nexus_info: the cache nexus to write the pixels.
5471 % o exception: return any errors or warnings in this structure.
5474 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5475 NexusInfo *nexus_info,ExceptionInfo *exception)
5485 register const Quantum
5494 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5496 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5497 nexus_info->region.x;
5498 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5500 rows=nexus_info->region.height;
5502 p=nexus_info->pixels;
5503 switch (cache_info->type)
5512 Write pixels to memory.
5514 if ((cache_info->columns == nexus_info->region.width) &&
5515 (extent == (MagickSizeType) ((size_t) extent)))
5520 q=cache_info->pixels+offset*cache_info->number_channels;
5521 for (y=0; y < (ssize_t) rows; y++)
5523 (void) memcpy(q,p,(size_t) length);
5524 p+=nexus_info->region.width*cache_info->number_channels;
5525 q+=cache_info->columns*cache_info->number_channels;
5532 Write pixels to disk.
5534 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5536 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5537 cache_info->cache_filename);
5538 return(MagickFalse);
5540 if ((cache_info->columns == nexus_info->region.width) &&
5541 (extent <= MagickMaxBufferExtent))
5546 for (y=0; y < (ssize_t) rows; y++)
5548 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5549 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5551 if ((MagickSizeType) count != length)
5553 p+=nexus_info->region.width*cache_info->number_channels;
5554 offset+=cache_info->columns;
5556 if (y < (ssize_t) rows)
5558 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5559 cache_info->cache_filename);
5560 return(MagickFalse);
5567 if ((cache_info->debug != MagickFalse) &&
5568 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5569 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5570 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5571 nexus_info->region.width,(double) nexus_info->region.height,(double)
5572 nexus_info->region.x,(double) nexus_info->region.y);