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-2012 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/colorspace-private.h"
50 #include "MagickCore/composite-private.h"
51 #include "MagickCore/exception.h"
52 #include "MagickCore/exception-private.h"
53 #include "MagickCore/geometry.h"
54 #include "MagickCore/list.h"
55 #include "MagickCore/log.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/memory-private.h"
59 #include "MagickCore/nt-base-private.h"
60 #include "MagickCore/pixel.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/policy.h"
63 #include "MagickCore/quantum.h"
64 #include "MagickCore/random_.h"
65 #include "MagickCore/resource_.h"
66 #include "MagickCore/semaphore.h"
67 #include "MagickCore/splay-tree.h"
68 #include "MagickCore/string_.h"
69 #include "MagickCore/string-private.h"
70 #include "MagickCore/thread-private.h"
71 #include "MagickCore/utility.h"
72 #include "MagickCore/utility-private.h"
73 #if defined(MAGICKCORE_ZLIB_DELEGATE)
80 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
81 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
82 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
87 typedef struct _MagickModulo
117 Forward declarations.
119 #if defined(__cplusplus) || defined(c_plusplus)
124 GetImagePixelCache(Image *,const MagickBooleanType,ExceptionInfo *)
128 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
129 const ssize_t,const size_t,const size_t,ExceptionInfo *),
130 *GetVirtualPixelsCache(const Image *);
133 *GetVirtualMetacontentFromCache(const Image *);
135 static MagickBooleanType
136 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,Quantum *,
138 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
139 const ssize_t,const ssize_t,Quantum *,ExceptionInfo *),
140 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
141 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
142 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
143 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
144 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *),
145 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
148 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
149 const size_t,ExceptionInfo *),
150 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
151 const size_t,ExceptionInfo *),
152 *SetPixelCacheNexusPixels(const Image *,const MapMode,const RectangleInfo *,
153 NexusInfo *,ExceptionInfo *) magick_hot_spot;
155 #if defined(__cplusplus) || defined(c_plusplus)
162 static volatile MagickBooleanType
163 instantiate_cache = MagickFalse;
166 *cache_semaphore = (SemaphoreInfo *) NULL;
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 + A c q u i r e P i x e l C a c h e %
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 % AcquirePixelCache() acquires a pixel cache.
181 % The format of the AcquirePixelCache() method is:
183 % Cache AcquirePixelCache(const size_t number_threads)
185 % A description of each parameter follows:
187 % o number_threads: the number of nexus threads.
190 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
195 cache_info=(CacheInfo *) AcquireQuantumMemory(1,sizeof(*cache_info));
196 if (cache_info == (CacheInfo *) NULL)
197 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
198 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
199 cache_info->type=UndefinedCache;
200 cache_info->mode=IOMode;
201 cache_info->colorspace=sRGBColorspace;
202 cache_info->file=(-1);
203 cache_info->id=GetMagickThreadId();
204 cache_info->number_threads=number_threads;
205 if (cache_info->number_threads == 0)
206 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
207 if (cache_info->number_threads == 0)
208 cache_info->number_threads=1;
209 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
210 if (cache_info->nexus_info == (NexusInfo **) NULL)
211 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
212 cache_info->semaphore=AllocateSemaphoreInfo();
213 cache_info->reference_count=1;
214 cache_info->disk_semaphore=AllocateSemaphoreInfo();
215 cache_info->debug=IsEventLogging();
216 cache_info->signature=MagickSignature;
217 return((Cache ) cache_info);
221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225 % A c q u i r e P i x e l C a c h e N e x u s %
229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
233 % The format of the AcquirePixelCacheNexus method is:
235 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
237 % A description of each parameter follows:
239 % o number_threads: the number of nexus threads.
242 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
250 nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(
251 number_threads,sizeof(*nexus_info)));
252 if (nexus_info == (NexusInfo **) NULL)
253 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
254 nexus_info[0]=(NexusInfo *) AcquireQuantumMemory(number_threads,
255 sizeof(**nexus_info));
256 if (nexus_info[0] == (NexusInfo *) NULL)
257 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
258 (void) ResetMagickMemory(nexus_info[0],0,number_threads*sizeof(**nexus_info));
259 for (i=0; i < (ssize_t) number_threads; i++)
261 nexus_info[i]=(&nexus_info[0][i]);
262 nexus_info[i]->signature=MagickSignature;
268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272 + A c q u i r e P i x e l C a c h e P i x e l s %
276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 % AcquirePixelCachePixels() returns the pixels associated with the specified
281 % The format of the AcquirePixelCachePixels() method is:
283 % const void *AcquirePixelCachePixels(const Image *image,
284 % MagickSizeType *length,ExceptionInfo *exception)
286 % A description of each parameter follows:
288 % o image: the image.
290 % o length: the pixel cache length.
292 % o exception: return any errors or warnings in this structure.
295 MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
296 MagickSizeType *length,ExceptionInfo *exception)
301 assert(image != (const Image *) NULL);
302 assert(image->signature == MagickSignature);
303 assert(exception != (ExceptionInfo *) NULL);
304 assert(exception->signature == MagickSignature);
305 assert(image->cache != (Cache) NULL);
306 cache_info=(CacheInfo *) image->cache;
307 assert(cache_info->signature == MagickSignature);
309 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
310 return((const void *) NULL);
311 *length=cache_info->length;
312 return((const void *) cache_info->pixels);
316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320 + C a c h e C o m p o n e n t G e n e s i s %
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 % CacheComponentGenesis() instantiates the cache component.
328 % The format of the CacheComponentGenesis method is:
330 % MagickBooleanType CacheComponentGenesis(void)
333 MagickPrivate MagickBooleanType CacheComponentGenesis(void)
335 AcquireSemaphoreInfo(&cache_semaphore);
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
344 + C a c h e C o m p o n e n t T e r m i n u s %
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 % CacheComponentTerminus() destroys the cache component.
352 % The format of the CacheComponentTerminus() method is:
354 % CacheComponentTerminus(void)
357 MagickPrivate void CacheComponentTerminus(void)
359 if (cache_semaphore == (SemaphoreInfo *) NULL)
360 AcquireSemaphoreInfo(&cache_semaphore);
361 LockSemaphoreInfo(cache_semaphore);
362 instantiate_cache=MagickFalse;
363 UnlockSemaphoreInfo(cache_semaphore);
364 DestroySemaphoreInfo(&cache_semaphore);
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 + C l o n e P i x e l C a c h e %
376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 % ClonePixelCache() clones a pixel cache.
380 % The format of the ClonePixelCache() method is:
382 % Cache ClonePixelCache(const Cache cache)
384 % A description of each parameter follows:
386 % o cache: the pixel cache.
389 MagickPrivate Cache ClonePixelCache(const Cache cache)
397 assert(cache != NULL);
398 cache_info=(const CacheInfo *) cache;
399 assert(cache_info->signature == MagickSignature);
400 if (cache_info->debug != MagickFalse)
401 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
402 cache_info->filename);
403 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
404 if (clone_info == (Cache) NULL)
405 return((Cache) NULL);
406 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
407 return((Cache ) clone_info);
411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 + C l o n e P i x e l C a c h e P i x e l s %
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %
420 % ClonePixelCachePixels() clones the source pixel cache to the destination
423 % The format of the ClonePixelCachePixels() method is:
425 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info,
426 % CacheInfo *source_info,ExceptionInfo *exception)
428 % A description of each parameter follows:
430 % o cache_info: the pixel cache.
432 % o source_info: the source pixel cache.
434 % o exception: return any errors or warnings in this structure.
438 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
444 LockSemaphoreInfo(cache_info->disk_semaphore);
445 if (cache_info->file != -1)
447 status=close(cache_info->file);
448 cache_info->file=(-1);
449 RelinquishMagickResource(FileResource,1);
451 UnlockSemaphoreInfo(cache_info->disk_semaphore);
452 return(status == -1 ? MagickFalse : MagickTrue);
455 static inline MagickSizeType MagickMax(const MagickSizeType x,
456 const MagickSizeType y)
463 static inline MagickSizeType MagickMin(const MagickSizeType x,
464 const MagickSizeType y)
471 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
478 Open pixel cache on disk.
480 LockSemaphoreInfo(cache_info->disk_semaphore);
481 if (cache_info->file != -1)
483 UnlockSemaphoreInfo(cache_info->disk_semaphore);
484 return(MagickTrue); /* cache already open */
486 if (*cache_info->cache_filename == '\0')
487 file=AcquireUniqueFileResource(cache_info->cache_filename);
493 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
498 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
499 O_BINARY | O_EXCL,S_MODE);
501 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
507 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
510 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
516 UnlockSemaphoreInfo(cache_info->disk_semaphore);
519 (void) AcquireMagickResource(FileResource,1);
520 cache_info->file=file;
521 cache_info->mode=mode;
522 UnlockSemaphoreInfo(cache_info->disk_semaphore);
526 static inline MagickOffsetType ReadPixelCacheRegion(
527 const CacheInfo *restrict cache_info,const MagickOffsetType offset,
528 const MagickSizeType length,unsigned char *restrict buffer)
530 register MagickOffsetType
536 #if !defined(MAGICKCORE_HAVE_PREAD)
537 LockSemaphoreInfo(cache_info->disk_semaphore);
538 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
540 UnlockSemaphoreInfo(cache_info->disk_semaphore);
541 return((MagickOffsetType) -1);
545 for (i=0; i < (MagickOffsetType) length; i+=count)
547 #if !defined(MAGICKCORE_HAVE_PREAD)
548 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
549 (MagickSizeType) SSIZE_MAX));
551 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
552 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
563 #if !defined(MAGICKCORE_HAVE_PREAD)
564 UnlockSemaphoreInfo(cache_info->disk_semaphore);
569 static inline MagickOffsetType WritePixelCacheRegion(
570 const CacheInfo *restrict cache_info,const MagickOffsetType offset,
571 const MagickSizeType length,const unsigned char *restrict buffer)
573 register MagickOffsetType
579 #if !defined(MAGICKCORE_HAVE_PWRITE)
580 LockSemaphoreInfo(cache_info->disk_semaphore);
581 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
583 UnlockSemaphoreInfo(cache_info->disk_semaphore);
584 return((MagickOffsetType) -1);
588 for (i=0; i < (MagickOffsetType) length; i+=count)
590 #if !defined(MAGICKCORE_HAVE_PWRITE)
591 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
592 (MagickSizeType) SSIZE_MAX));
594 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
595 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
606 #if !defined(MAGICKCORE_HAVE_PWRITE)
607 UnlockSemaphoreInfo(cache_info->disk_semaphore);
612 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
613 CacheInfo *cache_info,ExceptionInfo *exception)
618 register MagickOffsetType
628 Clone pixel cache (both caches on disk).
630 if (cache_info->debug != MagickFalse)
631 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
632 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
634 if (blob == (unsigned char *) NULL)
636 (void) ThrowMagickException(exception,GetMagickModule(),
637 ResourceLimitError,"MemoryAllocationFailed","'%s'",
638 cache_info->filename);
641 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
643 blob=(unsigned char *) RelinquishMagickMemory(blob);
644 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
645 cache_info->cache_filename);
648 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
650 (void) ClosePixelCacheOnDisk(cache_info);
651 blob=(unsigned char *) RelinquishMagickMemory(blob);
652 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
653 clone_info->cache_filename);
657 for (i=0; i < (MagickOffsetType) cache_info->length; i+=count)
659 count=ReadPixelCacheRegion(cache_info,cache_info->offset+i,
660 MagickMin(cache_info->length-i,(MagickSizeType) MagickMaxBufferExtent),
664 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
665 cache_info->cache_filename);
668 length=(size_t) count;
669 count=WritePixelCacheRegion(clone_info,clone_info->offset+i,length,blob);
670 if ((MagickSizeType) count != length)
672 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
673 clone_info->cache_filename);
677 (void) ClosePixelCacheOnDisk(clone_info);
678 (void) ClosePixelCacheOnDisk(cache_info);
679 blob=(unsigned char *) RelinquishMagickMemory(blob);
680 if (i < (MagickOffsetType) cache_info->length)
685 static MagickBooleanType PixelCacheCloneOptimized(CacheInfo *clone_info,
686 CacheInfo *cache_info,ExceptionInfo *exception)
691 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
694 Clone pixel cache (both caches in memory).
696 if (cache_info->debug != MagickFalse)
697 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
698 (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t)
702 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
705 Clone pixel cache (one cache on disk, one in memory).
707 if (cache_info->debug != MagickFalse)
708 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
709 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
711 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
712 cache_info->cache_filename);
715 count=ReadPixelCacheRegion(cache_info,cache_info->offset,
716 cache_info->length,(unsigned char *) clone_info->pixels);
717 (void) ClosePixelCacheOnDisk(cache_info);
718 if ((MagickSizeType) count != cache_info->length)
720 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
721 cache_info->cache_filename);
726 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
729 Clone pixel cache (one cache on disk, one in memory).
731 if (clone_info->debug != MagickFalse)
732 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
733 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
735 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
736 clone_info->cache_filename);
739 count=WritePixelCacheRegion(clone_info,clone_info->offset,
740 clone_info->length,(unsigned char *) cache_info->pixels);
741 (void) ClosePixelCacheOnDisk(clone_info);
742 if ((MagickSizeType) count != clone_info->length)
744 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
745 clone_info->cache_filename);
751 Clone pixel cache (both caches on disk).
753 return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception));
756 static MagickBooleanType PixelCacheCloneUnoptimized(CacheInfo *clone_info,
757 CacheInfo *cache_info,ExceptionInfo *exception)
770 register unsigned char
783 Clone pixel cache (unoptimized).
785 if (cache_info->debug != MagickFalse)
787 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache))
788 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
790 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache))
791 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
793 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache))
794 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
796 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
798 length=(size_t) MagickMax(MagickMax(cache_info->number_channels,
799 clone_info->number_channels)*sizeof(Quantum),MagickMax(
800 cache_info->metacontent_extent,clone_info->metacontent_extent));
801 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob));
802 if (blob == (unsigned char *) NULL)
804 (void) ThrowMagickException(exception,GetMagickModule(),
805 ResourceLimitError,"MemoryAllocationFailed","'%s'",
806 cache_info->filename);
809 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
812 if (cache_info->type == DiskCache)
814 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse)
816 blob=(unsigned char *) RelinquishMagickMemory(blob);
817 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
818 cache_info->cache_filename);
821 cache_offset=cache_info->offset;
823 if (clone_info->type == DiskCache)
825 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse)
827 blob=(unsigned char *) RelinquishMagickMemory(blob);
828 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
829 clone_info->cache_filename);
832 clone_offset=clone_info->offset;
835 Clone pixel channels.
839 for (y=0; y < (ssize_t) cache_info->rows; y++)
841 for (x=0; x < (ssize_t) cache_info->columns; x++)
847 Read a set of pixel channels.
849 length=cache_info->number_channels*sizeof(Quantum);
850 if (cache_info->type != DiskCache)
851 p=(unsigned char *) cache_info->pixels+cache_offset;
854 count=ReadPixelCacheRegion(cache_info,cache_offset,length,p);
855 if ((MagickSizeType) count != length)
861 cache_offset+=length;
862 if ((y < (ssize_t) clone_info->rows) &&
863 (x < (ssize_t) clone_info->columns))
864 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
876 Write a set of pixel channels.
878 channel=clone_info->channel_map[i].channel;
879 traits=cache_info->channel_map[channel].traits;
880 if (traits == UndefinedPixelTrait)
882 clone_offset+=sizeof(Quantum);
885 offset=cache_info->channel_map[channel].offset;
886 if (clone_info->type != DiskCache)
887 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,p+
888 offset*sizeof(Quantum),sizeof(Quantum));
891 count=WritePixelCacheRegion(clone_info,clone_offset,
892 sizeof(Quantum),p+offset*sizeof(Quantum));
893 if ((MagickSizeType) count != sizeof(Quantum))
899 clone_offset+=sizeof(Quantum);
902 if (y < (ssize_t) clone_info->rows)
905 Set remaining columns as undefined.
907 length=clone_info->number_channels*sizeof(Quantum);
908 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
909 for ( ; x < (ssize_t) clone_info->columns; x++)
911 if (clone_info->type != DiskCache)
912 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
916 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
917 if ((MagickSizeType) count != length)
923 clone_offset+=length;
927 length=clone_info->number_channels*sizeof(Quantum);
928 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
929 for ( ; y < (ssize_t) clone_info->rows; y++)
932 Set remaining rows as undefined.
934 for (x=0; x < (ssize_t) clone_info->columns; x++)
936 if (clone_info->type != DiskCache)
937 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob,
941 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
942 if ((MagickSizeType) count != length)
948 clone_offset+=length;
951 if ((cache_info->metacontent_extent != 0) ||
952 (clone_info->metacontent_extent != 0))
957 for (y=0; y < (ssize_t) cache_info->rows; y++)
959 for (x=0; x < (ssize_t) cache_info->columns; x++)
962 Read a set of metacontent.
964 length=cache_info->metacontent_extent;
965 if (cache_info->type != DiskCache)
966 p=(unsigned char *) cache_info->pixels+cache_offset;
969 count=ReadPixelCacheRegion(cache_info,cache_offset,length,p);
970 if ((MagickSizeType) count != length)
976 cache_offset+=length;
977 if ((y < (ssize_t) clone_info->rows) &&
978 (x < (ssize_t) clone_info->columns))
981 Write a set of metacontent.
983 length=clone_info->metacontent_extent;
984 if (clone_info->type != DiskCache)
985 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
989 count=WritePixelCacheRegion(clone_info,clone_offset,length,p);
990 if ((MagickSizeType) count != length)
996 clone_offset+=length;
999 length=clone_info->metacontent_extent;
1000 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1001 for ( ; x < (ssize_t) clone_info->columns; x++)
1004 Set remaining columns as undefined.
1006 if (clone_info->type != DiskCache)
1007 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1011 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
1012 if ((MagickSizeType) count != length)
1018 clone_offset+=length;
1021 if (y < (ssize_t) clone_info->rows)
1024 Set remaining rows as undefined.
1026 length=clone_info->metacontent_extent;
1027 (void) ResetMagickMemory(blob,0,length*sizeof(*blob));
1028 for ( ; y < (ssize_t) clone_info->rows; y++)
1030 for (x=0; x < (ssize_t) clone_info->columns; x++)
1032 if (clone_info->type != DiskCache)
1033 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,
1037 count=WritePixelCacheRegion(clone_info,clone_offset,length,
1039 if ((MagickSizeType) count != length)
1045 clone_offset+=length;
1050 if (clone_info->type == DiskCache)
1051 (void) ClosePixelCacheOnDisk(clone_info);
1052 if (cache_info->type == DiskCache)
1053 (void) ClosePixelCacheOnDisk(cache_info);
1054 blob=(unsigned char *) RelinquishMagickMemory(blob);
1058 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
1059 CacheInfo *cache_info,ExceptionInfo *exception)
1065 if (cache_info->type == PingCache)
1067 p=cache_info->channel_map;
1068 q=clone_info->channel_map;
1069 if ((cache_info->columns == clone_info->columns) &&
1070 (cache_info->rows == clone_info->rows) &&
1071 (cache_info->number_channels == clone_info->number_channels) &&
1072 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) &&
1073 (cache_info->metacontent_extent == clone_info->metacontent_extent))
1074 return(PixelCacheCloneOptimized(clone_info,cache_info,exception));
1075 return(PixelCacheCloneUnoptimized(clone_info,cache_info,exception));
1079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083 + C l o n e P i x e l C a c h e M e t h o d s %
1087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1089 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
1092 % The format of the ClonePixelCacheMethods() method is:
1094 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
1096 % A description of each parameter follows:
1098 % o clone: Specifies a pointer to a Cache structure.
1100 % o cache: the pixel cache.
1103 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
1109 assert(clone != (Cache) NULL);
1110 source_info=(CacheInfo *) clone;
1111 assert(source_info->signature == MagickSignature);
1112 if (source_info->debug != MagickFalse)
1113 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1114 source_info->filename);
1115 assert(cache != (Cache) NULL);
1116 cache_info=(CacheInfo *) cache;
1117 assert(cache_info->signature == MagickSignature);
1118 source_info->methods=cache_info->methods;
1122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1126 + D e s t r o y I m a g e P i x e l C a c h e %
1130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
1134 % The format of the DestroyImagePixelCache() method is:
1136 % void DestroyImagePixelCache(Image *image)
1138 % A description of each parameter follows:
1140 % o image: the image.
1143 static void DestroyImagePixelCache(Image *image)
1145 assert(image != (Image *) NULL);
1146 assert(image->signature == MagickSignature);
1147 if (image->debug != MagickFalse)
1148 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1149 if (image->cache == (void *) NULL)
1151 image->cache=DestroyPixelCache(image->cache);
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1159 + D e s t r o y I m a g e P i x e l s %
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 % DestroyImagePixels() deallocates memory associated with the pixel cache.
1167 % The format of the DestroyImagePixels() method is:
1169 % void DestroyImagePixels(Image *image)
1171 % A description of each parameter follows:
1173 % o image: the image.
1176 MagickExport void DestroyImagePixels(Image *image)
1181 assert(image != (const Image *) NULL);
1182 assert(image->signature == MagickSignature);
1183 if (image->debug != MagickFalse)
1184 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1185 assert(image->cache != (Cache) NULL);
1186 cache_info=(CacheInfo *) image->cache;
1187 assert(cache_info->signature == MagickSignature);
1188 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1190 cache_info->methods.destroy_pixel_handler(image);
1193 image->cache=DestroyPixelCache(image->cache);
1197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201 + D e s t r o y P i x e l C a c h e %
1205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 % DestroyPixelCache() deallocates memory associated with the pixel cache.
1209 % The format of the DestroyPixelCache() method is:
1211 % Cache DestroyPixelCache(Cache cache)
1213 % A description of each parameter follows:
1215 % o cache: the pixel cache.
1219 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1221 switch (cache_info->type)
1225 if (cache_info->mapped == MagickFalse)
1226 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1227 cache_info->pixels);
1229 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
1230 (size_t) cache_info->length);
1231 RelinquishMagickResource(MemoryResource,cache_info->length);
1236 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
1237 cache_info->length);
1238 RelinquishMagickResource(MapResource,cache_info->length);
1242 if (cache_info->file != -1)
1243 (void) ClosePixelCacheOnDisk(cache_info);
1244 RelinquishMagickResource(DiskResource,cache_info->length);
1250 cache_info->type=UndefinedCache;
1251 cache_info->mapped=MagickFalse;
1252 cache_info->metacontent=(void *) NULL;
1255 MagickPrivate Cache DestroyPixelCache(Cache cache)
1260 assert(cache != (Cache) NULL);
1261 cache_info=(CacheInfo *) cache;
1262 assert(cache_info->signature == MagickSignature);
1263 if (cache_info->debug != MagickFalse)
1264 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1265 cache_info->filename);
1266 LockSemaphoreInfo(cache_info->semaphore);
1267 cache_info->reference_count--;
1268 if (cache_info->reference_count != 0)
1270 UnlockSemaphoreInfo(cache_info->semaphore);
1271 return((Cache) NULL);
1273 UnlockSemaphoreInfo(cache_info->semaphore);
1274 if (cache_info->debug != MagickFalse)
1277 message[MaxTextExtent];
1279 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s",
1280 cache_info->filename);
1281 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1283 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
1284 (cache_info->type != DiskCache)))
1285 RelinquishPixelCachePixels(cache_info);
1288 RelinquishPixelCachePixels(cache_info);
1289 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1291 *cache_info->cache_filename='\0';
1292 if (cache_info->nexus_info != (NexusInfo **) NULL)
1293 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1294 cache_info->number_threads);
1295 if (cache_info->random_info != (RandomInfo *) NULL)
1296 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1297 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
1298 DestroySemaphoreInfo(&cache_info->disk_semaphore);
1299 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1300 DestroySemaphoreInfo(&cache_info->semaphore);
1301 cache_info->signature=(~MagickSignature);
1302 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
1308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1312 + D e s t r o y P i x e l C a c h e N e x u s %
1316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1320 % The format of the DestroyPixelCacheNexus() method is:
1322 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1323 % const size_t number_threads)
1325 % A description of each parameter follows:
1327 % o nexus_info: the nexus to destroy.
1329 % o number_threads: the number of nexus threads.
1333 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1335 if (nexus_info->mapped == MagickFalse)
1336 (void) RelinquishAlignedMemory(nexus_info->cache);
1338 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1339 nexus_info->cache=(Quantum *) NULL;
1340 nexus_info->pixels=(Quantum *) NULL;
1341 nexus_info->metacontent=(void *) NULL;
1342 nexus_info->length=0;
1343 nexus_info->mapped=MagickFalse;
1346 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1347 const size_t number_threads)
1352 assert(nexus_info != (NexusInfo **) NULL);
1353 for (i=0; i < (ssize_t) number_threads; i++)
1355 if (nexus_info[i]->cache != (Quantum *) NULL)
1356 RelinquishCacheNexusPixels(nexus_info[i]);
1357 nexus_info[i]->signature=(~MagickSignature);
1359 nexus_info[0]=(NexusInfo *) RelinquishMagickMemory(nexus_info[0]);
1360 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1369 % G e t A u t h e n t i c M e t a c o n t e n t %
1373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1375 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1376 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1377 % returned if the associated pixels are not available.
1379 % The format of the GetAuthenticMetacontent() method is:
1381 % void *GetAuthenticMetacontent(const Image *image)
1383 % A description of each parameter follows:
1385 % o image: the image.
1388 MagickExport void *GetAuthenticMetacontent(const Image *image)
1394 id = GetOpenMPThreadId();
1399 assert(image != (const Image *) NULL);
1400 assert(image->signature == MagickSignature);
1401 assert(image->cache != (Cache) NULL);
1402 cache_info=(CacheInfo *) image->cache;
1403 assert(cache_info->signature == MagickSignature);
1404 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1405 (GetAuthenticMetacontentFromHandler) NULL)
1407 metacontent=cache_info->methods.
1408 get_authentic_metacontent_from_handler(image);
1409 return(metacontent);
1411 assert(id < (int) cache_info->number_threads);
1412 metacontent=GetPixelCacheNexusMetacontent(cache_info,
1413 cache_info->nexus_info[id]);
1414 return(metacontent);
1418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 + 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 %
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1429 % with the last call to QueueAuthenticPixelsCache() or
1430 % GetAuthenticPixelsCache().
1432 % The format of the GetAuthenticMetacontentFromCache() method is:
1434 % void *GetAuthenticMetacontentFromCache(const Image *image)
1436 % A description of each parameter follows:
1438 % o image: the image.
1441 static void *GetAuthenticMetacontentFromCache(const Image *image)
1447 id = GetOpenMPThreadId();
1452 assert(image != (const Image *) NULL);
1453 assert(image->signature == MagickSignature);
1454 assert(image->cache != (Cache) NULL);
1455 cache_info=(CacheInfo *) image->cache;
1456 assert(cache_info->signature == MagickSignature);
1457 assert(id < (int) cache_info->number_threads);
1458 metacontent=GetPixelCacheNexusMetacontent(image->cache,
1459 cache_info->nexus_info[id]);
1460 return(metacontent);
1464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1468 + 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 %
1472 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1475 % disk pixel cache as defined by the geometry parameters. A pointer to the
1476 % pixels is returned if the pixels are transferred, otherwise a NULL is
1479 % The format of the GetAuthenticPixelCacheNexus() method is:
1481 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1482 % const ssize_t y,const size_t columns,const size_t rows,
1483 % NexusInfo *nexus_info,ExceptionInfo *exception)
1485 % A description of each parameter follows:
1487 % o image: the image.
1489 % o x,y,columns,rows: These values define the perimeter of a region of
1492 % o nexus_info: the cache nexus to return.
1494 % o exception: return any errors or warnings in this structure.
1498 static inline MagickBooleanType IsPixelAuthentic(
1499 const CacheInfo *restrict cache_info,const NexusInfo *restrict nexus_info)
1507 if (cache_info->type == PingCache)
1509 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
1510 nexus_info->region.x;
1511 status=nexus_info->pixels == (cache_info->pixels+offset*
1512 cache_info->number_channels) ? MagickTrue : MagickFalse;
1516 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
1517 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
1518 NexusInfo *nexus_info,ExceptionInfo *exception)
1527 Transfer pixels from the cache.
1529 assert(image != (Image *) NULL);
1530 assert(image->signature == MagickSignature);
1531 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,nexus_info,
1533 if (q == (Quantum *) NULL)
1534 return((Quantum *) NULL);
1535 cache_info=(CacheInfo *) image->cache;
1536 assert(cache_info->signature == MagickSignature);
1537 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
1539 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1540 return((Quantum *) NULL);
1541 if (cache_info->metacontent_extent != 0)
1542 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1543 return((Quantum *) NULL);
1548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1552 + 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 %
1556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1558 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1559 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1561 % The format of the GetAuthenticPixelsFromCache() method is:
1563 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1565 % A description of each parameter follows:
1567 % o image: the image.
1570 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
1576 id = GetOpenMPThreadId();
1578 assert(image != (const Image *) NULL);
1579 assert(image->signature == MagickSignature);
1580 assert(image->cache != (Cache) NULL);
1581 cache_info=(CacheInfo *) image->cache;
1582 assert(cache_info->signature == MagickSignature);
1583 assert(id < (int) cache_info->number_threads);
1584 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]));
1588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1592 % G e t A u t h e n t i c P i x e l Q u e u e %
1596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598 % GetAuthenticPixelQueue() returns the authentic pixels associated
1599 % corresponding with the last call to QueueAuthenticPixels() or
1600 % GetAuthenticPixels().
1602 % The format of the GetAuthenticPixelQueue() method is:
1604 % Quantum *GetAuthenticPixelQueue(const Image image)
1606 % A description of each parameter follows:
1608 % o image: the image.
1611 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
1617 id = GetOpenMPThreadId();
1619 assert(image != (const Image *) NULL);
1620 assert(image->signature == MagickSignature);
1621 assert(image->cache != (Cache) NULL);
1622 cache_info=(CacheInfo *) image->cache;
1623 assert(cache_info->signature == MagickSignature);
1624 if (cache_info->methods.get_authentic_pixels_from_handler !=
1625 (GetAuthenticPixelsFromHandler) NULL)
1626 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1627 assert(id < (int) cache_info->number_threads);
1628 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id]));
1632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1636 % G e t A u t h e n t i c P i x e l s %
1639 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1641 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1642 % region is successfully accessed, a pointer to a Quantum array
1643 % representing the region is returned, otherwise NULL is returned.
1645 % The returned pointer may point to a temporary working copy of the pixels
1646 % or it may point to the original pixels in memory. Performance is maximized
1647 % if the selected region is part of one row, or one or more full rows, since
1648 % then there is opportunity to access the pixels in-place (without a copy)
1649 % if the image is in memory, or in a memory-mapped file. The returned pointer
1650 % must *never* be deallocated by the user.
1652 % Pixels accessed via the returned pointer represent a simple array of type
1653 % Quantum. If the image has corresponding metacontent,call
1654 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1655 % meta-content corresponding to the region. Once the Quantum array has
1656 % been updated, the changes must be saved back to the underlying image using
1657 % SyncAuthenticPixels() or they may be lost.
1659 % The format of the GetAuthenticPixels() method is:
1661 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1662 % const ssize_t y,const size_t columns,const size_t rows,
1663 % ExceptionInfo *exception)
1665 % A description of each parameter follows:
1667 % o image: the image.
1669 % o x,y,columns,rows: These values define the perimeter of a region of
1672 % o exception: return any errors or warnings in this structure.
1675 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1676 const ssize_t y,const size_t columns,const size_t rows,
1677 ExceptionInfo *exception)
1683 id = GetOpenMPThreadId();
1688 assert(image != (Image *) NULL);
1689 assert(image->signature == MagickSignature);
1690 assert(image->cache != (Cache) NULL);
1691 cache_info=(CacheInfo *) image->cache;
1692 assert(cache_info->signature == MagickSignature);
1693 if (cache_info->methods.get_authentic_pixels_handler !=
1694 (GetAuthenticPixelsHandler) NULL)
1696 q=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,rows,
1700 assert(id < (int) cache_info->number_threads);
1701 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1702 cache_info->nexus_info[id],exception);
1707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1711 + G e t A u t h e n t i c P i x e l s C a c h e %
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1718 % as defined by the geometry parameters. A pointer to the pixels is returned
1719 % if the pixels are transferred, otherwise a NULL is returned.
1721 % The format of the GetAuthenticPixelsCache() method is:
1723 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1724 % const ssize_t y,const size_t columns,const size_t rows,
1725 % ExceptionInfo *exception)
1727 % A description of each parameter follows:
1729 % o image: the image.
1731 % o x,y,columns,rows: These values define the perimeter of a region of
1734 % o exception: return any errors or warnings in this structure.
1737 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1738 const ssize_t y,const size_t columns,const size_t rows,
1739 ExceptionInfo *exception)
1745 id = GetOpenMPThreadId();
1750 assert(image != (const Image *) NULL);
1751 assert(image->signature == MagickSignature);
1752 assert(image->cache != (Cache) NULL);
1753 cache_info=(CacheInfo *) image->cache;
1754 if (cache_info == (Cache) NULL)
1755 return((Quantum *) NULL);
1756 assert(cache_info->signature == MagickSignature);
1757 assert(id < (int) cache_info->number_threads);
1758 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1759 cache_info->nexus_info[id],exception);
1764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1768 + G e t I m a g e E x t e n t %
1772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1774 % GetImageExtent() returns the extent of the pixels associated corresponding
1775 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1777 % The format of the GetImageExtent() method is:
1779 % MagickSizeType GetImageExtent(const Image *image)
1781 % A description of each parameter follows:
1783 % o image: the image.
1786 MagickExport MagickSizeType GetImageExtent(const Image *image)
1792 id = GetOpenMPThreadId();
1794 assert(image != (Image *) NULL);
1795 assert(image->signature == MagickSignature);
1796 if (image->debug != MagickFalse)
1797 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1798 assert(image->cache != (Cache) NULL);
1799 cache_info=(CacheInfo *) image->cache;
1800 assert(cache_info->signature == MagickSignature);
1801 assert(id < (int) cache_info->number_threads);
1802 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1810 + G e t I m a g e P i x e l C a c h e %
1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1816 % GetImagePixelCache() ensures that there is only a single reference to the
1817 % pixel cache to be modified, updating the provided cache pointer to point to
1818 % a clone of the original pixel cache if necessary.
1820 % The format of the GetImagePixelCache method is:
1822 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1823 % ExceptionInfo *exception)
1825 % A description of each parameter follows:
1827 % o image: the image.
1829 % o clone: any value other than MagickFalse clones the cache pixels.
1831 % o exception: return any errors or warnings in this structure.
1835 static inline MagickBooleanType ValidatePixelCacheMorphology(
1836 const Image *restrict image)
1839 *restrict cache_info;
1841 const PixelChannelMap
1846 Does the image match the pixel cache morphology?
1848 cache_info=(CacheInfo *) image->cache;
1849 p=image->channel_map;
1850 q=cache_info->channel_map;
1851 if ((image->storage_class != cache_info->storage_class) ||
1852 (image->colorspace != cache_info->colorspace) ||
1853 (image->alpha_trait != cache_info->alpha_trait) ||
1854 (image->mask != cache_info->mask) ||
1855 (image->columns != cache_info->columns) ||
1856 (image->rows != cache_info->rows) ||
1857 (image->number_channels != cache_info->number_channels) ||
1858 (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) ||
1859 (image->metacontent_extent != cache_info->metacontent_extent) ||
1860 (cache_info->nexus_info == (NexusInfo **) NULL))
1861 return(MagickFalse);
1865 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1866 ExceptionInfo *exception)
1875 static MagickSizeType
1881 cache_timestamp = 0;
1884 LockSemaphoreInfo(image->semaphore);
1885 if (cpu_throttle == 0)
1891 Set CPU throttle in milleseconds.
1893 cpu_throttle=MagickResourceInfinity;
1894 limit=GetEnvironmentValue("MAGICK_THROTTLE");
1895 if (limit == (char *) NULL)
1896 limit=GetPolicyValue("throttle");
1897 if (limit != (char *) NULL)
1899 cpu_throttle=(MagickSizeType) StringToInteger(limit);
1900 limit=DestroyString(limit);
1903 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0))
1904 MagickDelay(cpu_throttle);
1905 if (time_limit == 0)
1908 Set the exire time in seconds.
1910 time_limit=GetMagickResourceLimit(TimeResource);
1911 cache_timestamp=time((time_t *) NULL);
1913 if ((time_limit != MagickResourceInfinity) &&
1914 ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
1915 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
1916 assert(image->cache != (Cache) NULL);
1917 cache_info=(CacheInfo *) image->cache;
1918 destroy=MagickFalse;
1919 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1921 LockSemaphoreInfo(cache_info->semaphore);
1922 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1933 clone_image=(*image);
1934 clone_image.semaphore=AllocateSemaphoreInfo();
1935 clone_image.reference_count=1;
1936 clone_image.cache=ClonePixelCache(cache_info);
1937 clone_info=(CacheInfo *) clone_image.cache;
1938 status=OpenPixelCache(&clone_image,IOMode,exception);
1939 if (status != MagickFalse)
1941 if (clone != MagickFalse)
1942 status=ClonePixelCachePixels(clone_info,cache_info,exception);
1943 if (status != MagickFalse)
1945 if (cache_info->mode == ReadMode)
1946 cache_info->nexus_info=(NexusInfo **) NULL;
1948 image->cache=clone_image.cache;
1951 DestroySemaphoreInfo(&clone_image.semaphore);
1953 UnlockSemaphoreInfo(cache_info->semaphore);
1955 if (destroy != MagickFalse)
1956 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1957 if (status != MagickFalse)
1960 Ensure the image matches the pixel cache morphology.
1962 image->taint=MagickTrue;
1963 image->type=UndefinedType;
1964 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1966 status=OpenPixelCache(image,IOMode,exception);
1967 cache_info=(CacheInfo *) image->cache;
1968 if (cache_info->type == DiskCache)
1969 (void) ClosePixelCacheOnDisk(cache_info);
1972 UnlockSemaphoreInfo(image->semaphore);
1973 if (status == MagickFalse)
1974 return((Cache) NULL);
1975 return(image->cache);
1979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1983 + G e t I m a g e P i x e l C a c h e T y p e %
1987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1989 % GetImagePixelCacheType() returns the pixel cache type: UndefinedCache,
1990 % DiskCache, MemoryCache, MapCache, or PingCache.
1992 % The format of the GetImagePixelCacheType() method is:
1994 % CacheType GetImagePixelCacheType(const Image *image)
1996 % A description of each parameter follows:
1998 % o image: the image.
2001 MagickExport CacheType GetImagePixelCacheType(const Image *image)
2006 assert(image != (Image *) NULL);
2007 assert(image->signature == MagickSignature);
2008 assert(image->cache != (Cache) NULL);
2009 cache_info=(CacheInfo *) image->cache;
2010 assert(cache_info->signature == MagickSignature);
2011 return(cache_info->type);
2015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2019 % G e t O n e A u t h e n t i c P i x e l %
2023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2025 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
2026 % location. The image background color is returned if an error occurs.
2028 % The format of the GetOneAuthenticPixel() method is:
2030 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
2031 % const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2033 % A description of each parameter follows:
2035 % o image: the image.
2037 % o x,y: These values define the location of the pixel to return.
2039 % o pixel: return a pixel at the specified (x,y) location.
2041 % o exception: return any errors or warnings in this structure.
2044 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2045 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2056 assert(image != (Image *) NULL);
2057 assert(image->signature == MagickSignature);
2058 assert(image->cache != (Cache) NULL);
2059 cache_info=(CacheInfo *) image->cache;
2060 assert(cache_info->signature == MagickSignature);
2061 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2062 if (cache_info->methods.get_one_authentic_pixel_from_handler !=
2063 (GetOneAuthenticPixelFromHandler) NULL)
2064 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
2066 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2067 if (q == (Quantum *) NULL)
2069 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2070 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2071 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2072 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2073 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2074 return(MagickFalse);
2076 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2081 channel=GetPixelChannelChannel(image,i);
2082 pixel[channel]=q[i];
2088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2092 + 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 %
2096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2098 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
2099 % location. The image background color is returned if an error occurs.
2101 % The format of the GetOneAuthenticPixelFromCache() method is:
2103 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
2104 % const ssize_t x,const ssize_t y,Quantum *pixel,
2105 % ExceptionInfo *exception)
2107 % A description of each parameter follows:
2109 % o image: the image.
2111 % o x,y: These values define the location of the pixel to return.
2113 % o pixel: return a pixel at the specified (x,y) location.
2115 % o exception: return any errors or warnings in this structure.
2118 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2119 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2125 id = GetOpenMPThreadId();
2133 assert(image != (const Image *) NULL);
2134 assert(image->signature == MagickSignature);
2135 assert(image->cache != (Cache) NULL);
2136 cache_info=(CacheInfo *) image->cache;
2137 assert(cache_info->signature == MagickSignature);
2138 assert(id < (int) cache_info->number_threads);
2139 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2140 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
2142 if (q == (Quantum *) NULL)
2144 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2145 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2146 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2147 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2148 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2149 return(MagickFalse);
2151 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2156 channel=GetPixelChannelChannel(image,i);
2157 pixel[channel]=q[i];
2163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2167 % G e t O n e V i r t u a l P i x e l %
2171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2173 % GetOneVirtualPixel() returns a single virtual pixel at the specified
2174 % (x,y) location. The image background color is returned if an error occurs.
2175 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2177 % The format of the GetOneVirtualPixel() method is:
2179 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
2180 % const ssize_t y,Quantum *pixel,ExceptionInfo exception)
2182 % A description of each parameter follows:
2184 % o image: the image.
2186 % o x,y: These values define the location of the pixel to return.
2188 % o pixel: return a pixel at the specified (x,y) location.
2190 % o exception: return any errors or warnings in this structure.
2193 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
2194 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2200 id = GetOpenMPThreadId();
2208 assert(image != (const Image *) NULL);
2209 assert(image->signature == MagickSignature);
2210 assert(image->cache != (Cache) NULL);
2211 cache_info=(CacheInfo *) image->cache;
2212 assert(cache_info->signature == MagickSignature);
2213 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2214 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2215 (GetOneVirtualPixelFromHandler) NULL)
2216 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2217 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2218 assert(id < (int) cache_info->number_threads);
2219 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2220 1UL,1UL,cache_info->nexus_info[id],exception);
2221 if (p == (const Quantum *) NULL)
2223 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2224 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2225 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2226 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2227 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2228 return(MagickFalse);
2230 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2235 channel=GetPixelChannelChannel(image,i);
2236 pixel[channel]=p[i];
2242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2246 + 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 %
2250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2252 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2253 % specified (x,y) location. The image background color is returned if an
2256 % The format of the GetOneVirtualPixelFromCache() method is:
2258 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2259 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2260 % Quantum *pixel,ExceptionInfo *exception)
2262 % A description of each parameter follows:
2264 % o image: the image.
2266 % o virtual_pixel_method: the virtual pixel method.
2268 % o x,y: These values define the location of the pixel to return.
2270 % o pixel: return a pixel at the specified (x,y) location.
2272 % o exception: return any errors or warnings in this structure.
2275 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
2276 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2277 Quantum *pixel,ExceptionInfo *exception)
2283 id = GetOpenMPThreadId();
2291 assert(image != (const Image *) NULL);
2292 assert(image->signature == MagickSignature);
2293 assert(image->cache != (Cache) NULL);
2294 cache_info=(CacheInfo *) image->cache;
2295 assert(cache_info->signature == MagickSignature);
2296 assert(id < (int) cache_info->number_threads);
2297 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2298 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2299 cache_info->nexus_info[id],exception);
2300 if (p == (const Quantum *) NULL)
2302 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red);
2303 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green);
2304 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue);
2305 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black);
2306 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha);
2307 return(MagickFalse);
2309 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
2314 channel=GetPixelChannelChannel(image,i);
2315 pixel[channel]=p[i];
2321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2325 % G e t O n e V i r t u a l P i x e l I n f o %
2329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 % GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y)
2332 % location. The image background color is returned if an error occurs. If
2333 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2335 % The format of the GetOneVirtualPixelInfo() method is:
2337 % MagickBooleanType GetOneVirtualPixelInfo(const Image image,
2338 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2339 % const ssize_t y,PixelInfo *pixel,ExceptionInfo exception)
2341 % A description of each parameter follows:
2343 % o image: the image.
2345 % o virtual_pixel_method: the virtual pixel method.
2347 % o x,y: these values define the location of the pixel to return.
2349 % o pixel: return a pixel at the specified (x,y) location.
2351 % o exception: return any errors or warnings in this structure.
2354 MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
2355 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2356 PixelInfo *pixel,ExceptionInfo *exception)
2362 id = GetOpenMPThreadId();
2364 register const Quantum
2367 assert(image != (const Image *) NULL);
2368 assert(image->signature == MagickSignature);
2369 assert(image->cache != (Cache) NULL);
2370 cache_info=(CacheInfo *) image->cache;
2371 assert(cache_info->signature == MagickSignature);
2372 assert(id < (int) cache_info->number_threads);
2373 GetPixelInfo(image,pixel);
2374 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2375 cache_info->nexus_info[id],exception);
2376 if (p == (const Quantum *) NULL)
2377 return(MagickFalse);
2378 GetPixelInfoPixel(image,p,pixel);
2383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2387 + G e t P i x e l C a c h e C o l o r s p a c e %
2391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2393 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2395 % The format of the GetPixelCacheColorspace() method is:
2397 % Colorspace GetPixelCacheColorspace(Cache cache)
2399 % A description of each parameter follows:
2401 % o cache: the pixel cache.
2404 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
2409 assert(cache != (Cache) NULL);
2410 cache_info=(CacheInfo *) cache;
2411 assert(cache_info->signature == MagickSignature);
2412 if (cache_info->debug != MagickFalse)
2413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2414 cache_info->filename);
2415 return(cache_info->colorspace);
2419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2423 + G e t P i x e l C a c h e M e t h o d s %
2427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2429 % GetPixelCacheMethods() initializes the CacheMethods structure.
2431 % The format of the GetPixelCacheMethods() method is:
2433 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2435 % A description of each parameter follows:
2437 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2440 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
2442 assert(cache_methods != (CacheMethods *) NULL);
2443 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
2444 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2445 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2446 cache_methods->get_virtual_metacontent_from_handler=
2447 GetVirtualMetacontentFromCache;
2448 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2449 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2450 cache_methods->get_authentic_metacontent_from_handler=
2451 GetAuthenticMetacontentFromCache;
2452 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2453 cache_methods->get_one_authentic_pixel_from_handler=
2454 GetOneAuthenticPixelFromCache;
2455 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2456 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2457 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2465 + G e t P i x e l C a c h e N e x u s E x t e n t %
2469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2471 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2472 % corresponding with the last call to SetPixelCacheNexusPixels() or
2473 % GetPixelCacheNexusPixels().
2475 % The format of the GetPixelCacheNexusExtent() method is:
2477 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2478 % NexusInfo *nexus_info)
2480 % A description of each parameter follows:
2482 % o nexus_info: the nexus info.
2485 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2486 NexusInfo *nexus_info)
2494 assert(cache != NULL);
2495 cache_info=(CacheInfo *) cache;
2496 assert(cache_info->signature == MagickSignature);
2497 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2499 return((MagickSizeType) cache_info->columns*cache_info->rows);
2504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2508 + 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 %
2512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2514 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified
2517 % The format of the GetPixelCacheNexusMetacontent() method is:
2519 % void *GetPixelCacheNexusMetacontent(const Cache cache,
2520 % NexusInfo *nexus_info)
2522 % A description of each parameter follows:
2524 % o cache: the pixel cache.
2526 % o nexus_info: the cache nexus to return the meta-content.
2529 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache,
2530 NexusInfo *nexus_info)
2535 assert(cache != NULL);
2536 cache_info=(CacheInfo *) cache;
2537 assert(cache_info->signature == MagickSignature);
2538 if (cache_info->storage_class == UndefinedClass)
2539 return((void *) NULL);
2540 return(nexus_info->metacontent);
2544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2548 + G e t P i x e l C a c h e N e x u s P i x e l s %
2552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2554 % GetPixelCacheNexusPixels() returns the pixels associated with the specified
2557 % The format of the GetPixelCacheNexusPixels() method is:
2559 % Quantum *GetPixelCacheNexusPixels(const Cache cache,
2560 % NexusInfo *nexus_info)
2562 % A description of each parameter follows:
2564 % o cache: the pixel cache.
2566 % o nexus_info: the cache nexus to return the pixels.
2569 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache,
2570 NexusInfo *nexus_info)
2575 assert(cache != NULL);
2576 cache_info=(CacheInfo *) cache;
2577 assert(cache_info->signature == MagickSignature);
2578 if (cache_info->storage_class == UndefinedClass)
2579 return((Quantum *) NULL);
2580 return(nexus_info->pixels);
2584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2588 + G e t P i x e l C a c h e P i x e l s %
2592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2594 % GetPixelCachePixels() returns the pixels associated with the specified image.
2596 % The format of the GetPixelCachePixels() method is:
2598 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2599 % ExceptionInfo *exception)
2601 % A description of each parameter follows:
2603 % o image: the image.
2605 % o length: the pixel cache length.
2607 % o exception: return any errors or warnings in this structure.
2610 MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2611 ExceptionInfo *exception)
2616 assert(image != (const Image *) NULL);
2617 assert(image->signature == MagickSignature);
2618 assert(image->cache != (Cache) NULL);
2619 assert(length != (MagickSizeType *) NULL);
2620 assert(exception != (ExceptionInfo *) NULL);
2621 assert(exception->signature == MagickSignature);
2622 cache_info=(CacheInfo *) image->cache;
2623 assert(cache_info->signature == MagickSignature);
2625 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2626 return((void *) NULL);
2627 *length=cache_info->length;
2628 return((void *) cache_info->pixels);
2632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636 + 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 %
2640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2644 % The format of the GetPixelCacheStorageClass() method is:
2646 % ClassType GetPixelCacheStorageClass(Cache cache)
2648 % A description of each parameter follows:
2650 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2652 % o cache: the pixel cache.
2655 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
2660 assert(cache != (Cache) NULL);
2661 cache_info=(CacheInfo *) cache;
2662 assert(cache_info->signature == MagickSignature);
2663 if (cache_info->debug != MagickFalse)
2664 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2665 cache_info->filename);
2666 return(cache_info->storage_class);
2670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2674 + G e t P i x e l C a c h e T i l e S i z e %
2678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2680 % GetPixelCacheTileSize() returns the pixel cache tile size.
2682 % The format of the GetPixelCacheTileSize() method is:
2684 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2687 % A description of each parameter follows:
2689 % o image: the image.
2691 % o width: the optimize cache tile width in pixels.
2693 % o height: the optimize cache tile height in pixels.
2696 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2702 assert(image != (Image *) NULL);
2703 assert(image->signature == MagickSignature);
2704 if (image->debug != MagickFalse)
2705 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2706 cache_info=(CacheInfo *) image->cache;
2707 assert(cache_info->signature == MagickSignature);
2708 *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2709 if (GetImagePixelCacheType(image) == DiskCache)
2710 *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2719 + 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 %
2723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2725 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2726 % pixel cache. A virtual pixel is any pixel access that is outside the
2727 % boundaries of the image cache.
2729 % The format of the GetPixelCacheVirtualMethod() method is:
2731 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2733 % A description of each parameter follows:
2735 % o image: the image.
2738 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2743 assert(image != (Image *) NULL);
2744 assert(image->signature == MagickSignature);
2745 assert(image->cache != (Cache) NULL);
2746 cache_info=(CacheInfo *) image->cache;
2747 assert(cache_info->signature == MagickSignature);
2748 return(cache_info->virtual_pixel_method);
2752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2756 + 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 %
2760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2762 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2763 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2765 % The format of the GetVirtualMetacontentFromCache() method is:
2767 % void *GetVirtualMetacontentFromCache(const Image *image)
2769 % A description of each parameter follows:
2771 % o image: the image.
2774 static const void *GetVirtualMetacontentFromCache(const Image *image)
2780 id = GetOpenMPThreadId();
2785 assert(image != (const Image *) NULL);
2786 assert(image->signature == MagickSignature);
2787 assert(image->cache != (Cache) NULL);
2788 cache_info=(CacheInfo *) image->cache;
2789 assert(cache_info->signature == MagickSignature);
2790 assert(id < (int) cache_info->number_threads);
2791 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2792 cache_info->nexus_info[id]);
2793 return(metacontent);
2797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2801 + 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 %
2805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2807 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2810 % The format of the GetVirtualMetacontentFromNexus() method is:
2812 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2813 % NexusInfo *nexus_info)
2815 % A description of each parameter follows:
2817 % o cache: the pixel cache.
2819 % o nexus_info: the cache nexus to return the meta-content.
2822 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
2823 NexusInfo *nexus_info)
2828 assert(cache != (Cache) NULL);
2829 cache_info=(CacheInfo *) cache;
2830 assert(cache_info->signature == MagickSignature);
2831 if (cache_info->storage_class == UndefinedClass)
2832 return((void *) NULL);
2833 return(nexus_info->metacontent);
2837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2841 % G e t V i r t u a l M e t a c o n t e n t %
2845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2847 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2848 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2849 % returned if the meta-content are not available.
2851 % The format of the GetVirtualMetacontent() method is:
2853 % const void *GetVirtualMetacontent(const Image *image)
2855 % A description of each parameter follows:
2857 % o image: the image.
2860 MagickExport const void *GetVirtualMetacontent(const Image *image)
2866 id = GetOpenMPThreadId();
2871 assert(image != (const Image *) NULL);
2872 assert(image->signature == MagickSignature);
2873 assert(image->cache != (Cache) NULL);
2874 cache_info=(CacheInfo *) image->cache;
2875 assert(cache_info->signature == MagickSignature);
2876 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(image);
2877 if (metacontent != (void *) NULL)
2878 return(metacontent);
2879 assert(id < (int) cache_info->number_threads);
2880 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2881 cache_info->nexus_info[id]);
2882 return(metacontent);
2886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2890 + 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 %
2894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2896 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk
2897 % pixel cache as defined by the geometry parameters. A pointer to the pixels
2898 % is returned if the pixels are transferred, otherwise a NULL is returned.
2900 % The format of the GetVirtualPixelsFromNexus() method is:
2902 % Quantum *GetVirtualPixelsFromNexus(const Image *image,
2903 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2904 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
2905 % ExceptionInfo *exception)
2907 % A description of each parameter follows:
2909 % o image: the image.
2911 % o virtual_pixel_method: the virtual pixel method.
2913 % o x,y,columns,rows: These values define the perimeter of a region of
2916 % o nexus_info: the cache nexus to acquire.
2918 % o exception: return any errors or warnings in this structure.
2925 0, 48, 12, 60, 3, 51, 15, 63,
2926 32, 16, 44, 28, 35, 19, 47, 31,
2927 8, 56, 4, 52, 11, 59, 7, 55,
2928 40, 24, 36, 20, 43, 27, 39, 23,
2929 2, 50, 14, 62, 1, 49, 13, 61,
2930 34, 18, 46, 30, 33, 17, 45, 29,
2931 10, 58, 6, 54, 9, 57, 5, 53,
2932 42, 26, 38, 22, 41, 25, 37, 21
2935 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
2940 index=x+DitherMatrix[x & 0x07]-32L;
2943 if (index >= (ssize_t) columns)
2944 return((ssize_t) columns-1L);
2948 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
2953 index=y+DitherMatrix[y & 0x07]-32L;
2956 if (index >= (ssize_t) rows)
2957 return((ssize_t) rows-1L);
2961 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
2965 if (x >= (ssize_t) columns)
2966 return((ssize_t) (columns-1));
2970 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
2974 if (y >= (ssize_t) rows)
2975 return((ssize_t) (rows-1));
2979 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
2981 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2984 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
2986 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2989 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
2990 const size_t extent)
2996 Compute the remainder of dividing offset by extent. It returns not only
2997 the quotient (tile the offset falls in) but also the positive remainer
2998 within that tile such that 0 <= remainder < extent. This method is
2999 essentially a ldiv() using a floored modulo division rather than the
3000 normal default truncated modulo division.
3002 modulo.quotient=offset/(ssize_t) extent;
3005 modulo.remainder=offset-modulo.quotient*(ssize_t) extent;
3009 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
3010 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3011 const size_t columns,const size_t rows,NexusInfo *nexus_info,
3012 ExceptionInfo *exception)
3029 virtual_pixel[CompositePixelChannel];
3034 register const Quantum
3047 register unsigned char
3054 *virtual_metacontent;
3059 assert(image != (const Image *) NULL);
3060 assert(image->signature == MagickSignature);
3061 assert(image->cache != (Cache) NULL);
3062 cache_info=(CacheInfo *) image->cache;
3063 assert(cache_info->signature == MagickSignature);
3064 if (cache_info->type == UndefinedCache)
3065 return((const Quantum *) NULL);
3068 region.width=columns;
3070 pixels=SetPixelCacheNexusPixels(image,ReadMode,®ion,nexus_info,exception);
3071 if (pixels == (Quantum *) NULL)
3072 return((const Quantum *) NULL);
3074 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3075 nexus_info->region.x;
3076 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3077 nexus_info->region.width-1L;
3078 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3079 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3080 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3081 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3087 Pixel request is inside cache extents.
3089 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
3091 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3092 if (status == MagickFalse)
3093 return((const Quantum *) NULL);
3094 if (cache_info->metacontent_extent != 0)
3096 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
3097 if (status == MagickFalse)
3098 return((const Quantum *) NULL);
3103 Pixel request is outside cache extents.
3105 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info);
3106 virtual_nexus=AcquirePixelCacheNexus(1);
3107 if (virtual_nexus == (NexusInfo **) NULL)
3109 if (virtual_nexus != (NexusInfo **) NULL)
3110 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3111 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3112 "UnableToGetCacheNexus","'%s'",image->filename);
3113 return((const Quantum *) NULL);
3115 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
3116 sizeof(*virtual_pixel));
3117 virtual_metacontent=(void *) NULL;
3118 switch (virtual_pixel_method)
3120 case BackgroundVirtualPixelMethod:
3121 case BlackVirtualPixelMethod:
3122 case GrayVirtualPixelMethod:
3123 case TransparentVirtualPixelMethod:
3124 case MaskVirtualPixelMethod:
3125 case WhiteVirtualPixelMethod:
3126 case EdgeVirtualPixelMethod:
3127 case CheckerTileVirtualPixelMethod:
3128 case HorizontalTileVirtualPixelMethod:
3129 case VerticalTileVirtualPixelMethod:
3131 if (cache_info->metacontent_extent != 0)
3134 Acquire a metacontent buffer.
3136 virtual_metacontent=(void *) AcquireQuantumMemory(1,
3137 cache_info->metacontent_extent);
3138 if (virtual_metacontent == (void *) NULL)
3140 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3141 (void) ThrowMagickException(exception,GetMagickModule(),
3142 CacheError,"UnableToGetCacheNexus","'%s'",image->filename);
3143 return((const Quantum *) NULL);
3145 (void) ResetMagickMemory(virtual_metacontent,0,
3146 cache_info->metacontent_extent);
3148 switch (virtual_pixel_method)
3150 case BlackVirtualPixelMethod:
3152 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3153 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3154 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3157 case GrayVirtualPixelMethod:
3159 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3160 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
3162 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3165 case TransparentVirtualPixelMethod:
3167 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3168 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
3169 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
3172 case MaskVirtualPixelMethod:
3173 case WhiteVirtualPixelMethod:
3175 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
3176 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
3177 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3182 SetPixelRed(image,ClampToQuantum(image->background_color.red),
3184 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
3186 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
3188 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
3190 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3200 for (v=0; v < (ssize_t) rows; v++)
3202 for (u=0; u < (ssize_t) columns; u+=length)
3204 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
3205 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) ||
3206 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) ||
3214 Transfer a single pixel.
3216 length=(MagickSizeType) 1;
3217 switch (virtual_pixel_method)
3221 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3222 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows),
3223 1UL,1UL,*virtual_nexus,exception);
3224 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3227 case RandomVirtualPixelMethod:
3229 if (cache_info->random_info == (RandomInfo *) NULL)
3230 cache_info->random_info=AcquireRandomInfo();
3231 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3232 RandomX(cache_info->random_info,cache_info->columns),
3233 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3234 *virtual_nexus,exception);
3235 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3238 case DitherVirtualPixelMethod:
3240 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3241 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows),
3242 1UL,1UL,*virtual_nexus,exception);
3243 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3246 case TileVirtualPixelMethod:
3248 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3249 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3250 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3251 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3253 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3256 case MirrorVirtualPixelMethod:
3258 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3259 if ((x_modulo.quotient & 0x01) == 1L)
3260 x_modulo.remainder=(ssize_t) cache_info->columns-
3261 x_modulo.remainder-1L;
3262 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3263 if ((y_modulo.quotient & 0x01) == 1L)
3264 y_modulo.remainder=(ssize_t) cache_info->rows-
3265 y_modulo.remainder-1L;
3266 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3267 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3269 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3272 case HorizontalTileEdgeVirtualPixelMethod:
3274 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3275 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3276 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL,
3277 *virtual_nexus,exception);
3278 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3281 case VerticalTileEdgeVirtualPixelMethod:
3283 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3284 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3285 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL,
3286 *virtual_nexus,exception);
3287 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3290 case BackgroundVirtualPixelMethod:
3291 case BlackVirtualPixelMethod:
3292 case GrayVirtualPixelMethod:
3293 case TransparentVirtualPixelMethod:
3294 case MaskVirtualPixelMethod:
3295 case WhiteVirtualPixelMethod:
3298 r=virtual_metacontent;
3301 case EdgeVirtualPixelMethod:
3302 case CheckerTileVirtualPixelMethod:
3304 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3305 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3306 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3309 r=virtual_metacontent;
3312 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3313 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3315 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3318 case HorizontalTileVirtualPixelMethod:
3320 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
3323 r=virtual_metacontent;
3326 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3327 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3328 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3329 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3331 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3334 case VerticalTileVirtualPixelMethod:
3336 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
3339 r=virtual_metacontent;
3342 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
3343 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
3344 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
3345 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3347 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3351 if (p == (const Quantum *) NULL)
3353 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3355 q+=cache_info->number_channels;
3356 if ((s != (void *) NULL) && (r != (const void *) NULL))
3358 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3359 s+=cache_info->metacontent_extent;
3364 Transfer a run of pixels.
3366 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t)
3367 length,1UL,*virtual_nexus,exception);
3368 if (p == (const Quantum *) NULL)
3370 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3371 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3372 q+=length*cache_info->number_channels;
3373 if ((r != (void *) NULL) && (s != (const void *) NULL))
3375 (void) memcpy(s,r,(size_t) length);
3376 s+=length*cache_info->metacontent_extent;
3383 if (virtual_metacontent != (void *) NULL)
3384 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3385 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3394 + G e t V i r t u a l P i x e l C a c h e %
3398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3400 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3401 % cache as defined by the geometry parameters. A pointer to the pixels
3402 % is returned if the pixels are transferred, otherwise a NULL is returned.
3404 % The format of the GetVirtualPixelCache() method is:
3406 % const Quantum *GetVirtualPixelCache(const Image *image,
3407 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3408 % const ssize_t y,const size_t columns,const size_t rows,
3409 % ExceptionInfo *exception)
3411 % A description of each parameter follows:
3413 % o image: the image.
3415 % o virtual_pixel_method: the virtual pixel method.
3417 % o x,y,columns,rows: These values define the perimeter of a region of
3420 % o exception: return any errors or warnings in this structure.
3423 static const Quantum *GetVirtualPixelCache(const Image *image,
3424 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3425 const size_t columns,const size_t rows,ExceptionInfo *exception)
3431 id = GetOpenMPThreadId();
3436 assert(image != (const Image *) NULL);
3437 assert(image->signature == MagickSignature);
3438 assert(image->cache != (Cache) NULL);
3439 cache_info=(CacheInfo *) image->cache;
3440 assert(cache_info->signature == MagickSignature);
3441 assert(id < (int) cache_info->number_threads);
3442 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
3443 cache_info->nexus_info[id],exception);
3448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3452 % G e t V i r t u a l P i x e l Q u e u e %
3456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3458 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3459 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3461 % The format of the GetVirtualPixelQueue() method is:
3463 % const Quantum *GetVirtualPixelQueue(const Image image)
3465 % A description of each parameter follows:
3467 % o image: the image.
3470 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
3476 id = GetOpenMPThreadId();
3478 assert(image != (const Image *) NULL);
3479 assert(image->signature == MagickSignature);
3480 assert(image->cache != (Cache) NULL);
3481 cache_info=(CacheInfo *) image->cache;
3482 assert(cache_info->signature == MagickSignature);
3483 if (cache_info->methods.get_virtual_pixels_handler !=
3484 (GetVirtualPixelsHandler) NULL)
3485 return(cache_info->methods.get_virtual_pixels_handler(image));
3486 assert(id < (int) cache_info->number_threads);
3487 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3495 % G e t V i r t u a l P i x e l s %
3499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3501 % GetVirtualPixels() returns an immutable pixel region. If the
3502 % region is successfully accessed, a pointer to it is returned, otherwise
3503 % NULL is returned. The returned pointer may point to a temporary working
3504 % copy of the pixels or it may point to the original pixels in memory.
3505 % Performance is maximized if the selected region is part of one row, or one
3506 % or more full rows, since there is opportunity to access the pixels in-place
3507 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3508 % returned pointer must *never* be deallocated by the user.
3510 % Pixels accessed via the returned pointer represent a simple array of type
3511 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3512 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3513 % access the meta-content (of type void) corresponding to the the
3516 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3518 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3519 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3520 % GetCacheViewAuthenticPixels() instead.
3522 % The format of the GetVirtualPixels() method is:
3524 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3525 % const ssize_t y,const size_t columns,const size_t rows,
3526 % ExceptionInfo *exception)
3528 % A description of each parameter follows:
3530 % o image: the image.
3532 % o x,y,columns,rows: These values define the perimeter of a region of
3535 % o exception: return any errors or warnings in this structure.
3538 MagickExport const Quantum *GetVirtualPixels(const Image *image,
3539 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3540 ExceptionInfo *exception)
3546 id = GetOpenMPThreadId();
3551 assert(image != (const Image *) NULL);
3552 assert(image->signature == MagickSignature);
3553 assert(image->cache != (Cache) NULL);
3554 cache_info=(CacheInfo *) image->cache;
3555 assert(cache_info->signature == MagickSignature);
3556 if (cache_info->methods.get_virtual_pixel_handler !=
3557 (GetVirtualPixelHandler) NULL)
3558 return(cache_info->methods.get_virtual_pixel_handler(image,
3559 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3560 assert(id < (int) cache_info->number_threads);
3561 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3562 columns,rows,cache_info->nexus_info[id],exception);
3567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3571 + 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 %
3575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3577 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3578 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3580 % The format of the GetVirtualPixelsCache() method is:
3582 % Quantum *GetVirtualPixelsCache(const Image *image)
3584 % A description of each parameter follows:
3586 % o image: the image.
3589 static const Quantum *GetVirtualPixelsCache(const Image *image)
3595 id = GetOpenMPThreadId();
3597 assert(image != (const Image *) NULL);
3598 assert(image->signature == MagickSignature);
3599 assert(image->cache != (Cache) NULL);
3600 cache_info=(CacheInfo *) image->cache;
3601 assert(cache_info->signature == MagickSignature);
3602 assert(id < (int) cache_info->number_threads);
3603 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3611 + G e t V i r t u a l P i x e l s N e x u s %
3615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3617 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3620 % The format of the GetVirtualPixelsNexus() method is:
3622 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3623 % NexusInfo *nexus_info)
3625 % A description of each parameter follows:
3627 % o cache: the pixel cache.
3629 % o nexus_info: the cache nexus to return the colormap pixels.
3632 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
3633 NexusInfo *nexus_info)
3638 assert(cache != (Cache) NULL);
3639 cache_info=(CacheInfo *) cache;
3640 assert(cache_info->signature == MagickSignature);
3641 if (cache_info->storage_class == UndefinedClass)
3642 return((Quantum *) NULL);
3643 return((const Quantum *) nexus_info->pixels);
3647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3651 + O p e n P i x e l C a c h e %
3655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3657 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3658 % dimensions, allocating space for the image pixels and optionally the
3659 % metacontent, and memory mapping the cache if it is disk based. The cache
3660 % nexus array is initialized as well.
3662 % The format of the OpenPixelCache() method is:
3664 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3665 % ExceptionInfo *exception)
3667 % A description of each parameter follows:
3669 % o image: the image.
3671 % o mode: ReadMode, WriteMode, or IOMode.
3673 % o exception: return any errors or warnings in this structure.
3677 static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
3679 cache_info->mapped=MagickFalse;
3680 cache_info->pixels=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
3681 (size_t) cache_info->length));
3682 if (cache_info->pixels == (Quantum *) NULL)
3684 cache_info->mapped=MagickTrue;
3685 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3686 cache_info->length);
3690 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
3700 cache_info=(CacheInfo *) image->cache;
3701 if (image->debug != MagickFalse)
3704 format[MaxTextExtent],
3705 message[MaxTextExtent];
3707 (void) FormatMagickSize(length,MagickFalse,format);
3708 (void) FormatLocaleString(message,MaxTextExtent,
3709 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3710 cache_info->cache_filename,cache_info->file,format);
3711 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3713 if (length != (MagickSizeType) ((MagickOffsetType) length))
3714 return(MagickFalse);
3715 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3717 return(MagickFalse);
3718 if ((MagickSizeType) extent >= length)
3720 offset=(MagickOffsetType) length-1;
3721 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
3722 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
3725 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3726 ExceptionInfo *exception)
3733 format[MaxTextExtent],
3734 message[MaxTextExtent];
3747 assert(image != (const Image *) NULL);
3748 assert(image->signature == MagickSignature);
3749 assert(image->cache != (Cache) NULL);
3750 if (image->debug != MagickFalse)
3751 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3752 if ((image->columns == 0) || (image->rows == 0))
3753 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3754 cache_info=(CacheInfo *) image->cache;
3755 assert(cache_info->signature == MagickSignature);
3756 source_info=(*cache_info);
3757 source_info.file=(-1);
3758 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]",
3759 image->filename,(double) GetImageIndexInList(image));
3760 cache_info->storage_class=image->storage_class;
3761 cache_info->colorspace=image->colorspace;
3762 cache_info->alpha_trait=image->alpha_trait;
3763 cache_info->mask=image->mask;
3764 cache_info->rows=image->rows;
3765 cache_info->columns=image->columns;
3766 InitializePixelChannelMap(image);
3767 cache_info->number_channels=GetPixelChannels(image);
3768 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3769 sizeof(*image->channel_map));
3770 cache_info->metacontent_extent=image->metacontent_extent;
3771 cache_info->mode=mode;
3772 if (image->ping != MagickFalse)
3774 cache_info->type=PingCache;
3775 cache_info->pixels=(Quantum *) NULL;
3776 cache_info->metacontent=(void *) NULL;
3777 cache_info->length=0;
3780 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3781 packet_size=cache_info->number_channels*sizeof(Quantum);
3782 if (image->metacontent_extent != 0)
3783 packet_size+=cache_info->metacontent_extent;
3784 length=number_pixels*packet_size;
3785 columns=(size_t) (length/cache_info->rows/packet_size);
3786 if (cache_info->columns != columns)
3787 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
3789 cache_info->length=length;
3790 status=AcquireMagickResource(AreaResource,cache_info->length);
3791 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3792 cache_info->metacontent_extent);
3793 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
3795 status=AcquireMagickResource(MemoryResource,cache_info->length);
3796 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
3797 (cache_info->type == MemoryCache))
3799 AllocatePixelCachePixels(cache_info);
3800 if (cache_info->pixels == (Quantum *) NULL)
3801 cache_info->pixels=source_info.pixels;
3805 Create memory pixel cache.
3808 if (image->debug != MagickFalse)
3810 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
3811 (void) FormatLocaleString(message,MaxTextExtent,
3812 "open %s (%s memory, %.20gx%.20gx%.20g %s)",
3813 cache_info->filename,cache_info->mapped != MagickFalse ?
3814 "anonymous" : "heap",(double) cache_info->columns,(double)
3815 cache_info->rows,(double) cache_info->number_channels,
3817 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3820 cache_info->type=MemoryCache;
3821 cache_info->metacontent=(void *) NULL;
3822 if (cache_info->metacontent_extent != 0)
3823 cache_info->metacontent=(void *) (cache_info->pixels+
3824 number_pixels*cache_info->number_channels);
3825 if ((source_info.storage_class != UndefinedClass) &&
3828 status=ClonePixelCachePixels(cache_info,&source_info,
3830 RelinquishPixelCachePixels(&source_info);
3835 RelinquishMagickResource(MemoryResource,cache_info->length);
3838 Create pixel cache on disk.
3840 status=AcquireMagickResource(DiskResource,cache_info->length);
3841 if (status == MagickFalse)
3843 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3844 "CacheResourcesExhausted","'%s'",image->filename);
3845 return(MagickFalse);
3847 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3849 (void) ClosePixelCacheOnDisk(cache_info);
3850 *cache_info->cache_filename='\0';
3852 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3854 RelinquishMagickResource(DiskResource,cache_info->length);
3855 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3857 return(MagickFalse);
3859 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
3860 cache_info->length);
3861 if (status == MagickFalse)
3863 ThrowFileException(exception,CacheError,"UnableToExtendCache",
3865 return(MagickFalse);
3867 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3868 cache_info->metacontent_extent);
3869 if (length != (MagickSizeType) ((size_t) length))
3870 cache_info->type=DiskCache;
3873 status=AcquireMagickResource(MapResource,cache_info->length);
3874 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
3875 (cache_info->type != MemoryCache))
3876 cache_info->type=DiskCache;
3879 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3880 cache_info->offset,(size_t) cache_info->length);
3881 if (cache_info->pixels == (Quantum *) NULL)
3883 cache_info->type=DiskCache;
3884 cache_info->pixels=source_info.pixels;
3889 Create file-backed memory-mapped pixel cache.
3892 (void) ClosePixelCacheOnDisk(cache_info);
3893 cache_info->type=MapCache;
3894 cache_info->mapped=MagickTrue;
3895 cache_info->metacontent=(void *) NULL;
3896 if (cache_info->metacontent_extent != 0)
3897 cache_info->metacontent=(void *) (cache_info->pixels+
3898 number_pixels*cache_info->number_channels);
3899 if ((source_info.storage_class != UndefinedClass) &&
3902 status=ClonePixelCachePixels(cache_info,&source_info,
3904 RelinquishPixelCachePixels(&source_info);
3906 if (image->debug != MagickFalse)
3908 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
3909 (void) FormatLocaleString(message,MaxTextExtent,
3910 "open %s (%s[%d], memory-mapped, %.20gx%.20gx%.20g %s)",
3911 cache_info->filename,cache_info->cache_filename,
3912 cache_info->file,(double) cache_info->columns,(double)
3913 cache_info->rows,(double) cache_info->number_channels,
3915 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
3921 RelinquishMagickResource(MapResource,cache_info->length);
3924 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3926 status=ClonePixelCachePixels(cache_info,&source_info,exception);
3927 RelinquishPixelCachePixels(&source_info);
3929 if (image->debug != MagickFalse)
3931 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
3932 (void) FormatLocaleString(message,MaxTextExtent,
3933 "open %s (%s[%d], disk, %.20gx%.20gx%.20g %s)",cache_info->filename,
3934 cache_info->cache_filename,cache_info->file,(double)
3935 cache_info->columns,(double) cache_info->rows,(double)
3936 cache_info->number_channels,format);
3937 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3947 + P e r s i s t P i x e l C a c h e %
3951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3953 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
3954 % persistent pixel cache is one that resides on disk and is not destroyed
3955 % when the program exits.
3957 % The format of the PersistPixelCache() method is:
3959 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
3960 % const MagickBooleanType attach,MagickOffsetType *offset,
3961 % ExceptionInfo *exception)
3963 % A description of each parameter follows:
3965 % o image: the image.
3967 % o filename: the persistent pixel cache filename.
3969 % o attach: A value other than zero initializes the persistent pixel cache.
3971 % o initialize: A value other than zero initializes the persistent pixel
3974 % o offset: the offset in the persistent cache to store pixels.
3976 % o exception: return any errors or warnings in this structure.
3979 MagickExport MagickBooleanType PersistPixelCache(Image *image,
3980 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
3981 ExceptionInfo *exception)
3996 assert(image != (Image *) NULL);
3997 assert(image->signature == MagickSignature);
3998 if (image->debug != MagickFalse)
3999 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4000 assert(image->cache != (void *) NULL);
4001 assert(filename != (const char *) NULL);
4002 assert(offset != (MagickOffsetType *) NULL);
4003 page_size=GetMagickPageSize();
4004 cache_info=(CacheInfo *) image->cache;
4005 assert(cache_info->signature == MagickSignature);
4006 if (attach != MagickFalse)
4009 Attach existing persistent pixel cache.
4011 if (image->debug != MagickFalse)
4012 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4013 "attach persistent cache");
4014 (void) CopyMagickString(cache_info->cache_filename,filename,
4016 cache_info->type=DiskCache;
4017 cache_info->offset=(*offset);
4018 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4019 return(MagickFalse);
4020 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4023 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4024 (cache_info->reference_count == 1))
4026 LockSemaphoreInfo(cache_info->semaphore);
4027 if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
4028 (cache_info->reference_count == 1))
4034 Usurp existing persistent pixel cache.
4036 status=rename_utf8(cache_info->cache_filename,filename);
4039 (void) CopyMagickString(cache_info->cache_filename,filename,
4041 *offset+=cache_info->length+page_size-(cache_info->length %
4043 UnlockSemaphoreInfo(cache_info->semaphore);
4044 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
4045 if (image->debug != MagickFalse)
4046 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4047 "Usurp resident persistent cache");
4051 UnlockSemaphoreInfo(cache_info->semaphore);
4054 Clone persistent pixel cache.
4056 clone_image=(*image);
4057 clone_info=(CacheInfo *) clone_image.cache;
4058 image->cache=ClonePixelCache(cache_info);
4059 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
4060 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
4061 cache_info->type=DiskCache;
4062 cache_info->offset=(*offset);
4063 cache_info=(CacheInfo *) image->cache;
4064 status=OpenPixelCache(image,IOMode,exception);
4065 if (status != MagickFalse)
4066 status=ClonePixelCachePixels(cache_info,clone_info,exception);
4067 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4068 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4077 + Q u e u e A u t h e n t i c P i x e l C a c h e N e x u s %
4081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4083 % QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
4084 % defined by the region rectangle and returns a pointer to the region. This
4085 % region is subsequently transferred from the pixel cache with
4086 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4087 % pixels are transferred, otherwise a NULL is returned.
4089 % The format of the QueueAuthenticPixelCacheNexus() method is:
4091 % Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
4092 % const ssize_t y,const size_t columns,const size_t rows,
4093 % const MagickBooleanType clone,NexusInfo *nexus_info,
4094 % ExceptionInfo *exception)
4096 % A description of each parameter follows:
4098 % o image: the image.
4100 % o x,y,columns,rows: These values define the perimeter of a region of
4103 % o nexus_info: the cache nexus to set.
4105 % o clone: clone the pixel cache.
4107 % o exception: return any errors or warnings in this structure.
4110 MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4111 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
4112 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4127 Validate pixel cache geometry.
4129 assert(image != (const Image *) NULL);
4130 assert(image->signature == MagickSignature);
4131 assert(image->cache != (Cache) NULL);
4132 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4133 if (cache_info == (Cache) NULL)
4134 return((Quantum *) NULL);
4135 assert(cache_info->signature == MagickSignature);
4136 if ((cache_info->columns == 0) && (cache_info->rows == 0))
4138 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4139 "NoPixelsDefinedInCache","'%s'",image->filename);
4140 return((Quantum *) NULL);
4142 if ((x < 0) || (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4143 (y >= (ssize_t) cache_info->rows))
4145 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4146 "PixelsAreNotAuthentic","'%s'",image->filename);
4147 return((Quantum *) NULL);
4149 offset=(MagickOffsetType) y*cache_info->columns+x;
4151 return((Quantum *) NULL);
4152 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4153 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4154 if ((MagickSizeType) offset >= number_pixels)
4155 return((Quantum *) NULL);
4161 region.width=columns;
4163 return(SetPixelCacheNexusPixels(image,WriteMode,®ion,nexus_info,exception));
4167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4171 + 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 %
4175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4177 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4178 % defined by the region rectangle and returns a pointer to the region. This
4179 % region is subsequently transferred from the pixel cache with
4180 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4181 % pixels are transferred, otherwise a NULL is returned.
4183 % The format of the QueueAuthenticPixelsCache() method is:
4185 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4186 % const ssize_t y,const size_t columns,const size_t rows,
4187 % ExceptionInfo *exception)
4189 % A description of each parameter follows:
4191 % o image: the image.
4193 % o x,y,columns,rows: These values define the perimeter of a region of
4196 % o exception: return any errors or warnings in this structure.
4199 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4200 const ssize_t y,const size_t columns,const size_t rows,
4201 ExceptionInfo *exception)
4207 id = GetOpenMPThreadId();
4212 assert(image != (const Image *) NULL);
4213 assert(image->signature == MagickSignature);
4214 assert(image->cache != (Cache) NULL);
4215 cache_info=(CacheInfo *) image->cache;
4216 assert(cache_info->signature == MagickSignature);
4217 assert(id < (int) cache_info->number_threads);
4218 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4219 cache_info->nexus_info[id],exception);
4224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4228 % Q u e u e A u t h e n t i c P i x e l s %
4232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4234 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4235 % successfully initialized a pointer to a Quantum array representing the
4236 % region is returned, otherwise NULL is returned. The returned pointer may
4237 % point to a temporary working buffer for the pixels or it may point to the
4238 % final location of the pixels in memory.
4240 % Write-only access means that any existing pixel values corresponding to
4241 % the region are ignored. This is useful if the initial image is being
4242 % created from scratch, or if the existing pixel values are to be
4243 % completely replaced without need to refer to their pre-existing values.
4244 % The application is free to read and write the pixel buffer returned by
4245 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4246 % initialize the pixel array values. Initializing pixel array values is the
4247 % application's responsibility.
4249 % Performance is maximized if the selected region is part of one row, or
4250 % one or more full rows, since then there is opportunity to access the
4251 % pixels in-place (without a copy) if the image is in memory, or in a
4252 % memory-mapped file. The returned pointer must *never* be deallocated
4255 % Pixels accessed via the returned pointer represent a simple array of type
4256 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4257 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4258 % obtain the meta-content (of type void) corresponding to the region.
4259 % Once the Quantum (and/or Quantum) array has been updated, the
4260 % changes must be saved back to the underlying image using
4261 % SyncAuthenticPixels() or they may be lost.
4263 % The format of the QueueAuthenticPixels() method is:
4265 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4266 % const ssize_t y,const size_t columns,const size_t rows,
4267 % ExceptionInfo *exception)
4269 % A description of each parameter follows:
4271 % o image: the image.
4273 % o x,y,columns,rows: These values define the perimeter of a region of
4276 % o exception: return any errors or warnings in this structure.
4279 MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4280 const ssize_t y,const size_t columns,const size_t rows,
4281 ExceptionInfo *exception)
4287 id = GetOpenMPThreadId();
4292 assert(image != (Image *) NULL);
4293 assert(image->signature == MagickSignature);
4294 assert(image->cache != (Cache) NULL);
4295 cache_info=(CacheInfo *) image->cache;
4296 assert(cache_info->signature == MagickSignature);
4297 if (cache_info->methods.queue_authentic_pixels_handler !=
4298 (QueueAuthenticPixelsHandler) NULL)
4300 q=cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4304 assert(id < (int) cache_info->number_threads);
4305 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4306 cache_info->nexus_info[id],exception);
4311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4315 + 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 %
4319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4321 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4324 % The format of the ReadPixelCacheMetacontent() method is:
4326 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4327 % NexusInfo *nexus_info,ExceptionInfo *exception)
4329 % A description of each parameter follows:
4331 % o cache_info: the pixel cache.
4333 % o nexus_info: the cache nexus to read the metacontent.
4335 % o exception: return any errors or warnings in this structure.
4338 static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4339 NexusInfo *nexus_info,ExceptionInfo *exception)
4352 register unsigned char
4358 if (cache_info->metacontent_extent == 0)
4359 return(MagickFalse);
4360 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4362 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4363 nexus_info->region.x;
4364 length=(MagickSizeType) nexus_info->region.width*
4365 cache_info->metacontent_extent;
4366 rows=nexus_info->region.height;
4368 q=(unsigned char *) nexus_info->metacontent;
4369 switch (cache_info->type)
4374 register unsigned char
4378 Read meta-content from memory.
4380 if ((cache_info->columns == nexus_info->region.width) &&
4381 (extent == (MagickSizeType) ((size_t) extent)))
4386 p=(unsigned char *) cache_info->metacontent+offset*
4387 cache_info->metacontent_extent;
4388 for (y=0; y < (ssize_t) rows; y++)
4390 (void) memcpy(q,p,(size_t) length);
4391 p+=cache_info->metacontent_extent*cache_info->columns;
4392 q+=cache_info->metacontent_extent*nexus_info->region.width;
4399 Read meta content from disk.
4401 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4403 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4404 cache_info->cache_filename);
4405 return(MagickFalse);
4407 if ((cache_info->columns == nexus_info->region.width) &&
4408 (extent <= MagickMaxBufferExtent))
4413 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4414 for (y=0; y < (ssize_t) rows; y++)
4416 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4417 cache_info->number_channels*sizeof(Quantum)+offset*
4418 cache_info->metacontent_extent,length,(unsigned char *) q);
4419 if ((MagickSizeType) count != length)
4421 offset+=cache_info->columns;
4422 q+=cache_info->metacontent_extent*nexus_info->region.width;
4424 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4425 (void) ClosePixelCacheOnDisk(cache_info);
4426 if (y < (ssize_t) rows)
4428 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4429 cache_info->cache_filename);
4430 return(MagickFalse);
4437 if ((cache_info->debug != MagickFalse) &&
4438 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4439 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4440 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4441 nexus_info->region.width,(double) nexus_info->region.height,(double)
4442 nexus_info->region.x,(double) nexus_info->region.y);
4447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4451 + R e a d P i x e l C a c h e P i x e l s %
4455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4457 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4460 % The format of the ReadPixelCachePixels() method is:
4462 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4463 % NexusInfo *nexus_info,ExceptionInfo *exception)
4465 % A description of each parameter follows:
4467 % o cache_info: the pixel cache.
4469 % o nexus_info: the cache nexus to read the pixels.
4471 % o exception: return any errors or warnings in this structure.
4474 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4475 NexusInfo *nexus_info,ExceptionInfo *exception)
4494 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
4496 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4497 nexus_info->region.x;
4498 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
4500 rows=nexus_info->region.height;
4502 q=nexus_info->pixels;
4503 switch (cache_info->type)
4512 Read pixels from memory.
4514 if ((cache_info->columns == nexus_info->region.width) &&
4515 (extent == (MagickSizeType) ((size_t) extent)))
4520 p=cache_info->pixels+offset*cache_info->number_channels;
4521 for (y=0; y < (ssize_t) rows; y++)
4523 (void) memcpy(q,p,(size_t) length);
4524 p+=cache_info->number_channels*cache_info->columns;
4525 q+=cache_info->number_channels*nexus_info->region.width;
4532 Read pixels from disk.
4534 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4536 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4537 cache_info->cache_filename);
4538 return(MagickFalse);
4540 if ((cache_info->columns == nexus_info->region.width) &&
4541 (extent <= MagickMaxBufferExtent))
4546 for (y=0; y < (ssize_t) rows; y++)
4548 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4549 cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4550 if ((MagickSizeType) count != length)
4552 offset+=cache_info->columns;
4553 q+=cache_info->number_channels*nexus_info->region.width;
4555 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4556 (void) ClosePixelCacheOnDisk(cache_info);
4557 if (y < (ssize_t) rows)
4559 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4560 cache_info->cache_filename);
4561 return(MagickFalse);
4568 if ((cache_info->debug != MagickFalse) &&
4569 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4570 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4571 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4572 nexus_info->region.width,(double) nexus_info->region.height,(double)
4573 nexus_info->region.x,(double) nexus_info->region.y);
4578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4582 + R e f e r e n c e P i x e l C a c h e %
4586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4588 % ReferencePixelCache() increments the reference count associated with the
4589 % pixel cache returning a pointer to the cache.
4591 % The format of the ReferencePixelCache method is:
4593 % Cache ReferencePixelCache(Cache cache_info)
4595 % A description of each parameter follows:
4597 % o cache_info: the pixel cache.
4600 MagickPrivate Cache ReferencePixelCache(Cache cache)
4605 assert(cache != (Cache *) NULL);
4606 cache_info=(CacheInfo *) cache;
4607 assert(cache_info->signature == MagickSignature);
4608 LockSemaphoreInfo(cache_info->semaphore);
4609 cache_info->reference_count++;
4610 UnlockSemaphoreInfo(cache_info->semaphore);
4615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4619 + S e t P i x e l C a c h e M e t h o d s %
4623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4625 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4627 % The format of the SetPixelCacheMethods() method is:
4629 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4631 % A description of each parameter follows:
4633 % o cache: the pixel cache.
4635 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4638 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4643 GetOneAuthenticPixelFromHandler
4644 get_one_authentic_pixel_from_handler;
4646 GetOneVirtualPixelFromHandler
4647 get_one_virtual_pixel_from_handler;
4650 Set cache pixel methods.
4652 assert(cache != (Cache) NULL);
4653 assert(cache_methods != (CacheMethods *) NULL);
4654 cache_info=(CacheInfo *) cache;
4655 assert(cache_info->signature == MagickSignature);
4656 if (cache_info->debug != MagickFalse)
4657 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4658 cache_info->filename);
4659 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4660 cache_info->methods.get_virtual_pixel_handler=
4661 cache_methods->get_virtual_pixel_handler;
4662 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4663 cache_info->methods.destroy_pixel_handler=
4664 cache_methods->destroy_pixel_handler;
4665 if (cache_methods->get_virtual_metacontent_from_handler !=
4666 (GetVirtualMetacontentFromHandler) NULL)
4667 cache_info->methods.get_virtual_metacontent_from_handler=
4668 cache_methods->get_virtual_metacontent_from_handler;
4669 if (cache_methods->get_authentic_pixels_handler !=
4670 (GetAuthenticPixelsHandler) NULL)
4671 cache_info->methods.get_authentic_pixels_handler=
4672 cache_methods->get_authentic_pixels_handler;
4673 if (cache_methods->queue_authentic_pixels_handler !=
4674 (QueueAuthenticPixelsHandler) NULL)
4675 cache_info->methods.queue_authentic_pixels_handler=
4676 cache_methods->queue_authentic_pixels_handler;
4677 if (cache_methods->sync_authentic_pixels_handler !=
4678 (SyncAuthenticPixelsHandler) NULL)
4679 cache_info->methods.sync_authentic_pixels_handler=
4680 cache_methods->sync_authentic_pixels_handler;
4681 if (cache_methods->get_authentic_pixels_from_handler !=
4682 (GetAuthenticPixelsFromHandler) NULL)
4683 cache_info->methods.get_authentic_pixels_from_handler=
4684 cache_methods->get_authentic_pixels_from_handler;
4685 if (cache_methods->get_authentic_metacontent_from_handler !=
4686 (GetAuthenticMetacontentFromHandler) NULL)
4687 cache_info->methods.get_authentic_metacontent_from_handler=
4688 cache_methods->get_authentic_metacontent_from_handler;
4689 get_one_virtual_pixel_from_handler=
4690 cache_info->methods.get_one_virtual_pixel_from_handler;
4691 if (get_one_virtual_pixel_from_handler !=
4692 (GetOneVirtualPixelFromHandler) NULL)
4693 cache_info->methods.get_one_virtual_pixel_from_handler=
4694 cache_methods->get_one_virtual_pixel_from_handler;
4695 get_one_authentic_pixel_from_handler=
4696 cache_methods->get_one_authentic_pixel_from_handler;
4697 if (get_one_authentic_pixel_from_handler !=
4698 (GetOneAuthenticPixelFromHandler) NULL)
4699 cache_info->methods.get_one_authentic_pixel_from_handler=
4700 cache_methods->get_one_authentic_pixel_from_handler;
4704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4708 + S e t P i x e l C a c h e N e x u s P i x e l s %
4712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4714 % SetPixelCacheNexusPixels() defines the region of the cache for the
4715 % specified cache nexus.
4717 % The format of the SetPixelCacheNexusPixels() method is:
4719 % Quantum SetPixelCacheNexusPixels(const Image *image,const MapMode mode,
4720 % const RectangleInfo *region,NexusInfo *nexus_info,
4721 % ExceptionInfo *exception)
4723 % A description of each parameter follows:
4725 % o image: the image.
4727 % o mode: ReadMode, WriteMode, or IOMode.
4729 % o region: A pointer to the RectangleInfo structure that defines the
4730 % region of this particular cache nexus.
4732 % o nexus_info: the cache nexus to set.
4734 % o exception: return any errors or warnings in this structure.
4738 static inline MagickBooleanType AcquireCacheNexusPixels(
4739 const CacheInfo *restrict cache_info,NexusInfo *nexus_info,
4740 ExceptionInfo *exception)
4742 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4743 return(MagickFalse);
4744 nexus_info->mapped=MagickFalse;
4745 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
4746 (size_t) nexus_info->length));
4747 if (nexus_info->cache == (Quantum *) NULL)
4749 nexus_info->mapped=MagickTrue;
4750 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4751 nexus_info->length);
4753 if (nexus_info->cache == (Quantum *) NULL)
4755 (void) ThrowMagickException(exception,GetMagickModule(),
4756 ResourceLimitError,"MemoryAllocationFailed","'%s'",
4757 cache_info->filename);
4758 return(MagickFalse);
4763 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4766 if (mode == ReadMode)
4768 MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
4771 MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
4774 static Quantum *SetPixelCacheNexusPixels(const Image *image,const MapMode mode,
4775 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
4787 cache_info=(CacheInfo *) image->cache;
4788 assert(cache_info->signature == MagickSignature);
4789 if (cache_info->type == UndefinedCache)
4790 return((Quantum *) NULL);
4791 nexus_info->region=(*region);
4792 if ((cache_info->type != DiskCache) && (cache_info->type != PingCache))
4798 x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
4799 y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
4800 if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
4801 (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
4802 ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
4803 ((nexus_info->region.width == cache_info->columns) ||
4804 ((nexus_info->region.width % cache_info->columns) == 0)))))
4810 Pixels are accessed directly from memory.
4812 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4813 nexus_info->region.x;
4814 nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
4816 nexus_info->metacontent=(void *) NULL;
4817 if (cache_info->metacontent_extent != 0)
4818 nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
4819 offset*cache_info->metacontent_extent;
4820 PrefetchPixelCacheNexusPixels(nexus_info,mode);
4821 return(nexus_info->pixels);
4825 Pixels are stored in a cache region until they are synced to the cache.
4827 number_pixels=(MagickSizeType) nexus_info->region.width*
4828 nexus_info->region.height;
4829 length=number_pixels*cache_info->number_channels*sizeof(Quantum);
4830 if (cache_info->metacontent_extent != 0)
4831 length+=number_pixels*cache_info->metacontent_extent;
4832 if (nexus_info->cache == (Quantum *) NULL)
4834 nexus_info->length=length;
4835 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4836 if (status == MagickFalse)
4838 nexus_info->length=0;
4839 return((Quantum *) NULL);
4843 if (nexus_info->length != length)
4845 RelinquishCacheNexusPixels(nexus_info);
4846 nexus_info->length=length;
4847 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4848 if (status == MagickFalse)
4850 nexus_info->length=0;
4851 return((Quantum *) NULL);
4854 nexus_info->pixels=nexus_info->cache;
4855 nexus_info->metacontent=(void *) NULL;
4856 if (cache_info->metacontent_extent != 0)
4857 nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
4858 cache_info->number_channels);
4859 PrefetchPixelCacheNexusPixels(nexus_info,mode);
4860 return(nexus_info->pixels);
4864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4868 % 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 %
4872 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4874 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
4875 % pixel cache and returns the previous setting. A virtual pixel is any pixel
4876 % access that is outside the boundaries of the image cache.
4878 % The format of the SetPixelCacheVirtualMethod() method is:
4880 % VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4881 % const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4883 % A description of each parameter follows:
4885 % o image: the image.
4887 % o virtual_pixel_method: choose the type of virtual pixel.
4889 % o exception: return any errors or warnings in this structure.
4893 static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
4894 ExceptionInfo *exception)
4908 assert(image != (Image *) NULL);
4909 assert(image->signature == MagickSignature);
4910 if (image->debug != MagickFalse)
4911 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4912 assert(image->cache != (Cache) NULL);
4913 cache_info=(CacheInfo *) image->cache;
4914 assert(cache_info->signature == MagickSignature);
4915 image->alpha_trait=BlendPixelTrait;
4917 image_view=AcquireVirtualCacheView(image,exception); /* must be virtual */
4918 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4919 #pragma omp parallel for schedule(static,4) shared(status) \
4920 dynamic_number_threads(image,image->columns,image->rows,1)
4922 for (y=0; y < (ssize_t) image->rows; y++)
4930 if (status == MagickFalse)
4932 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4933 if (q == (Quantum *) NULL)
4938 for (x=0; x < (ssize_t) image->columns; x++)
4940 SetPixelAlpha(image,alpha,q);
4941 q+=GetPixelChannels(image);
4943 status=SyncCacheViewAuthenticPixels(image_view,exception);
4945 image_view=DestroyCacheView(image_view);
4949 MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4950 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4958 assert(image != (Image *) NULL);
4959 assert(image->signature == MagickSignature);
4960 if (image->debug != MagickFalse)
4961 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4962 assert(image->cache != (Cache) NULL);
4963 cache_info=(CacheInfo *) image->cache;
4964 assert(cache_info->signature == MagickSignature);
4965 method=cache_info->virtual_pixel_method;
4966 cache_info->virtual_pixel_method=virtual_pixel_method;
4967 if ((image->columns != 0) && (image->rows != 0))
4968 switch (virtual_pixel_method)
4970 case BackgroundVirtualPixelMethod:
4972 if ((image->background_color.alpha_trait == BlendPixelTrait) &&
4973 (image->alpha_trait != BlendPixelTrait))
4974 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4975 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
4976 (IsGrayColorspace(image->colorspace) != MagickFalse))
4977 (void) TransformImageColorspace(image,RGBColorspace,exception);
4980 case TransparentVirtualPixelMethod:
4982 if (image->alpha_trait != BlendPixelTrait)
4983 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4997 + 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 %
5001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5003 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5004 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5005 % is synced, otherwise MagickFalse.
5007 % The format of the SyncAuthenticPixelCacheNexus() method is:
5009 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5010 % NexusInfo *nexus_info,ExceptionInfo *exception)
5012 % A description of each parameter follows:
5014 % o image: the image.
5016 % o nexus_info: the cache nexus to sync.
5018 % o exception: return any errors or warnings in this structure.
5021 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5022 NexusInfo *nexus_info,ExceptionInfo *exception)
5031 Transfer pixels to the cache.
5033 assert(image != (Image *) NULL);
5034 assert(image->signature == MagickSignature);
5035 if (image->cache == (Cache) NULL)
5036 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5037 cache_info=(CacheInfo *) image->cache;
5038 assert(cache_info->signature == MagickSignature);
5039 if (cache_info->type == UndefinedCache)
5040 return(MagickFalse);
5041 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5043 assert(cache_info->signature == MagickSignature);
5044 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5045 if ((cache_info->metacontent_extent != 0) &&
5046 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5047 return(MagickFalse);
5052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5056 + S y n c A u t h e n t i c P i x e l C a c h e %
5060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5062 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5063 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5064 % otherwise MagickFalse.
5066 % The format of the SyncAuthenticPixelsCache() method is:
5068 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5069 % ExceptionInfo *exception)
5071 % A description of each parameter follows:
5073 % o image: the image.
5075 % o exception: return any errors or warnings in this structure.
5078 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5079 ExceptionInfo *exception)
5085 id = GetOpenMPThreadId();
5090 assert(image != (Image *) NULL);
5091 assert(image->signature == MagickSignature);
5092 assert(image->cache != (Cache) NULL);
5093 cache_info=(CacheInfo *) image->cache;
5094 assert(cache_info->signature == MagickSignature);
5095 assert(id < (int) cache_info->number_threads);
5096 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5106 % S y n c A u t h e n t i c P i x e l s %
5110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5112 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5113 % The method returns MagickTrue if the pixel region is flushed, otherwise
5116 % The format of the SyncAuthenticPixels() method is:
5118 % MagickBooleanType SyncAuthenticPixels(Image *image,
5119 % ExceptionInfo *exception)
5121 % A description of each parameter follows:
5123 % o image: the image.
5125 % o exception: return any errors or warnings in this structure.
5128 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5129 ExceptionInfo *exception)
5135 id = GetOpenMPThreadId();
5140 assert(image != (Image *) NULL);
5141 assert(image->signature == MagickSignature);
5142 assert(image->cache != (Cache) NULL);
5143 cache_info=(CacheInfo *) image->cache;
5144 assert(cache_info->signature == MagickSignature);
5145 if (cache_info->methods.sync_authentic_pixels_handler !=
5146 (SyncAuthenticPixelsHandler) NULL)
5148 status=cache_info->methods.sync_authentic_pixels_handler(image,
5152 assert(id < (int) cache_info->number_threads);
5153 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5163 + S y n c I m a g e P i x e l C a c h e %
5167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5169 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5170 % The method returns MagickTrue if the pixel region is flushed, otherwise
5173 % The format of the SyncImagePixelCache() method is:
5175 % MagickBooleanType SyncImagePixelCache(Image *image,
5176 % ExceptionInfo *exception)
5178 % A description of each parameter follows:
5180 % o image: the image.
5182 % o exception: return any errors or warnings in this structure.
5185 MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5186 ExceptionInfo *exception)
5191 assert(image != (Image *) NULL);
5192 assert(exception != (ExceptionInfo *) NULL);
5193 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5194 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5202 + 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 %
5206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5208 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5209 % of the pixel cache.
5211 % The format of the WritePixelCacheMetacontent() method is:
5213 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5214 % NexusInfo *nexus_info,ExceptionInfo *exception)
5216 % A description of each parameter follows:
5218 % o cache_info: the pixel cache.
5220 % o nexus_info: the cache nexus to write the meta-content.
5222 % o exception: return any errors or warnings in this structure.
5225 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5226 NexusInfo *nexus_info,ExceptionInfo *exception)
5236 register const unsigned char
5245 if (cache_info->metacontent_extent == 0)
5246 return(MagickFalse);
5247 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5249 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5250 nexus_info->region.x;
5251 length=(MagickSizeType) nexus_info->region.width*
5252 cache_info->metacontent_extent;
5253 rows=nexus_info->region.height;
5254 extent=(MagickSizeType) length*rows;
5255 p=(unsigned char *) nexus_info->metacontent;
5256 switch (cache_info->type)
5261 register unsigned char
5265 Write associated pixels to memory.
5267 if ((cache_info->columns == nexus_info->region.width) &&
5268 (extent == (MagickSizeType) ((size_t) extent)))
5273 q=(unsigned char *) cache_info->metacontent+offset*
5274 cache_info->metacontent_extent;
5275 for (y=0; y < (ssize_t) rows; y++)
5277 (void) memcpy(q,p,(size_t) length);
5278 p+=nexus_info->region.width*cache_info->metacontent_extent;
5279 q+=cache_info->columns*cache_info->metacontent_extent;
5286 Write associated pixels to disk.
5288 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5290 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5291 cache_info->cache_filename);
5292 return(MagickFalse);
5294 if ((cache_info->columns == nexus_info->region.width) &&
5295 (extent <= MagickMaxBufferExtent))
5300 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5301 for (y=0; y < (ssize_t) rows; y++)
5303 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5304 cache_info->number_channels*sizeof(Quantum)+offset*
5305 cache_info->metacontent_extent,length,(const unsigned char *) p);
5306 if ((MagickSizeType) count != length)
5308 p+=nexus_info->region.width*cache_info->metacontent_extent;
5309 offset+=cache_info->columns;
5311 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5312 (void) ClosePixelCacheOnDisk(cache_info);
5313 if (y < (ssize_t) rows)
5315 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5316 cache_info->cache_filename);
5317 return(MagickFalse);
5324 if ((cache_info->debug != MagickFalse) &&
5325 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5326 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5327 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5328 nexus_info->region.width,(double) nexus_info->region.height,(double)
5329 nexus_info->region.x,(double) nexus_info->region.y);
5334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5338 + W r i t e C a c h e P i x e l s %
5342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5344 % WritePixelCachePixels() writes image pixels to the specified region of the
5347 % The format of the WritePixelCachePixels() method is:
5349 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5350 % NexusInfo *nexus_info,ExceptionInfo *exception)
5352 % A description of each parameter follows:
5354 % o cache_info: the pixel cache.
5356 % o nexus_info: the cache nexus to write the pixels.
5358 % o exception: return any errors or warnings in this structure.
5361 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5362 NexusInfo *nexus_info,ExceptionInfo *exception)
5372 register const Quantum
5381 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse)
5383 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5384 nexus_info->region.x;
5385 length=(MagickSizeType) nexus_info->region.width*cache_info->number_channels*
5387 rows=nexus_info->region.height;
5389 p=nexus_info->pixels;
5390 switch (cache_info->type)
5399 Write pixels to memory.
5401 if ((cache_info->columns == nexus_info->region.width) &&
5402 (extent == (MagickSizeType) ((size_t) extent)))
5407 q=cache_info->pixels+offset*cache_info->number_channels;
5408 for (y=0; y < (ssize_t) rows; y++)
5410 (void) memcpy(q,p,(size_t) length);
5411 p+=nexus_info->region.width*cache_info->number_channels;
5412 q+=cache_info->columns*cache_info->number_channels;
5419 Write pixels to disk.
5421 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5423 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5424 cache_info->cache_filename);
5425 return(MagickFalse);
5427 if ((cache_info->columns == nexus_info->region.width) &&
5428 (extent <= MagickMaxBufferExtent))
5433 for (y=0; y < (ssize_t) rows; y++)
5435 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5436 cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5438 if ((MagickSizeType) count != length)
5440 p+=nexus_info->region.width*cache_info->number_channels;
5441 offset+=cache_info->columns;
5443 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5444 (void) ClosePixelCacheOnDisk(cache_info);
5445 if (y < (ssize_t) rows)
5447 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5448 cache_info->cache_filename);
5449 return(MagickFalse);
5456 if ((cache_info->debug != MagickFalse) &&
5457 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5458 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5459 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5460 nexus_info->region.width,(double) nexus_info->region.height,(double)
5461 nexus_info->region.x,(double) nexus_info->region.y);