2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % CCCC AAA CCCC H H EEEEE %
8 % C AAAAA C HHHHH EEE %
10 % CCCC A A CCCC H H EEEEE %
13 % MagickCore Pixel Cache Methods %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/composite-private.h"
50 #include "MagickCore/exception.h"
51 #include "MagickCore/exception-private.h"
52 #include "MagickCore/geometry.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/log.h"
55 #include "MagickCore/magick.h"
56 #include "MagickCore/memory_.h"
57 #include "MagickCore/pixel.h"
58 #include "MagickCore/pixel-accessor.h"
59 #include "MagickCore/policy.h"
60 #include "MagickCore/quantum.h"
61 #include "MagickCore/random_.h"
62 #include "MagickCore/resource_.h"
63 #include "MagickCore/semaphore.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/string-private.h"
67 #include "MagickCore/thread-private.h"
68 #include "MagickCore/utility.h"
69 #if defined(MAGICKCORE_ZLIB_DELEGATE)
76 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
81 typedef struct _MagickModulo
111 Forward declarations.
113 #if defined(__cplusplus) || defined(c_plusplus)
118 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
119 const ssize_t,const size_t,const size_t,ExceptionInfo *),
120 *GetVirtualPixelsCache(const Image *);
123 *GetVirtualMetacontentFromCache(const Image *);
125 static MagickBooleanType
126 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
127 PixelPacket *,ExceptionInfo *),
128 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
129 const ssize_t,const ssize_t,PixelPacket *,ExceptionInfo *),
130 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
131 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
132 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
133 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
134 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
135 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
138 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
139 const size_t,ExceptionInfo *),
140 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
141 const size_t,ExceptionInfo *),
142 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
145 #if defined(__cplusplus) || defined(c_plusplus)
152 static volatile MagickBooleanType
153 instantiate_cache = MagickFalse;
156 *cache_semaphore = (SemaphoreInfo *) NULL;
159 *cache_resources = (SplayTreeInfo *) NULL;
162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 + A c q u i r e P i x e l C a c h e %
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172 % AcquirePixelCache() acquires a pixel cache.
174 % The format of the AcquirePixelCache() method is:
176 % Cache AcquirePixelCache(const size_t number_threads)
178 % A description of each parameter follows:
180 % o number_threads: the number of nexus threads.
183 MagickExport Cache AcquirePixelCache(const size_t number_threads)
188 cache_info=(CacheInfo *) AcquireMagickMemory(sizeof(*cache_info));
189 if (cache_info == (CacheInfo *) NULL)
190 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
191 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
192 cache_info->type=UndefinedCache;
193 cache_info->mode=IOMode;
194 cache_info->colorspace=RGBColorspace;
195 cache_info->file=(-1);
196 cache_info->id=GetMagickThreadId();
197 cache_info->number_threads=number_threads;
198 if (number_threads == 0)
199 cache_info->number_threads=GetOpenMPMaximumThreads();
200 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
201 if (cache_info->nexus_info == (NexusInfo **) NULL)
202 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
203 cache_info->semaphore=AllocateSemaphoreInfo();
204 cache_info->reference_count=1;
205 cache_info->disk_semaphore=AllocateSemaphoreInfo();
206 cache_info->debug=IsEventLogging();
207 cache_info->signature=MagickSignature;
208 if ((cache_resources == (SplayTreeInfo *) NULL) &&
209 (instantiate_cache == MagickFalse))
211 if (cache_semaphore == (SemaphoreInfo *) NULL)
212 AcquireSemaphoreInfo(&cache_semaphore);
213 LockSemaphoreInfo(cache_semaphore);
214 if ((cache_resources == (SplayTreeInfo *) NULL) &&
215 (instantiate_cache == MagickFalse))
217 cache_resources=NewSplayTree((int (*)(const void *,const void *))
218 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
219 instantiate_cache=MagickTrue;
221 UnlockSemaphoreInfo(cache_semaphore);
223 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
224 return((Cache ) cache_info);
228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 % A c q u i r e P i x e l C a c h e N e x u s %
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
240 % The format of the AcquirePixelCacheNexus method is:
242 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
244 % A description of each parameter follows:
246 % o number_threads: the number of nexus threads.
249 MagickExport NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
257 nexus_info=(NexusInfo **) AcquireQuantumMemory(number_threads,
258 sizeof(*nexus_info));
259 if (nexus_info == (NexusInfo **) NULL)
260 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
261 for (i=0; i < (ssize_t) number_threads; i++)
263 nexus_info[i]=(NexusInfo *) AcquireAlignedMemory(1,sizeof(**nexus_info));
264 if (nexus_info[i] == (NexusInfo *) NULL)
265 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
266 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
267 nexus_info[i]->signature=MagickSignature;
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 + A c q u i r e P i x e l C a c h e P i x e l s %
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283 % AcquirePixelCachePixels() returns the pixels associated with the specified
286 % The format of the AcquirePixelCachePixels() method is:
288 % const void *AcquirePixelCachePixels(const Image *image,
289 % MagickSizeType *length,ExceptionInfo *exception)
291 % A description of each parameter follows:
293 % o image: the image.
295 % o length: the pixel cache length.
297 % o exception: return any errors or warnings in this structure.
300 MagickExport const void *AcquirePixelCachePixels(const Image *image,
301 MagickSizeType *length,ExceptionInfo *exception)
306 assert(image != (const Image *) NULL);
307 assert(image->signature == MagickSignature);
308 assert(exception != (ExceptionInfo *) NULL);
309 assert(exception->signature == MagickSignature);
310 assert(image->cache != (Cache) NULL);
311 cache_info=(CacheInfo *) image->cache;
312 assert(cache_info->signature == MagickSignature);
314 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
315 return((const void *) NULL);
316 *length=cache_info->length;
317 return((const void *) cache_info->pixels);
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325 + C a c h e C o m p o n e n t G e n e s i s %
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331 % CacheComponentGenesis() instantiates the cache component.
333 % The format of the CacheComponentGenesis method is:
335 % MagickBooleanType CacheComponentGenesis(void)
338 MagickExport MagickBooleanType CacheComponentGenesis(void)
340 AcquireSemaphoreInfo(&cache_semaphore);
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 + C a c h e C o m p o n e n t T e r m i n u s %
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355 % CacheComponentTerminus() destroys the cache component.
357 % The format of the CacheComponentTerminus() method is:
359 % CacheComponentTerminus(void)
362 MagickExport void CacheComponentTerminus(void)
364 if (cache_semaphore == (SemaphoreInfo *) NULL)
365 AcquireSemaphoreInfo(&cache_semaphore);
366 LockSemaphoreInfo(cache_semaphore);
367 if (cache_resources != (SplayTreeInfo *) NULL)
368 cache_resources=DestroySplayTree(cache_resources);
369 instantiate_cache=MagickFalse;
370 UnlockSemaphoreInfo(cache_semaphore);
371 DestroySemaphoreInfo(&cache_semaphore);
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 + C l i p P i x e l C a c h e N e x u s %
383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
386 % mask. It returns MagickTrue if the pixel region is clipped, otherwise
389 % The format of the ClipPixelCacheNexus() method is:
391 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
392 % ExceptionInfo *exception)
394 % A description of each parameter follows:
396 % o image: the image.
398 % o nexus_info: the cache nexus to clip.
400 % o exception: return any errors or warnings in this structure.
403 static MagickBooleanType ClipPixelCacheNexus(Image *image,
404 NexusInfo *nexus_info,ExceptionInfo *exception)
416 register const Quantum
429 if (image->debug != MagickFalse)
430 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
431 if (image->clip_mask == (Image *) NULL)
433 cache_info=(CacheInfo *) image->cache;
434 if (cache_info == (Cache) NULL)
436 image_nexus=AcquirePixelCacheNexus(1);
437 clip_nexus=AcquirePixelCacheNexus(1);
438 if ((image_nexus == (NexusInfo **) NULL) ||
439 (clip_nexus == (NexusInfo **) NULL))
440 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
441 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
442 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
443 nexus_info->region.height,image_nexus[0],exception);
444 q=nexus_info->pixels;
445 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
446 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
447 nexus_info->region.height,clip_nexus[0],exception);
448 number_pixels=(MagickSizeType) nexus_info->region.width*
449 nexus_info->region.height;
450 for (i=0; i < (ssize_t) number_pixels; i++)
452 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
454 if (GetPixelIntensity(image,r) > ((Quantum) QuantumRange/2))
456 SetPixelRed(image,GetPixelRed(image,p),q);
457 SetPixelGreen(image,GetPixelGreen(image,p),q);
458 SetPixelBlue(image,GetPixelBlue(image,p),q);
459 if (cache_info->colorspace == CMYKColorspace)
460 SetPixelBlack(image,GetPixelBlack(image,p),q);
461 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
463 p+=GetPixelComponents(image);
464 q+=GetPixelComponents(image);
465 r+=GetPixelComponents(image->clip_mask);
467 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
468 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
469 if (i < (ssize_t) number_pixels)
475 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479 + C l o n e P i x e l C a c h e %
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 % ClonePixelCache() clones a pixel cache.
487 % The format of the ClonePixelCache() method is:
489 % Cache ClonePixelCache(const Cache cache)
491 % A description of each parameter follows:
493 % o cache: the pixel cache.
496 MagickExport Cache ClonePixelCache(const Cache cache)
504 assert(cache != (const Cache) NULL);
505 cache_info=(const CacheInfo *) cache;
506 assert(cache_info->signature == MagickSignature);
507 if (cache_info->debug != MagickFalse)
508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
509 cache_info->filename);
510 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
511 if (clone_info == (Cache) NULL)
512 return((Cache) NULL);
513 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
514 return((Cache ) clone_info);
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522 + C l o n e P i x e l C a c h e P i x e l s %
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
527 % ClonePixelCachePixels() clones the source pixel cache to the destination
530 % The format of the ClonePixelCachePixels() method is:
532 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
533 % CacheInfo *source_info,ExceptionInfo *exception)
535 % A description of each parameter follows:
537 % o cache_info: the pixel cache.
539 % o source_info: the source pixel cache.
541 % o exception: return any errors or warnings in this structure.
545 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
551 LockSemaphoreInfo(cache_info->disk_semaphore);
552 if (cache_info->file != -1)
554 status=close(cache_info->file);
555 cache_info->file=(-1);
556 RelinquishMagickResource(FileResource,1);
558 UnlockSemaphoreInfo(cache_info->disk_semaphore);
559 return(status == -1 ? MagickFalse : MagickTrue);
562 static void LimitPixelCacheDescriptors(void)
569 Limit # of open file descriptors.
571 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
573 LockSemaphoreInfo(cache_semaphore);
574 if (cache_resources == (SplayTreeInfo *) NULL)
576 UnlockSemaphoreInfo(cache_semaphore);
579 ResetSplayTreeIterator(cache_resources);
580 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
581 while (p != (CacheInfo *) NULL)
583 if ((p->type == DiskCache) && (p->file != -1))
585 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
587 for (q=p; p != (CacheInfo *) NULL; )
589 if ((p->type == DiskCache) && (p->file != -1) &&
590 (p->timestamp < q->timestamp))
592 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
594 if (q != (CacheInfo *) NULL)
597 Close least recently used cache.
599 (void) close(q->file);
602 UnlockSemaphoreInfo(cache_semaphore);
605 static inline MagickSizeType MagickMax(const MagickSizeType x,
606 const MagickSizeType y)
613 static inline MagickSizeType MagickMin(const MagickSizeType x,
614 const MagickSizeType y)
621 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
628 Open pixel cache on disk.
630 LockSemaphoreInfo(cache_info->disk_semaphore);
631 if (cache_info->file != -1)
633 UnlockSemaphoreInfo(cache_info->disk_semaphore);
634 return(MagickTrue); /* cache already open */
636 LimitPixelCacheDescriptors();
637 if (*cache_info->cache_filename == '\0')
638 file=AcquireUniqueFileResource(cache_info->cache_filename);
644 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
649 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
652 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
658 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
661 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
667 UnlockSemaphoreInfo(cache_info->disk_semaphore);
670 (void) AcquireMagickResource(FileResource,1);
671 cache_info->file=file;
672 cache_info->timestamp=time(0);
673 UnlockSemaphoreInfo(cache_info->disk_semaphore);
677 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
678 const MagickOffsetType offset,const MagickSizeType length,
679 unsigned char *restrict buffer)
681 register MagickOffsetType
687 cache_info->timestamp=time(0);
688 #if !defined(MAGICKCORE_HAVE_PREAD)
689 LockSemaphoreInfo(cache_info->disk_semaphore);
690 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
692 UnlockSemaphoreInfo(cache_info->disk_semaphore);
693 return((MagickOffsetType) -1);
697 for (i=0; i < (MagickOffsetType) length; i+=count)
699 #if !defined(MAGICKCORE_HAVE_PREAD)
700 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
701 (MagickSizeType) SSIZE_MAX));
703 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
704 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
715 #if !defined(MAGICKCORE_HAVE_PREAD)
716 UnlockSemaphoreInfo(cache_info->disk_semaphore);
721 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
722 const MagickOffsetType offset,const MagickSizeType length,
723 const unsigned char *restrict buffer)
725 register MagickOffsetType
731 cache_info->timestamp=time(0);
732 #if !defined(MAGICKCORE_HAVE_PWRITE)
733 LockSemaphoreInfo(cache_info->disk_semaphore);
734 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
736 UnlockSemaphoreInfo(cache_info->disk_semaphore);
737 return((MagickOffsetType) -1);
741 for (i=0; i < (MagickOffsetType) length; i+=count)
743 #if !defined(MAGICKCORE_HAVE_PWRITE)
744 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
745 (MagickSizeType) SSIZE_MAX));
747 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
748 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
759 #if !defined(MAGICKCORE_HAVE_PWRITE)
760 UnlockSemaphoreInfo(cache_info->disk_semaphore);
765 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
766 CacheInfo *cache_info,ExceptionInfo *exception)
771 register MagickOffsetType
781 Clone pixel cache (both caches on disk).
783 if (cache_info->debug != MagickFalse)
784 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
785 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
787 if (blob == (unsigned char *) NULL)
789 (void) ThrowMagickException(exception,GetMagickModule(),
790 ResourceLimitError,"MemoryAllocationFailed","`%s'",
791 cache_info->filename);
794 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
796 blob=(unsigned char *) RelinquishMagickMemory(blob);
797 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
798 cache_info->cache_filename);
801 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
803 (void) ClosePixelCacheOnDisk(cache_info);
804 blob=(unsigned char *) RelinquishMagickMemory(blob);
805 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
806 clone_info->cache_filename);
810 for (i=0; i < (MagickOffsetType) cache_info->length; i+=count)
812 count=ReadPixelCacheRegion(cache_info,cache_info->offset+i,
813 MagickMin(cache_info->length-i,(MagickSizeType) MagickMaxBufferExtent),
817 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
818 cache_info->cache_filename);
821 length=(size_t) count;
822 count=WritePixelCacheRegion(clone_info,clone_info->offset+i,length,blob);
823 if ((MagickSizeType) count != length)
825 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
826 clone_info->cache_filename);
830 (void) ClosePixelCacheOnDisk(clone_info);
831 (void) ClosePixelCacheOnDisk(cache_info);
832 blob=(unsigned char *) RelinquishMagickMemory(blob);
833 if (i < (MagickOffsetType) cache_info->length)
838 static MagickBooleanType OptimizedPixelCacheClone(CacheInfo *clone_info,
839 CacheInfo *cache_info,ExceptionInfo *exception)
844 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
847 Clone pixel cache (both caches in memory).
849 if (cache_info->debug != MagickFalse)
850 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
851 (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t)
855 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
858 Clone pixel cache (one cache on disk, one in memory).
860 if (cache_info->debug != MagickFalse)
861 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
862 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
864 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
865 cache_info->cache_filename);
868 count=ReadPixelCacheRegion(cache_info,cache_info->offset,
869 cache_info->length,(unsigned char *) clone_info->pixels);
870 (void) ClosePixelCacheOnDisk(cache_info);
871 if ((MagickSizeType) count != cache_info->length)
873 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
874 cache_info->cache_filename);
879 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
882 Clone pixel cache (one cache on disk, one in memory).
884 if (clone_info->debug != MagickFalse)
885 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
886 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
888 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
889 clone_info->cache_filename);
892 count=WritePixelCacheRegion(clone_info,clone_info->offset,
893 clone_info->length,(unsigned char *) cache_info->pixels);
894 (void) ClosePixelCacheOnDisk(clone_info);
895 if ((MagickSizeType) count != clone_info->length)
897 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
898 clone_info->cache_filename);
904 Clone pixel cache (both caches on disk).
906 return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception));
909 static MagickBooleanType UnoptimizedPixelCacheClone(CacheInfo *clone_info,
910 CacheInfo *cache_info,ExceptionInfo *exception)
933 Clone pixel cache (unoptimized).
935 if (cache_info->debug != MagickFalse)
937 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
938 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
940 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
941 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
943 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
944 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
946 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
948 length=(size_t) MagickMax(MagickMax(cache_info->pixel_components,
949 clone_info->pixel_components)*sizeof(Quantum),MagickMax(
950 cache_info->metacontent_extent,clone_info->metacontent_extent));
951 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob));
952 if (blob == (unsigned char *) NULL)
954 (void) ThrowMagickException(exception,GetMagickModule(),
955 ResourceLimitError,"MemoryAllocationFailed","`%s'",
956 cache_info->filename);
959 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
962 if (cache_info->type == DiskCache)
964 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
966 blob=(unsigned char *) RelinquishMagickMemory(blob);
967 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
968 cache_info->cache_filename);
971 cache_offset=cache_info->offset;
973 if (clone_info->type == DiskCache)
975 if ((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->pixel_components*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->pixel_components*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->pixel_components*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->pixel_components*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->pixel_components == clone_info->pixel_components) &&
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 *) RelinquishAlignedMemory(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->pixel_components) ? 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->pixel_components != cache_info->pixel_components) ||
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->pixel_components*sizeof(Quantum));
2789 if (GetPixelCacheType(image) == DiskCache)
2790 *width=8192UL/(cache_info->pixel_components*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)
3153 register const Quantum
3166 register unsigned char
3170 *virtual_associated_pixel;
3175 assert(image != (const Image *) NULL);
3176 assert(image->signature == MagickSignature);
3177 assert(image->cache != (Cache) NULL);
3178 cache_info=(CacheInfo *) image->cache;
3179 assert(cache_info->signature == MagickSignature);
3180 if (cache_info->type == UndefinedCache)
3181 return((const Quantum *) NULL);
3184 region.width=columns;
3186 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
3187 if (pixels == (Quantum *) NULL)
3188 return((const Quantum *) NULL);
3189 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3190 nexus_info->region.x;
3191 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3192 nexus_info->region.width-1L;
3193 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3194 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3195 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3196 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3202 Pixel request is inside cache extents.
3204 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3206 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3207 if (status == MagickFalse)
3208 return((const Quantum *) NULL);
3209 if (cache_info->metacontent_extent != 0)
3211 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3212 if (status == MagickFalse)
3213 return((const Quantum *) NULL);
3218 Pixel request is outside cache extents.
3221 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3222 virtual_nexus=AcquirePixelCacheNexus(1);
3223 if (virtual_nexus == (NexusInfo **) NULL)
3225 if (virtual_nexus != (NexusInfo **) NULL)
3226 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3227 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3228 "UnableToGetCacheNexus","`%s'",image->filename);
3229 return((const Quantum *) NULL);
3231 virtual_pixel=(Quantum *) NULL;
3232 virtual_associated_pixel=(void *) NULL;
3233 switch (virtual_pixel_method)
3235 case BackgroundVirtualPixelMethod:
3236 case BlackVirtualPixelMethod:
3237 case GrayVirtualPixelMethod:
3238 case TransparentVirtualPixelMethod:
3239 case MaskVirtualPixelMethod:
3240 case WhiteVirtualPixelMethod:
3241 case EdgeVirtualPixelMethod:
3242 case CheckerTileVirtualPixelMethod:
3243 case HorizontalTileVirtualPixelMethod:
3244 case VerticalTileVirtualPixelMethod:
3247 Acquire virtual pixel and associated channels.
3249 virtual_pixel=(Quantum *) AcquireQuantumMemory(
3250 cache_info->pixel_components,sizeof(*virtual_pixel));
3251 if (virtual_pixel == (Quantum *) NULL)
3253 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3254 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3255 "UnableToGetCacheNexus","`%s'",image->filename);
3256 return((const Quantum *) NULL);
3258 (void) ResetMagickMemory(virtual_pixel,0,cache_info->pixel_components*
3259 sizeof(*virtual_pixel));
3260 if (cache_info->metacontent_extent != 0)
3262 virtual_associated_pixel=(void *) AcquireMagickMemory(
3263 cache_info->metacontent_extent);
3264 if (virtual_associated_pixel == (void *) NULL)
3266 virtual_pixel=(Quantum *) RelinquishMagickMemory(
3268 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3269 (void) ThrowMagickException(exception,GetMagickModule(),
3270 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
3271 return((const Quantum *) NULL);
3273 (void) ResetMagickMemory(virtual_associated_pixel,0,
3274 cache_info->metacontent_extent);
3276 switch (virtual_pixel_method)
3278 case BlackVirtualPixelMethod:
3280 SetPixelRed(image,0,virtual_pixel);
3281 SetPixelGreen(image,0,virtual_pixel);
3282 SetPixelBlue(image,0,virtual_pixel);
3283 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3286 case GrayVirtualPixelMethod:
3288 SetPixelRed(image,QuantumRange/2,virtual_pixel);
3289 SetPixelGreen(image,QuantumRange/2,virtual_pixel);
3290 SetPixelBlue(image,QuantumRange/2,virtual_pixel);
3291 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3294 case TransparentVirtualPixelMethod:
3296 SetPixelRed(image,0,virtual_pixel);
3297 SetPixelGreen(image,0,virtual_pixel);
3298 SetPixelBlue(image,0,virtual_pixel);
3299 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3302 case MaskVirtualPixelMethod:
3303 case WhiteVirtualPixelMethod:
3305 SetPixelRed(image,(Quantum) QuantumRange,virtual_pixel);
3306 SetPixelGreen(image,(Quantum) QuantumRange,virtual_pixel);
3307 SetPixelBlue(image,(Quantum) QuantumRange,virtual_pixel);
3308 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3313 SetPixelRed(image,image->background_color.red,virtual_pixel);
3314 SetPixelGreen(image,image->background_color.green,virtual_pixel);
3315 SetPixelBlue(image,image->background_color.blue,virtual_pixel);
3316 SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
3325 for (v=0; v < (ssize_t) rows; v++)
3327 for (u=0; u < (ssize_t) columns; u+=length)
3329 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3330 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3331 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3339 Transfer a single pixel.
3341 length=(MagickSizeType) 1;
3342 switch (virtual_pixel_method)
3346 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3347 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3348 1UL,1UL,*virtual_nexus,exception);
3349 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3352 case RandomVirtualPixelMethod:
3354 if (cache_info->random_info == (RandomInfo *) NULL)
3355 cache_info->random_info=AcquireRandomInfo();
3356 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3357 RandomX(cache_info->random_info,cache_info->columns),
3358 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3359 *virtual_nexus,exception);
3360 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3363 case DitherVirtualPixelMethod:
3365 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3366 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3367 1UL,1UL,*virtual_nexus,exception);
3368 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3371 case TileVirtualPixelMethod:
3373 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3374 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3375 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3376 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3378 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3381 case MirrorVirtualPixelMethod:
3383 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3384 if ((x_modulo.quotient & 0x01) == 1L)
3385 x_modulo.remainder=(ssize_t) cache_info->columns-
3386 x_modulo.remainder-1L;
3387 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3388 if ((y_modulo.quotient & 0x01) == 1L)
3389 y_modulo.remainder=(ssize_t) cache_info->rows-
3390 y_modulo.remainder-1L;
3391 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3392 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3394 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3397 case HorizontalTileEdgeVirtualPixelMethod:
3399 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3400 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3401 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3402 *virtual_nexus,exception);
3403 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3406 case VerticalTileEdgeVirtualPixelMethod:
3408 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3409 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3410 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3411 *virtual_nexus,exception);
3412 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3415 case BackgroundVirtualPixelMethod:
3416 case BlackVirtualPixelMethod:
3417 case GrayVirtualPixelMethod:
3418 case TransparentVirtualPixelMethod:
3419 case MaskVirtualPixelMethod:
3420 case WhiteVirtualPixelMethod:
3423 r=virtual_associated_pixel;
3426 case EdgeVirtualPixelMethod:
3427 case CheckerTileVirtualPixelMethod:
3429 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3430 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3431 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3434 r=virtual_associated_pixel;
3437 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3438 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3440 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3443 case HorizontalTileVirtualPixelMethod:
3445 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3448 r=virtual_associated_pixel;
3451 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3452 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3453 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3454 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3456 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3459 case VerticalTileVirtualPixelMethod:
3461 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3464 r=virtual_associated_pixel;
3467 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3468 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3469 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3470 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3472 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3476 if (p == (const Quantum *) NULL)
3478 (void) memcpy(q,p,(size_t) length*cache_info->pixel_components*
3480 q+=cache_info->pixel_components;
3481 if ((s != (void *) NULL) &&
3482 (r != (const void *) NULL))
3484 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3485 s+=cache_info->metacontent_extent;
3490 Transfer a run of pixels.
3492 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3493 length,1UL,*virtual_nexus,exception);
3494 if (p == (const Quantum *) NULL)
3496 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3497 (void) memcpy(q,p,(size_t) length*cache_info->pixel_components*sizeof(*p));
3498 q+=length*cache_info->pixel_components;
3499 if ((s != (void *) NULL) && (r != (const void *) NULL))
3501 (void) memcpy(s,r,(size_t) length);
3502 s+=length*cache_info->metacontent_extent;
3509 if (virtual_associated_pixel != (void *) NULL)
3510 virtual_associated_pixel=(void *) RelinquishMagickMemory(
3511 virtual_associated_pixel);
3512 if (virtual_pixel != (Quantum *) NULL)
3513 virtual_pixel=(Quantum *) RelinquishMagickMemory(virtual_pixel);
3514 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3523 + G e t V i r t u a l P i x e l C a c h e %
3527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3529 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3530 % cache as defined by the geometry parameters. A pointer to the pixels
3531 % is returned if the pixels are transferred, otherwise a NULL is returned.
3533 % The format of the GetVirtualPixelCache() method is:
3535 % const Quantum *GetVirtualPixelCache(const Image *image,
3536 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3537 % const ssize_t y,const size_t columns,const size_t rows,
3538 % ExceptionInfo *exception)
3540 % A description of each parameter follows:
3542 % o image: the image.
3544 % o virtual_pixel_method: the virtual pixel method.
3546 % o x,y,columns,rows: These values define the perimeter of a region of
3549 % o exception: return any errors or warnings in this structure.
3552 static const Quantum *GetVirtualPixelCache(const Image *image,
3553 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3554 const size_t columns,const size_t rows,ExceptionInfo *exception)
3560 id = GetOpenMPThreadId();
3565 assert(image != (const Image *) NULL);
3566 assert(image->signature == MagickSignature);
3567 assert(image->cache != (Cache) NULL);
3568 cache_info=(CacheInfo *) image->cache;
3569 assert(cache_info->signature == MagickSignature);
3570 assert(id < (int) cache_info->number_threads);
3571 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3572 cache_info->nexus_info[id],exception);
3577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3581 % G e t V i r t u a l P i x e l Q u e u e %
3585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3587 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3588 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3590 % The format of the GetVirtualPixelQueue() method is:
3592 % const Quantum *GetVirtualPixelQueue(const Image image)
3594 % A description of each parameter follows:
3596 % o image: the image.
3599 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3605 id = GetOpenMPThreadId();
3607 assert(image != (const Image *) NULL);
3608 assert(image->signature == MagickSignature);
3609 assert(image->cache != (Cache) NULL);
3610 cache_info=(CacheInfo *) image->cache;
3611 assert(cache_info->signature == MagickSignature);
3612 if (cache_info->methods.get_virtual_pixels_handler !=
3613 (GetVirtualPixelsHandler) NULL)
3614 return(cache_info->methods.get_virtual_pixels_handler(image));
3615 assert(id < (int) cache_info->number_threads);
3616 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3624 % G e t V i r t u a l P i x e l s %
3628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3630 % GetVirtualPixels() returns an immutable pixel region. If the
3631 % region is successfully accessed, a pointer to it is returned, otherwise
3632 % NULL is returned. The returned pointer may point to a temporary working
3633 % copy of the pixels or it may point to the original pixels in memory.
3634 % Performance is maximized if the selected region is part of one row, or one
3635 % or more full rows, since there is opportunity to access the pixels in-place
3636 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3637 % returned pointer must *never* be deallocated by the user.
3639 % Pixels accessed via the returned pointer represent a simple array of type
3640 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3641 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3642 % access the meta-content (of type void) corresponding to the the
3645 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3647 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3648 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3649 % GetCacheViewAuthenticPixels() instead.
3651 % The format of the GetVirtualPixels() method is:
3653 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3654 % const ssize_t y,const size_t columns,const size_t rows,
3655 % ExceptionInfo *exception)
3657 % A description of each parameter follows:
3659 % o image: the image.
3661 % o x,y,columns,rows: These values define the perimeter of a region of
3664 % o exception: return any errors or warnings in this structure.
3667 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3668 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3669 ExceptionInfo *exception)
3675 id = GetOpenMPThreadId();
3680 assert(image != (const Image *) NULL);
3681 assert(image->signature == MagickSignature);
3682 assert(image->cache != (Cache) NULL);
3683 cache_info=(CacheInfo *) image->cache;
3684 assert(cache_info->signature == MagickSignature);
3685 if (cache_info->methods.get_virtual_pixel_handler !=
3686 (GetVirtualPixelHandler) NULL)
3687 return(cache_info->methods.get_virtual_pixel_handler(image,
3688 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3689 assert(id < (int) cache_info->number_threads);
3690 pixels=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3691 columns,rows,cache_info->nexus_info[id],exception);
3696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3700 + 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 %
3704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3706 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3707 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3709 % The format of the GetVirtualPixelsCache() method is:
3711 % Quantum *GetVirtualPixelsCache(const Image *image)
3713 % A description of each parameter follows:
3715 % o image: the image.
3718 static const Quantum *GetVirtualPixelsCache(const Image *image)
3724 id = GetOpenMPThreadId();
3726 assert(image != (const Image *) NULL);
3727 assert(image->signature == MagickSignature);
3728 assert(image->cache != (Cache) NULL);
3729 cache_info=(CacheInfo *) image->cache;
3730 assert(cache_info->signature == MagickSignature);
3731 assert(id < (int) cache_info->number_threads);
3732 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3740 + G e t V i r t u a l P i x e l s N e x u s %
3744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3746 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3749 % The format of the GetVirtualPixelsNexus() method is:
3751 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3752 % NexusInfo *nexus_info)
3754 % A description of each parameter follows:
3756 % o cache: the pixel cache.
3758 % o nexus_info: the cache nexus to return the colormap pixels.
3761 MagickExport const Quantum *GetVirtualPixelsNexus(const Cache cache,
3762 NexusInfo *nexus_info)
3767 assert(cache != (Cache) NULL);
3768 cache_info=(CacheInfo *) cache;
3769 assert(cache_info->signature == MagickSignature);
3770 if (cache_info->storage_class == UndefinedClass)
3771 return((Quantum *) NULL);
3772 return((const Quantum *) nexus_info->pixels);
3776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3780 + M a s k P i x e l C a c h e N e x u s %
3784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3786 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3787 % The method returns MagickTrue if the pixel region is masked, otherwise
3790 % The format of the MaskPixelCacheNexus() method is:
3792 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3793 % NexusInfo *nexus_info,ExceptionInfo *exception)
3795 % A description of each parameter follows:
3797 % o image: the image.
3799 % o nexus_info: the cache nexus to clip.
3801 % o exception: return any errors or warnings in this structure.
3805 static inline void MagickPixelCompositeMask(const PixelInfo *p,
3806 const MagickRealType alpha,const PixelInfo *q,
3807 const MagickRealType beta,PixelInfo *composite)
3812 if (alpha == TransparentAlpha)
3817 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3818 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
3819 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3820 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3821 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3822 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3823 composite->black=gamma*MagickOver_(p->black,alpha,q->black,beta);
3826 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3827 ExceptionInfo *exception)
3843 register const Quantum
3856 if (image->debug != MagickFalse)
3857 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3858 if (image->mask == (Image *) NULL)
3859 return(MagickFalse);
3860 cache_info=(CacheInfo *) image->cache;
3861 if (cache_info == (Cache) NULL)
3862 return(MagickFalse);
3863 image_nexus=AcquirePixelCacheNexus(1);
3864 clip_nexus=AcquirePixelCacheNexus(1);
3865 if ((image_nexus == (NexusInfo **) NULL) ||
3866 (clip_nexus == (NexusInfo **) NULL))
3867 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
3868 p=(const Quantum *) GetAuthenticPixelCacheNexus(image,
3869 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3870 nexus_info->region.height,image_nexus[0],exception);
3871 q=nexus_info->pixels;
3872 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
3873 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3874 nexus_info->region.height,clip_nexus[0],&image->exception);
3875 GetPixelInfo(image,&alpha);
3876 GetPixelInfo(image,&beta);
3877 number_pixels=(MagickSizeType) nexus_info->region.width*
3878 nexus_info->region.height;
3879 for (i=0; i < (ssize_t) number_pixels; i++)
3881 if ((p == (const Quantum *) NULL) || (r == (const Quantum *) NULL))
3883 SetPixelInfo(image,p,&alpha);
3884 SetPixelInfo(image,q,&beta);
3885 MagickPixelCompositeMask(&beta,(MagickRealType) GetPixelIntensity(image,r),
3886 &alpha,alpha.alpha,&beta);
3887 SetPixelRed(image,ClampToQuantum(beta.red),q);
3888 SetPixelGreen(image,ClampToQuantum(beta.green),q);
3889 SetPixelBlue(image,ClampToQuantum(beta.blue),q);
3890 if (cache_info->colorspace == CMYKColorspace)
3891 SetPixelBlack(image,ClampToQuantum(beta.black),q);
3892 SetPixelAlpha(image,ClampToQuantum(beta.alpha),q);
3897 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
3898 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3899 if (i < (ssize_t) number_pixels)
3900 return(MagickFalse);
3905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3909 + O p e n P i x e l C a c h e %
3913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3915 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3916 % dimensions, allocating space for the image pixels and optionally the
3917 % metacontent, and memory mapping the cache if it is disk based. The cache
3918 % nexus array is initialized as well.
3920 % The format of the OpenPixelCache() method is:
3922 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3923 % ExceptionInfo *exception)
3925 % A description of each parameter follows:
3927 % o image: the image.
3929 % o mode: ReadMode, WriteMode, or IOMode.
3931 % o exception: return any errors or warnings in this structure.
3935 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3937 cache_info->mapped=MagickFalse;
3938 cache_info->pixels=(Quantum *) AcquireMagickMemory((size_t)
3939 cache_info->length);
3940 if (cache_info->pixels == (Quantum *) NULL)
3942 cache_info->mapped=MagickTrue;
3943 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3944 cache_info->length);
3948 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3958 cache_info=(CacheInfo *) image->cache;
3959 if (image->debug != MagickFalse)
3962 format[MaxTextExtent],
3963 message[MaxTextExtent];
3965 (void) FormatMagickSize(length,MagickFalse,format);
3966 (void) FormatLocaleString(message,MaxTextExtent,
3967 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3968 cache_info->cache_filename,cache_info->file,format);
3969 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3971 if (length != (MagickSizeType) ((MagickOffsetType) length))
3972 return(MagickFalse);
3973 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3975 return(MagickFalse);
3976 if ((MagickSizeType) extent >= length)
3978 offset=(MagickOffsetType) length-1;
3979 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3980 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3983 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3984 ExceptionInfo *exception)
3991 format[MaxTextExtent],
3992 message[MaxTextExtent];
4005 assert(image != (const Image *) NULL);
4006 assert(image->signature == MagickSignature);
4007 assert(image->cache != (Cache) NULL);
4008 if (image->debug != MagickFalse)
4009 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4010 if ((image->columns == 0) || (image->rows == 0))
4011 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
4012 StandardPixelComponentMap(image);
4013 cache_info=(CacheInfo *) image->cache;
4014 assert(cache_info->signature == MagickSignature);
4015 source_info=(*cache_info);
4016 source_info.file=(-1);
4017 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
4018 image->filename,(double) GetImageIndexInList(image));
4019 cache_info->storage_class=image->storage_class;
4020 cache_info->colorspace=image->colorspace;
4021 cache_info->mode=mode;
4022 cache_info->rows=image->rows;
4023 cache_info->columns=image->columns;
4024 cache_info->pixel_components=GetPixelComponents(image);
4025 cache_info->metacontent_extent=image->metacontent_extent;
4026 if (image->ping != MagickFalse)
4028 cache_info->type=PingCache;
4029 cache_info->pixels=(Quantum *) NULL;
4030 cache_info->metacontent=(void *) NULL;
4031 cache_info->length=0;
4034 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4035 packet_size=cache_info->pixel_components*sizeof(Quantum);
4036 if (image->metacontent_extent != 0)
4037 packet_size+=cache_info->metacontent_extent;
4038 length=number_pixels*packet_size;
4039 columns=(size_t) (length/cache_info->rows/packet_size);
4040 if (cache_info->columns != columns)
4041 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
4043 cache_info->length=length;
4044 if ((cache_info->type != UndefinedCache) &&
4045 (cache_info->columns <= source_info.columns) &&
4046 (cache_info->rows <= source_info.rows) &&
4047 (cache_info->pixel_components <= source_info.pixel_components) &&
4048 (cache_info->metacontent_extent <= source_info.metacontent_extent))
4051 Inline pixel cache clone optimization.
4053 if ((cache_info->columns == source_info.columns) &&
4054 (cache_info->rows == source_info.rows) &&
4055 (cache_info->pixel_components == source_info.pixel_components) &&
4056 (cache_info->metacontent_extent == source_info.metacontent_extent))
4058 return(ClonePixelCachePixels(cache_info,&source_info,exception));
4060 status=AcquireMagickResource(AreaResource,cache_info->length);
4061 length=number_pixels*(cache_info->pixel_components*sizeof(Quantum)+
4062 cache_info->metacontent_extent);
4063 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
4065 status=AcquireMagickResource(MemoryResource,cache_info->length);
4066 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
4067 (cache_info->type == MemoryCache))
4069 AllocatePixelCachePixels(cache_info);
4070 if (cache_info->pixels == (Quantum *) NULL)
4071 cache_info->pixels=source_info.pixels;
4075 Create memory pixel cache.
4078 if (image->debug != MagickFalse)
4080 (void) FormatMagickSize(cache_info->length,MagickTrue,
4082 (void) FormatLocaleString(message,MaxTextExtent,
4083 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
4084 cache_info->filename,cache_info->mapped != MagickFalse ?
4085 "anonymous" : "heap",(double) cache_info->columns,(double)
4086 cache_info->rows,(double) cache_info->pixel_components,
4088 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4091 cache_info->type=MemoryCache;
4092 cache_info->metacontent=(void *) NULL;
4093 if (cache_info->metacontent_extent != 0)
4094 cache_info->metacontent=(void *) (cache_info->pixels+
4095 number_pixels*cache_info->pixel_components);
4096 if (source_info.storage_class != UndefinedClass)
4098 status=ClonePixelCachePixels(cache_info,&source_info,
4100 RelinquishPixelCachePixels(&source_info);
4105 RelinquishMagickResource(MemoryResource,cache_info->length);
4108 Create pixel cache on disk.
4110 status=AcquireMagickResource(DiskResource,cache_info->length);
4111 if (status == MagickFalse)
4113 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4114 "CacheResourcesExhausted","`%s'",image->filename);
4115 return(MagickFalse);
4117 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4119 RelinquishMagickResource(DiskResource,cache_info->length);
4120 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
4122 return(MagickFalse);
4124 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
4125 cache_info->length);
4126 if (status == MagickFalse)
4128 ThrowFileException(exception,CacheError,"UnableToExtendCache",
4130 return(MagickFalse);
4132 length=number_pixels*(cache_info->pixel_components*sizeof(Quantum)+
4133 cache_info->metacontent_extent);
4134 status=AcquireMagickResource(AreaResource,cache_info->length);
4135 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
4136 cache_info->type=DiskCache;
4139 status=AcquireMagickResource(MapResource,cache_info->length);
4140 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
4141 (cache_info->type != MemoryCache))
4142 cache_info->type=DiskCache;
4145 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4146 cache_info->offset,(size_t) cache_info->length);
4147 if (cache_info->pixels == (Quantum *) NULL)
4149 cache_info->type=DiskCache;
4150 cache_info->pixels=source_info.pixels;
4155 Create file-backed memory-mapped pixel cache.
4158 (void) ClosePixelCacheOnDisk(cache_info);
4159 cache_info->type=MapCache;
4160 cache_info->mapped=MagickTrue;
4161 cache_info->metacontent=(void *) NULL;
4162 if (cache_info->metacontent_extent != 0)
4163 cache_info->metacontent=(void *) (cache_info->pixels+
4164 number_pixels*cache_info->pixel_components);
4165 if (source_info.storage_class != UndefinedClass)
4167 status=ClonePixelCachePixels(cache_info,&source_info,
4169 RelinquishPixelCachePixels(&source_info);
4171 if (image->debug != MagickFalse)
4173 (void) FormatMagickSize(cache_info->length,MagickTrue,
4175 (void) FormatLocaleString(message,MaxTextExtent,
4176 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
4177 cache_info->filename,cache_info->cache_filename,
4178 cache_info->file,(double) cache_info->columns,(double)
4179 cache_info->rows,(double) cache_info->pixel_components,
4181 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
4187 RelinquishMagickResource(MapResource,cache_info->length);
4190 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
4192 status=ClonePixelCachePixels(cache_info,&source_info,exception);
4193 RelinquishPixelCachePixels(&source_info);
4195 if (image->debug != MagickFalse)
4197 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4198 (void) FormatLocaleString(message,MaxTextExtent,
4199 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
4200 cache_info->cache_filename,cache_info->file,(double)
4201 cache_info->columns,(double) cache_info->rows,(double)
4202 cache_info->pixel_components,format);
4203 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
4209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4213 + P e r s i s t P i x e l C a c h e %
4217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4219 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
4220 % persistent pixel cache is one that resides on disk and is not destroyed
4221 % when the program exits.
4223 % The format of the PersistPixelCache() method is:
4225 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4226 % const MagickBooleanType attach,MagickOffsetType *offset,
4227 % ExceptionInfo *exception)
4229 % A description of each parameter follows:
4231 % o image: the image.
4233 % o filename: the persistent pixel cache filename.
4235 % o attach: A value other than zero initializes the persistent pixel cache.
4237 % o initialize: A value other than zero initializes the persistent pixel
4240 % o offset: the offset in the persistent cache to store pixels.
4242 % o exception: return any errors or warnings in this structure.
4245 MagickExport MagickBooleanType PersistPixelCache(Image *image,
4246 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4247 ExceptionInfo *exception)
4262 assert(image != (Image *) NULL);
4263 assert(image->signature == MagickSignature);
4264 if (image->debug != MagickFalse)
4265 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4266 assert(image->cache != (void *) NULL);
4267 assert(filename != (const char *) NULL);
4268 assert(offset != (MagickOffsetType *) NULL);
4269 page_size=GetMagickPageSize();
4270 cache_info=(CacheInfo *) image->cache;
4271 assert(cache_info->signature == MagickSignature);
4272 if (attach != MagickFalse)
4275 Attach existing persistent pixel cache.
4277 if (image->debug != MagickFalse)
4278 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4279 "attach persistent cache");
4280 (void) CopyMagickString(cache_info->cache_filename,filename,
4282 cache_info->type=DiskCache;
4283 cache_info->offset=(*offset);
4284 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4285 return(MagickFalse);
4286 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4289 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4290 (cache_info->reference_count == 1))
4292 LockSemaphoreInfo(cache_info->semaphore);
4293 if ((cache_info->mode != ReadMode) &&
4294 (cache_info->type != MemoryCache) &&
4295 (cache_info->reference_count == 1))
4301 Usurp existing persistent pixel cache.
4303 status=rename(cache_info->cache_filename,filename);
4306 (void) CopyMagickString(cache_info->cache_filename,filename,
4308 *offset+=cache_info->length+page_size-(cache_info->length %
4310 UnlockSemaphoreInfo(cache_info->semaphore);
4311 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4312 if (image->debug != MagickFalse)
4313 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4314 "Usurp resident persistent cache");
4318 UnlockSemaphoreInfo(cache_info->semaphore);
4321 Clone persistent pixel cache.
4323 clone_image=(*image);
4324 clone_info=(CacheInfo *) clone_image.cache;
4325 image->cache=ClonePixelCache(cache_info);
4326 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4327 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4328 cache_info->type=DiskCache;
4329 cache_info->offset=(*offset);
4330 cache_info=(CacheInfo *) image->cache;
4331 status=OpenPixelCache(image,IOMode,exception);
4332 if (status != MagickFalse)
4333 status=ClonePixelCachePixels(cache_info,clone_info,&image->exception);
4334 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4335 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4344 + Q u e u e A u t h e n t i c N e x u s %
4348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4350 % QueueAuthenticNexus() allocates an region to store image pixels as defined
4351 % by the region rectangle and returns a pointer to the region. This region is
4352 % subsequently transferred from the pixel cache with
4353 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4354 % pixels are transferred, otherwise a NULL is returned.
4356 % The format of the QueueAuthenticNexus() method is:
4358 % Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4359 % const ssize_t y,const size_t columns,const size_t rows,
4360 % NexusInfo *nexus_info,ExceptionInfo *exception)
4362 % A description of each parameter follows:
4364 % o image: the image.
4366 % o x,y,columns,rows: These values define the perimeter of a region of
4369 % o nexus_info: the cache nexus to set.
4371 % o exception: return any errors or warnings in this structure.
4374 MagickExport Quantum *QueueAuthenticNexus(Image *image,const ssize_t x,
4375 const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
4376 ExceptionInfo *exception)
4391 Validate pixel cache geometry.
4393 assert(image != (const Image *) NULL);
4394 assert(image->signature == MagickSignature);
4395 assert(image->cache != (Cache) NULL);
4396 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
4397 assert(cache_info->signature == MagickSignature);
4398 if (cache_info == (Cache) NULL)
4399 return((Quantum *) NULL);
4400 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4402 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4403 "NoPixelsDefinedInCache","`%s'",image->filename);
4404 return((Quantum *) NULL);
4406 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4407 (y >= (ssize_t) cache_info->rows))
4409 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4410 "PixelsAreNotAuthentic","`%s'",image->filename);
4411 return((Quantum *) NULL);
4413 offset=(MagickOffsetType) y*cache_info->columns+x;
4415 return((Quantum *) NULL);
4416 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4417 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4418 if ((MagickSizeType) offset >= number_pixels)
4419 return((Quantum *) NULL);
4425 region.width=columns;
4427 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
4431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4435 + Q u e u e A u t h e n t i c P i x e l s C a c h e %
4439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4441 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4442 % defined by the region rectangle and returns a pointer to the region. This
4443 % region is subsequently transferred from the pixel cache with
4444 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4445 % pixels are transferred, otherwise a NULL is returned.
4447 % The format of the QueueAuthenticPixelsCache() method is:
4449 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4450 % const ssize_t y,const size_t columns,const size_t rows,
4451 % ExceptionInfo *exception)
4453 % A description of each parameter follows:
4455 % o image: the image.
4457 % o x,y,columns,rows: These values define the perimeter of a region of
4460 % o exception: return any errors or warnings in this structure.
4463 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4464 const ssize_t y,const size_t columns,const size_t rows,
4465 ExceptionInfo *exception)
4471 id = GetOpenMPThreadId();
4476 assert(image != (const Image *) NULL);
4477 assert(image->signature == MagickSignature);
4478 assert(image->cache != (Cache) NULL);
4479 cache_info=(CacheInfo *) image->cache;
4480 assert(cache_info->signature == MagickSignature);
4481 assert(id < (int) cache_info->number_threads);
4482 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4492 % Q u e u e A u t h e n t i c P i x e l s %
4496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4498 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4499 % successfully initialized a pointer to a Quantum array representing the
4500 % region is returned, otherwise NULL is returned. The returned pointer may
4501 % point to a temporary working buffer for the pixels or it may point to the
4502 % final location of the pixels in memory.
4504 % Write-only access means that any existing pixel values corresponding to
4505 % the region are ignored. This is useful if the initial image is being
4506 % created from scratch, or if the existing pixel values are to be
4507 % completely replaced without need to refer to their pre-existing values.
4508 % The application is free to read and write the pixel buffer returned by
4509 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4510 % initialize the pixel array values. Initializing pixel array values is the
4511 % application's responsibility.
4513 % Performance is maximized if the selected region is part of one row, or
4514 % one or more full rows, since then there is opportunity to access the
4515 % pixels in-place (without a copy) if the image is in memory, or in a
4516 % memory-mapped file. The returned pointer must *never* be deallocated
4519 % Pixels accessed via the returned pointer represent a simple array of type
4520 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4521 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4522 % obtain the meta-content (of type void) corresponding to the region.
4523 % Once the Quantum (and/or Quantum) array has been updated, the
4524 % changes must be saved back to the underlying image using
4525 % SyncAuthenticPixels() or they may be lost.
4527 % The format of the QueueAuthenticPixels() method is:
4529 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4530 % const ssize_t y,const size_t columns,const size_t rows,
4531 % ExceptionInfo *exception)
4533 % A description of each parameter follows:
4535 % o image: the image.
4537 % o x,y,columns,rows: These values define the perimeter of a region of
4540 % o exception: return any errors or warnings in this structure.
4543 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4544 const ssize_t y,const size_t columns,const size_t rows,
4545 ExceptionInfo *exception)
4551 id = GetOpenMPThreadId();
4556 assert(image != (Image *) NULL);
4557 assert(image->signature == MagickSignature);
4558 assert(image->cache != (Cache) NULL);
4559 cache_info=(CacheInfo *) image->cache;
4560 assert(cache_info->signature == MagickSignature);
4561 if (cache_info->methods.queue_authentic_pixels_handler !=
4562 (QueueAuthenticPixelsHandler) NULL)
4564 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4565 columns,rows,exception);
4568 assert(id < (int) cache_info->number_threads);
4569 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
4575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4579 + R e a d P i x e l C a c h e M e t a c o n t e n t %
4583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4585 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4588 % The format of the ReadPixelCacheMetacontent() method is:
4590 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4591 % NexusInfo *nexus_info,ExceptionInfo *exception)
4593 % A description of each parameter follows:
4595 % o cache_info: the pixel cache.
4597 % o nexus_info: the cache nexus to read the metacontent.
4599 % o exception: return any errors or warnings in this structure.
4602 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4603 NexusInfo *nexus_info,ExceptionInfo *exception)
4616 register unsigned char
4622 if (cache_info->metacontent_extent == 0)
4623 return(MagickFalse);
4624 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4626 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4627 nexus_info->region.x;
4628 length=(MagickSizeType) nexus_info->region.width*
4629 cache_info->metacontent_extent;
4630 rows=nexus_info->region.height;
4632 q=(unsigned char *) nexus_info->metacontent;
4633 switch (cache_info->type)
4638 register unsigned char
4642 Read meta-content from memory.
4644 if ((cache_info->columns == nexus_info->region.width) &&
4645 (extent == (MagickSizeType) ((size_t) extent)))
4650 p=(unsigned char *) cache_info->metacontent+offset*
4651 cache_info->metacontent_extent;
4652 for (y=0; y < (ssize_t) rows; y++)
4654 (void) memcpy(q,p,(size_t) length);
4655 p+=cache_info->metacontent_extent*cache_info->columns;
4656 q+=cache_info->metacontent_extent*nexus_info->region.width;
4663 Read meta content from disk.
4665 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4667 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4668 cache_info->cache_filename);
4669 return(MagickFalse);
4671 if ((cache_info->columns == nexus_info->region.width) &&
4672 (extent <= MagickMaxBufferExtent))
4677 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4678 for (y=0; y < (ssize_t) rows; y++)
4680 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4681 cache_info->pixel_components*sizeof(Quantum)+offset*
4682 cache_info->metacontent_extent,length,(unsigned char *) q);
4683 if ((MagickSizeType) count != length)
4685 offset+=cache_info->columns;
4686 q+=cache_info->metacontent_extent*nexus_info->region.width;
4688 if (y < (ssize_t) rows)
4690 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4691 cache_info->cache_filename);
4692 return(MagickFalse);
4699 if ((cache_info->debug != MagickFalse) &&
4700 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4701 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4702 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4703 nexus_info->region.width,(double) nexus_info->region.height,(double)
4704 nexus_info->region.x,(double) nexus_info->region.y);
4709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4713 + R e a d P i x e l C a c h e P i x e l s %
4717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4719 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4722 % The format of the ReadPixelCachePixels() method is:
4724 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4725 % NexusInfo *nexus_info,ExceptionInfo *exception)
4727 % A description of each parameter follows:
4729 % o cache_info: the pixel cache.
4731 % o nexus_info: the cache nexus to read the pixels.
4733 % o exception: return any errors or warnings in this structure.
4736 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4737 NexusInfo *nexus_info,ExceptionInfo *exception)
4756 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4758 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4759 nexus_info->region.x;
4760 length=(MagickSizeType) nexus_info->region.width*cache_info->pixel_components*
4762 rows=nexus_info->region.height;
4764 q=nexus_info->pixels;
4765 switch (cache_info->type)
4774 Read pixels from memory.
4776 if ((cache_info->columns == nexus_info->region.width) &&
4777 (extent == (MagickSizeType) ((size_t) extent)))
4782 p=cache_info->pixels+offset*cache_info->pixel_components;
4783 for (y=0; y < (ssize_t) rows; y++)
4785 (void) memcpy(q,p,(size_t) length);
4786 p+=cache_info->pixel_components*cache_info->columns;
4787 q+=cache_info->pixel_components*nexus_info->region.width;
4794 Read pixels from disk.
4796 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4798 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4799 cache_info->cache_filename);
4800 return(MagickFalse);
4802 if ((cache_info->columns == nexus_info->region.width) &&
4803 (extent <= MagickMaxBufferExtent))
4808 for (y=0; y < (ssize_t) rows; y++)
4810 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4811 cache_info->pixel_components*sizeof(*q),length,(unsigned char *) q);
4812 if ((MagickSizeType) count != length)
4814 offset+=cache_info->columns;
4815 q+=cache_info->pixel_components*nexus_info->region.width;
4817 if (y < (ssize_t) rows)
4819 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4820 cache_info->cache_filename);
4821 return(MagickFalse);
4828 if ((cache_info->debug != MagickFalse) &&
4829 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4830 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4831 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4832 nexus_info->region.width,(double) nexus_info->region.height,(double)
4833 nexus_info->region.x,(double) nexus_info->region.y);
4838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4842 + R e f e r e n c e P i x e l C a c h e %
4846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4848 % ReferencePixelCache() increments the reference count associated with the
4849 % pixel cache returning a pointer to the cache.
4851 % The format of the ReferencePixelCache method is:
4853 % Cache ReferencePixelCache(Cache cache_info)
4855 % A description of each parameter follows:
4857 % o cache_info: the pixel cache.
4860 MagickExport Cache ReferencePixelCache(Cache cache)
4865 assert(cache != (Cache *) NULL);
4866 cache_info=(CacheInfo *) cache;
4867 assert(cache_info->signature == MagickSignature);
4868 LockSemaphoreInfo(cache_info->semaphore);
4869 cache_info->reference_count++;
4870 UnlockSemaphoreInfo(cache_info->semaphore);
4875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4879 + S e t P i x e l C a c h e M e t h o d s %
4883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4885 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4887 % The format of the SetPixelCacheMethods() method is:
4889 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4891 % A description of each parameter follows:
4893 % o cache: the pixel cache.
4895 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4898 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4903 GetOneAuthenticPixelFromHandler
4904 get_one_authentic_pixel_from_handler;
4906 GetOneVirtualPixelFromHandler
4907 get_one_virtual_pixel_from_handler;
4910 Set cache pixel methods.
4912 assert(cache != (Cache) NULL);
4913 assert(cache_methods != (CacheMethods *) NULL);
4914 cache_info=(CacheInfo *) cache;
4915 assert(cache_info->signature == MagickSignature);
4916 if (cache_info->debug != MagickFalse)
4917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4918 cache_info->filename);
4919 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4920 cache_info->methods.get_virtual_pixel_handler=
4921 cache_methods->get_virtual_pixel_handler;
4922 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4923 cache_info->methods.destroy_pixel_handler=
4924 cache_methods->destroy_pixel_handler;
4925 if (cache_methods->get_virtual_metacontent_from_handler !=
4926 (GetVirtualMetacontentFromHandler) NULL)
4927 cache_info->methods.get_virtual_metacontent_from_handler=
4928 cache_methods->get_virtual_metacontent_from_handler;
4929 if (cache_methods->get_authentic_pixels_handler !=
4930 (GetAuthenticPixelsHandler) NULL)
4931 cache_info->methods.get_authentic_pixels_handler=
4932 cache_methods->get_authentic_pixels_handler;
4933 if (cache_methods->queue_authentic_pixels_handler !=
4934 (QueueAuthenticPixelsHandler) NULL)
4935 cache_info->methods.queue_authentic_pixels_handler=
4936 cache_methods->queue_authentic_pixels_handler;
4937 if (cache_methods->sync_authentic_pixels_handler !=
4938 (SyncAuthenticPixelsHandler) NULL)
4939 cache_info->methods.sync_authentic_pixels_handler=
4940 cache_methods->sync_authentic_pixels_handler;
4941 if (cache_methods->get_authentic_pixels_from_handler !=
4942 (GetAuthenticPixelsFromHandler) NULL)
4943 cache_info->methods.get_authentic_pixels_from_handler=
4944 cache_methods->get_authentic_pixels_from_handler;
4945 if (cache_methods->get_authentic_metacontent_from_handler !=
4946 (GetAuthenticMetacontentFromHandler) NULL)
4947 cache_info->methods.get_authentic_metacontent_from_handler=
4948 cache_methods->get_authentic_metacontent_from_handler;
4949 get_one_virtual_pixel_from_handler=
4950 cache_info->methods.get_one_virtual_pixel_from_handler;
4951 if (get_one_virtual_pixel_from_handler !=
4952 (GetOneVirtualPixelFromHandler) NULL)
4953 cache_info->methods.get_one_virtual_pixel_from_handler=
4954 cache_methods->get_one_virtual_pixel_from_handler;
4955 get_one_authentic_pixel_from_handler=
4956 cache_methods->get_one_authentic_pixel_from_handler;
4957 if (get_one_authentic_pixel_from_handler !=
4958 (GetOneAuthenticPixelFromHandler) NULL)
4959 cache_info->methods.get_one_authentic_pixel_from_handler=
4960 cache_methods->get_one_authentic_pixel_from_handler;
4964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4968 + S e t P i x e l C a c h e N e x u s P i x e l s %
4972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4974 % SetPixelCacheNexusPixels() defines the region of the cache for the
4975 % specified cache nexus.
4977 % The format of the SetPixelCacheNexusPixels() method is:
4979 % Quantum SetPixelCacheNexusPixels(const Image *image,
4980 % const RectangleInfo *region,NexusInfo *nexus_info,
4981 % ExceptionInfo *exception)
4983 % A description of each parameter follows:
4985 % o image: the image.
4987 % o region: A pointer to the RectangleInfo structure that defines the
4988 % region of this particular cache nexus.
4990 % o nexus_info: the cache nexus to set.
4992 % o exception: return any errors or warnings in this structure.
4996 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
4997 NexusInfo *nexus_info,ExceptionInfo *exception)
4999 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
5000 return(MagickFalse);
5001 nexus_info->mapped=MagickFalse;
5002 nexus_info->cache=(Quantum *) AcquireMagickMemory((size_t)
5003 nexus_info->length);
5004 if (nexus_info->cache == (Quantum *) NULL)
5006 nexus_info->mapped=MagickTrue;
5007 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
5008 nexus_info->length);
5010 if (nexus_info->cache == (Quantum *) NULL)
5012 (void) ThrowMagickException(exception,GetMagickModule(),
5013 ResourceLimitError,"MemoryAllocationFailed","`%s'",
5014 cache_info->filename);
5015 return(MagickFalse);
5020 static Quantum *SetPixelCacheNexusPixels(const Image *image,
5021 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
5033 cache_info=(CacheInfo *) image->cache;
5034 assert(cache_info->signature == MagickSignature);
5035 if (cache_info->type == UndefinedCache)
5036 return((Quantum *) NULL);
5037 nexus_info->region=(*region);
5038 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache) &&
5039 (image->clip_mask == (Image *) NULL) && (image->mask == (Image *) NULL))
5045 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5046 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5047 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
5048 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
5049 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
5050 ((nexus_info->region.width == cache_info->columns) ||
5051 ((nexus_info->region.width % cache_info->columns) == 0)))))
5057 Pixels are accessed directly from memory.
5059 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5060 nexus_info->region.x;
5061 nexus_info->pixels=cache_info->pixels+cache_info->pixel_components*
5063 nexus_info->metacontent=(void *) NULL;
5064 if (cache_info->metacontent_extent != 0)
5065 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5066 offset*cache_info->metacontent_extent;
5067 return(nexus_info->pixels);
5071 Pixels are stored in a cache region until they are synced to the cache.
5073 number_pixels=(MagickSizeType) nexus_info->region.width*
5074 nexus_info->region.height;
5075 length=number_pixels*cache_info->pixel_components*sizeof(Quantum);
5076 if (cache_info->metacontent_extent != 0)
5077 length+=number_pixels*cache_info->metacontent_extent;
5078 if (nexus_info->cache == (Quantum *) NULL)
5080 nexus_info->length=length;
5081 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5082 if (status == MagickFalse)
5084 nexus_info->length=0;
5085 return((Quantum *) NULL);
5089 if (nexus_info->length != length)
5091 RelinquishCacheNexusPixels(nexus_info);
5092 nexus_info->length=length;
5093 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5094 if (status == MagickFalse)
5096 nexus_info->length=0;
5097 return((Quantum *) NULL);
5100 nexus_info->pixels=nexus_info->cache;
5101 nexus_info->metacontent=(void *) NULL;
5102 if (cache_info->metacontent_extent != 0)
5103 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5104 cache_info->pixel_components);
5105 return(nexus_info->pixels);
5109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5113 % S e t P i x e l C a c h e V i r t u a l M e t h o d %
5117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5119 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5120 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5121 % access that is outside the boundaries of the image cache.
5123 % The format of the SetPixelCacheVirtualMethod() method is:
5125 % VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5126 % const VirtualPixelMethod virtual_pixel_method)
5128 % A description of each parameter follows:
5130 % o image: the image.
5132 % o virtual_pixel_method: choose the type of virtual pixel.
5135 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
5136 const VirtualPixelMethod virtual_pixel_method)
5144 assert(image != (Image *) NULL);
5145 assert(image->signature == MagickSignature);
5146 if (image->debug != MagickFalse)
5147 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5148 assert(image->cache != (Cache) NULL);
5149 cache_info=(CacheInfo *) image->cache;
5150 assert(cache_info->signature == MagickSignature);
5151 method=cache_info->virtual_pixel_method;
5152 cache_info->virtual_pixel_method=virtual_pixel_method;
5157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5161 + S y n c A u t h e n t i c P i x e l C a c h e N e x u s %
5165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5167 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5168 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5169 % is synced, otherwise MagickFalse.
5171 % The format of the SyncAuthenticPixelCacheNexus() method is:
5173 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5174 % NexusInfo *nexus_info,ExceptionInfo *exception)
5176 % A description of each parameter follows:
5178 % o image: the image.
5180 % o nexus_info: the cache nexus to sync.
5182 % o exception: return any errors or warnings in this structure.
5185 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5186 NexusInfo *nexus_info,ExceptionInfo *exception)
5195 Transfer pixels to the cache.
5197 assert(image != (Image *) NULL);
5198 assert(image->signature == MagickSignature);
5199 if (image->cache == (Cache) NULL)
5200 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5201 cache_info=(CacheInfo *) image->cache;
5202 assert(cache_info->signature == MagickSignature);
5203 if (cache_info->type == UndefinedCache)
5204 return(MagickFalse);
5205 if ((image->clip_mask != (Image *) NULL) &&
5206 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5207 return(MagickFalse);
5208 if ((image->mask != (Image *) NULL) &&
5209 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5210 return(MagickFalse);
5211 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5213 assert(cache_info->signature == MagickSignature);
5214 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5215 if ((cache_info->metacontent_extent != 0) &&
5216 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5217 return(MagickFalse);
5222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5226 + S y n c A u t h e n t i c P i x e l C a c h e %
5230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5232 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5233 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5234 % otherwise MagickFalse.
5236 % The format of the SyncAuthenticPixelsCache() method is:
5238 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5239 % ExceptionInfo *exception)
5241 % A description of each parameter follows:
5243 % o image: the image.
5245 % o exception: return any errors or warnings in this structure.
5248 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5249 ExceptionInfo *exception)
5255 id = GetOpenMPThreadId();
5260 assert(image != (Image *) NULL);
5261 assert(image->signature == MagickSignature);
5262 assert(image->cache != (Cache) NULL);
5263 cache_info=(CacheInfo *) image->cache;
5264 assert(cache_info->signature == MagickSignature);
5265 assert(id < (int) cache_info->number_threads);
5266 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5276 % S y n c A u t h e n t i c P i x e l s %
5280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5282 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5283 % The method returns MagickTrue if the pixel region is flushed, otherwise
5286 % The format of the SyncAuthenticPixels() method is:
5288 % MagickBooleanType SyncAuthenticPixels(Image *image,
5289 % ExceptionInfo *exception)
5291 % A description of each parameter follows:
5293 % o image: the image.
5295 % o exception: return any errors or warnings in this structure.
5298 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5299 ExceptionInfo *exception)
5305 id = GetOpenMPThreadId();
5310 assert(image != (Image *) NULL);
5311 assert(image->signature == MagickSignature);
5312 assert(image->cache != (Cache) NULL);
5313 cache_info=(CacheInfo *) image->cache;
5314 assert(cache_info->signature == MagickSignature);
5315 if (cache_info->methods.sync_authentic_pixels_handler !=
5316 (SyncAuthenticPixelsHandler) NULL)
5318 status=cache_info->methods.sync_authentic_pixels_handler(image,
5322 assert(id < (int) cache_info->number_threads);
5323 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333 + W r i t e P i x e l C a c h e M e t a c o n t e n t %
5337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5339 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5340 % of the pixel cache.
5342 % The format of the WritePixelCacheMetacontent() method is:
5344 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5345 % NexusInfo *nexus_info,ExceptionInfo *exception)
5347 % A description of each parameter follows:
5349 % o cache_info: the pixel cache.
5351 % o nexus_info: the cache nexus to write the meta-content.
5353 % o exception: return any errors or warnings in this structure.
5356 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5357 NexusInfo *nexus_info,ExceptionInfo *exception)
5367 register const unsigned char
5376 if (cache_info->metacontent_extent == 0)
5377 return(MagickFalse);
5378 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5380 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5381 nexus_info->region.x;
5382 length=(MagickSizeType) nexus_info->region.width*
5383 cache_info->metacontent_extent;
5384 rows=nexus_info->region.height;
5385 extent=(MagickSizeType) length*rows;
5386 p=(unsigned char *) nexus_info->metacontent;
5387 switch (cache_info->type)
5392 register unsigned char
5396 Write associated pixels to memory.
5398 if ((cache_info->columns == nexus_info->region.width) &&
5399 (extent == (MagickSizeType) ((size_t) extent)))
5404 q=(unsigned char *) cache_info->metacontent+offset*
5405 cache_info->metacontent_extent;
5406 for (y=0; y < (ssize_t) rows; y++)
5408 (void) memcpy(q,p,(size_t) length);
5409 p+=nexus_info->region.width*cache_info->metacontent_extent;
5410 q+=cache_info->columns*cache_info->metacontent_extent;
5417 Write associated pixels to disk.
5419 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5421 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5422 cache_info->cache_filename);
5423 return(MagickFalse);
5425 if ((cache_info->columns == nexus_info->region.width) &&
5426 (extent <= MagickMaxBufferExtent))
5431 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5432 for (y=0; y < (ssize_t) rows; y++)
5434 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5435 cache_info->pixel_components*sizeof(Quantum)+offset*
5436 cache_info->metacontent_extent,length,(const unsigned char *) p);
5437 if ((MagickSizeType) count != length)
5439 p+=nexus_info->region.width*cache_info->metacontent_extent;
5440 offset+=cache_info->columns;
5442 if (y < (ssize_t) rows)
5444 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5445 cache_info->cache_filename);
5446 return(MagickFalse);
5453 if ((cache_info->debug != MagickFalse) &&
5454 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5455 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5456 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5457 nexus_info->region.width,(double) nexus_info->region.height,(double)
5458 nexus_info->region.x,(double) nexus_info->region.y);
5463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5467 + W r i t e C a c h e P i x e l s %
5471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5473 % WritePixelCachePixels() writes image pixels to the specified region of the
5476 % The format of the WritePixelCachePixels() method is:
5478 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5479 % NexusInfo *nexus_info,ExceptionInfo *exception)
5481 % A description of each parameter follows:
5483 % o cache_info: the pixel cache.
5485 % o nexus_info: the cache nexus to write the pixels.
5487 % o exception: return any errors or warnings in this structure.
5490 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5491 NexusInfo *nexus_info,ExceptionInfo *exception)
5501 register const Quantum
5510 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5512 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5513 nexus_info->region.x;
5514 length=(MagickSizeType) nexus_info->region.width*cache_info->pixel_components*
5516 rows=nexus_info->region.height;
5518 p=nexus_info->pixels;
5519 switch (cache_info->type)
5528 Write pixels to memory.
5530 if ((cache_info->columns == nexus_info->region.width) &&
5531 (extent == (MagickSizeType) ((size_t) extent)))
5536 q=cache_info->pixels+offset*cache_info->pixel_components;
5537 for (y=0; y < (ssize_t) rows; y++)
5539 (void) memcpy(q,p,(size_t) length);
5540 p+=nexus_info->region.width*cache_info->pixel_components;
5541 q+=cache_info->columns*cache_info->pixel_components;
5548 Write pixels to disk.
5550 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5552 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5553 cache_info->cache_filename);
5554 return(MagickFalse);
5556 if ((cache_info->columns == nexus_info->region.width) &&
5557 (extent <= MagickMaxBufferExtent))
5562 for (y=0; y < (ssize_t) rows; y++)
5564 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5565 cache_info->pixel_components*sizeof(*p),length,(const unsigned char *)
5567 if ((MagickSizeType) count != length)
5569 p+=nexus_info->region.width*cache_info->pixel_components;
5570 offset+=cache_info->columns;
5572 if (y < (ssize_t) rows)
5574 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5575 cache_info->cache_filename);
5576 return(MagickFalse);
5583 if ((cache_info->debug != MagickFalse) &&
5584 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5585 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5586 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5587 nexus_info->region.width,(double) nexus_info->region.height,(double)
5588 nexus_info->region.x,(double) nexus_info->region.y);