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/distribute-cache-private.h"
52#include "MagickCore/exception.h"
53#include "MagickCore/exception-private.h"
54#include "MagickCore/geometry.h"
55#include "MagickCore/list.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#include "MagickCore/memory-private.h"
60#include "MagickCore/nt-base-private.h"
61#include "MagickCore/option.h"
62#include "MagickCore/pixel.h"
63#include "MagickCore/pixel-accessor.h"
64#include "MagickCore/pixel-private.h"
65#include "MagickCore/policy.h"
66#include "MagickCore/policy-private.h"
67#include "MagickCore/quantum.h"
68#include "MagickCore/random_.h"
69#include "MagickCore/registry.h"
70#include "MagickCore/resource_.h"
71#include "MagickCore/semaphore.h"
72#include "MagickCore/splay-tree.h"
73#include "MagickCore/string_.h"
74#include "MagickCore/string-private.h"
75#include "MagickCore/timer-private.h"
76#include "MagickCore/thread-private.h"
77#include "MagickCore/utility.h"
78#include "MagickCore/utility-private.h"
79#if defined(MAGICKCORE_HAVE_ERRNO_H)
82#if defined(MAGICKCORE_HAVE_SYS_LOADAVG_H)
83# include <sys/loadavg.h>
85#if defined(MAGICKCORE_ZLIB_DELEGATE)
92#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
93#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
94 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
109#if defined(__cplusplus) || defined(c_plusplus)
118 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
120 *GetVirtualPixelsCache(
const Image *);
123 *GetVirtualMetacontentFromCache(
const Image *);
125static MagickBooleanType
126 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,Quantum *,
128 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
134 ReadPixelCacheMetacontent(
CacheInfo *magick_restrict,
143 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
145 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
147 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
148 const ssize_t,
const ssize_t,
const size_t,
const size_t,
152#if defined(MAGICKCORE_OPENCL_SUPPORT)
154 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
157#if defined(__cplusplus) || defined(c_plusplus)
168 cache_anonymous_memory = (-1);
192MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
195 *magick_restrict cache_info;
200 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
202 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
203 (void) memset(cache_info,0,
sizeof(*cache_info));
204 cache_info->type=UndefinedCache;
205 cache_info->mode=IOMode;
206 cache_info->disk_mode=IOMode;
207 cache_info->colorspace=sRGBColorspace;
208 cache_info->file=(-1);
209 cache_info->id=GetMagickThreadId();
210 cache_info->number_threads=number_threads;
211 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
212 cache_info->number_threads=GetOpenMPMaximumThreads();
213 if (cache_info->number_threads == 0)
214 cache_info->number_threads=1;
215 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
216 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
217 if (value != (
const char *) NULL)
219 cache_info->synchronize=IsStringTrue(value);
220 value=DestroyString(value);
222 value=GetPolicyValue(
"cache:synchronize");
223 if (value != (
const char *) NULL)
225 cache_info->synchronize=IsStringTrue(value);
226 value=DestroyString(value);
228 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
229 (MagickSizeType) MAGICK_SSIZE_MAX);
230 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
231 (MagickSizeType) MAGICK_SSIZE_MAX);
232 cache_info->semaphore=AcquireSemaphoreInfo();
233 cache_info->reference_count=1;
234 cache_info->file_semaphore=AcquireSemaphoreInfo();
235 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
237 cache_info->signature=MagickCoreSignature;
238 return((Cache ) cache_info);
263MagickPrivate
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
266 **magick_restrict nexus_info;
271 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
272 number_threads,
sizeof(*nexus_info)));
274 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
275 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
276 2*
sizeof(**nexus_info));
278 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
279 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
280 for (i=0; i < (ssize_t) (2*number_threads); i++)
282 nexus_info[i]=(*nexus_info+i);
283 if (i < (ssize_t) number_threads)
284 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
285 nexus_info[i]->signature=MagickCoreSignature;
318MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
322 *magick_restrict cache_info;
324 assert(image != (
const Image *) NULL);
325 assert(image->signature == MagickCoreSignature);
327 assert(exception->signature == MagickCoreSignature);
328 assert(image->cache != (Cache) NULL);
331 assert(cache_info->signature == MagickCoreSignature);
333 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
334 return((
void *) NULL);
335 *length=(size_t) cache_info->length;
336 return(cache_info->pixels);
357MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
360 cache_semaphore=AcquireSemaphoreInfo();
382MagickPrivate
void CacheComponentTerminus(
void)
385 ActivateSemaphoreInfo(&cache_semaphore);
387 RelinquishSemaphoreInfo(&cache_semaphore);
419static MagickBooleanType ClipPixelCacheNexus(
Image *image,
423 *magick_restrict cache_info;
435 if (IsEventLogging() != MagickFalse)
436 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
437 if ((image->channels & WriteMaskChannel) == 0)
439 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
444 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
445 nexus_info->region.width,nexus_info->region.height,
446 nexus_info->virtual_nexus,exception);
447 q=nexus_info->pixels;
448 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
450 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
455 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
463 mask=(double) GetPixelWriteMask(image,p);
464 if (fabs(mask) >= MagickEpsilon)
473 src_alpha=GetPixelAlpha(image,p);
474 mask_alpha=QuantumScale*mask*(double) src_alpha;
475 dst_alpha=(double) GetPixelAlpha(image,q);
476 for (i=0; i < (ssize_t) image->number_channels; i++)
481 PixelChannel channel = GetPixelChannelChannel(image,i);
482 if (channel == AlphaPixelChannel)
484 traits=GetPixelChannelTraits(image,channel);
485 if ((traits & UpdatePixelTrait) == 0)
487 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha,
488 (
double) q[i],dst_alpha));
490 SetPixelAlpha(image,src_alpha,q);
492 p+=(ptrdiff_t) GetPixelChannels(image);
493 q+=(ptrdiff_t) GetPixelChannels(image);
521MagickPrivate Cache ClonePixelCache(
const Cache cache)
524 *magick_restrict clone_info;
527 *magick_restrict cache_info;
529 assert(cache != NULL);
531 assert(cache_info->signature == MagickCoreSignature);
532 if (IsEventLogging() != MagickFalse)
533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
534 cache_info->filename);
535 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
536 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
537 return((Cache ) clone_info);
565MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
568 *magick_restrict cache_info,
569 *magick_restrict source_info;
571 assert(clone != (Cache) NULL);
573 assert(source_info->signature == MagickCoreSignature);
574 if (IsEventLogging() != MagickFalse)
575 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
576 source_info->filename);
577 assert(cache != (Cache) NULL);
579 assert(cache_info->signature == MagickCoreSignature);
580 source_info->methods=cache_info->methods;
612static MagickBooleanType ClonePixelCacheOnDisk(
634 if ((OpenPixelCacheOnDisk(cache_info,ReadMode,exception) == MagickFalse) ||
635 (OpenPixelCacheOnDisk(clone_info,IOMode,exception) == MagickFalse))
637 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
638 (lseek(clone_info->file,0,SEEK_SET) < 0))
640 quantum=(size_t) MagickMaxBufferExtent;
641 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
643#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
644 if (cache_info->length < 0x7ffff000)
648 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
649 (
size_t) cache_info->length);
650 }
while ((count < 0) && (errno == EINTR));
651 if (count == (ssize_t) cache_info->length)
655 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
656 (lseek(clone_info->file,0,SEEK_SET) < 0))
660 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
662 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
663 if (buffer == (
unsigned char *) NULL)
666 while (extent < cache_info->length)
671 length=(size_t) MagickMin((MagickSizeType) quantum,cache_info->length-
673 count=MagickRead(cache_info->file,buffer,length);
676 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
684 while (offset < count)
686 number_bytes=MagickWrite(clone_info->file,buffer+offset,(
size_t) (count-
688 if (number_bytes <= 0)
690 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
693 offset+=number_bytes;
695 extent+=(MagickSizeType) offset;
698 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
699 return(extent == cache_info->length ? MagickTrue : MagickFalse);
702#if defined(MAGICKCORE_OPENMP_SUPPORT)
703static inline int GetCacheNumberThreads(
const CacheInfo *source,
704 const CacheInfo *destination,
const size_t chunk,
const int factor)
707 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
708 number_threads = 1UL,
709 workload_factor = 64UL << factor;
714 number_threads=(chunk <= workload_factor) ? 1UL :
715 (chunk >= (workload_factor << 6)) ? max_threads :
716 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
720 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
721 ((destination->type != MemoryCache) && (destination->type != MapCache)))
722 number_threads=MagickMin(number_threads,4);
723 return((
int) number_threads);
727static MagickBooleanType ClonePixelCacheRepository(
731#define cache_number_threads(source,destination,chunk,factor) \
732 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
739 **magick_restrict cache_nexus,
740 **magick_restrict clone_nexus;
748 assert(cache_info != (
CacheInfo *) NULL);
749 assert(clone_info != (
CacheInfo *) NULL);
751 if (cache_info->type == PingCache)
753 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
754 if ((cache_info->storage_class == clone_info->storage_class) &&
755 (cache_info->colorspace == clone_info->colorspace) &&
756 (cache_info->alpha_trait == clone_info->alpha_trait) &&
757 (cache_info->channels == clone_info->channels) &&
758 (cache_info->columns == clone_info->columns) &&
759 (cache_info->rows == clone_info->rows) &&
760 (cache_info->number_channels == clone_info->number_channels) &&
761 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
762 (cache_info->metacontent_extent == clone_info->metacontent_extent))
767 if (((cache_info->type == MemoryCache) ||
768 (cache_info->type == MapCache)) &&
769 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
771 (void) memcpy(clone_info->pixels,cache_info->pixels,
772 cache_info->number_channels*cache_info->columns*cache_info->rows*
773 sizeof(*cache_info->pixels));
774 if ((cache_info->metacontent_extent != 0) &&
775 (clone_info->metacontent_extent != 0))
776 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
777 cache_info->columns*cache_info->rows*
778 clone_info->metacontent_extent*
sizeof(
unsigned char));
781 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
782 return(ClonePixelCacheOnDisk(cache_info,clone_info,exception));
787 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
788 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
789 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
790 optimize=(cache_info->number_channels == clone_info->number_channels) &&
791 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
792 MagickTrue : MagickFalse;
793 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
794 clone_info->number_channels*clone_info->columns);
796#if defined(MAGICKCORE_OPENMP_SUPPORT)
797 #pragma omp parallel for schedule(static) shared(status) \
798 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
800 for (y=0; y < (ssize_t) cache_info->rows; y++)
803 id = GetOpenMPThreadId();
811 if (status == MagickFalse)
813 if (y >= (ssize_t) clone_info->rows)
815 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
816 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
817 if (pixels == (Quantum *) NULL)
819 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
820 if (status == MagickFalse)
822 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
823 clone_info->columns,1,MagickTrue,clone_nexus[
id],exception);
824 if (pixels == (Quantum *) NULL)
826 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
827 if (optimize != MagickFalse)
828 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
841 p=cache_nexus[id]->pixels;
842 q=clone_nexus[id]->pixels;
843 for (x=0; x < (ssize_t) cache_info->columns; x++)
848 if (x == (ssize_t) clone_info->columns)
850 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
858 channel=clone_info->channel_map[i].channel;
859 traits=cache_info->channel_map[channel].traits;
860 if (traits != UndefinedPixelTrait)
861 *q=(*(p+cache_info->channel_map[channel].offset));
864 p+=(ptrdiff_t) cache_info->number_channels;
867 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
869 if ((cache_info->metacontent_extent != 0) &&
870 (clone_info->metacontent_extent != 0))
875 length=(size_t) MagickMin(cache_info->metacontent_extent,
876 clone_info->metacontent_extent);
877#if defined(MAGICKCORE_OPENMP_SUPPORT)
878 #pragma omp parallel for schedule(static) shared(status) \
879 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
881 for (y=0; y < (ssize_t) cache_info->rows; y++)
884 id = GetOpenMPThreadId();
889 if (status == MagickFalse)
891 if (y >= (ssize_t) clone_info->rows)
893 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
894 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
895 if (pixels == (Quantum *) NULL)
897 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
898 if (status == MagickFalse)
900 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
901 clone_info->columns,1,MagickTrue,clone_nexus[
id],exception);
902 if (pixels == (Quantum *) NULL)
904 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
905 (cache_nexus[
id]->metacontent != (
void *) NULL))
906 (void) memcpy(clone_nexus[
id]->metacontent,
907 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
908 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
911 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
912 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
913 if (cache_info->debug != MagickFalse)
916 message[MagickPathExtent];
918 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
919 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
920 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
921 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
948static void DestroyImagePixelCache(
Image *image)
950 assert(image != (
Image *) NULL);
951 assert(image->signature == MagickCoreSignature);
952 if (IsEventLogging() != MagickFalse)
953 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
954 if (image->cache != (
void *) NULL)
955 image->cache=DestroyPixelCache(image->cache);
980MagickExport
void DestroyImagePixels(
Image *image)
983 *magick_restrict cache_info;
985 assert(image != (
const Image *) NULL);
986 assert(image->signature == MagickCoreSignature);
987 if (IsEventLogging() != MagickFalse)
988 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
989 if (image->cache == (Cache) NULL)
992 assert(cache_info->signature == MagickCoreSignature);
993 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
995 cache_info->methods.destroy_pixel_handler(image);
998 image->cache=DestroyPixelCache(image->cache);
1024static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1030 if (cache_info->file != -1)
1032 status=close_utf8(cache_info->file);
1033 cache_info->file=(-1);
1034 RelinquishMagickResource(FileResource,1);
1036 return(status == -1 ? MagickFalse : MagickTrue);
1039static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1041 switch (cache_info->type)
1045 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1046#if defined(MAGICKCORE_OPENCL_SUPPORT)
1047 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1049 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1051 cache_info->pixels=(Quantum *) NULL;
1055 if (cache_info->mapped == MagickFalse)
1056 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1057 cache_info->pixels);
1060 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1061 cache_info->pixels=(Quantum *) NULL;
1063 RelinquishMagickResource(MemoryResource,cache_info->length);
1068 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1069 cache_info->pixels=(Quantum *) NULL;
1070 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1071 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1072 *cache_info->cache_filename=
'\0';
1073 RelinquishMagickResource(MapResource,cache_info->length);
1078 if (cache_info->file != -1)
1079 (void) ClosePixelCacheOnDisk(cache_info);
1080 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1081 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1082 *cache_info->cache_filename=
'\0';
1083 RelinquishMagickResource(DiskResource,cache_info->length);
1086 case DistributedCache:
1088 *cache_info->cache_filename=
'\0';
1090 cache_info->server_info);
1096 cache_info->type=UndefinedCache;
1097 cache_info->mapped=MagickFalse;
1098 cache_info->metacontent=(
void *) NULL;
1101MagickPrivate Cache DestroyPixelCache(Cache cache)
1104 *magick_restrict cache_info;
1106 assert(cache != (Cache) NULL);
1108 assert(cache_info->signature == MagickCoreSignature);
1109 if (IsEventLogging() != MagickFalse)
1110 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1111 cache_info->filename);
1112 LockSemaphoreInfo(cache_info->semaphore);
1113 cache_info->reference_count--;
1114 if (cache_info->reference_count != 0)
1116 UnlockSemaphoreInfo(cache_info->semaphore);
1117 return((Cache) NULL);
1119 UnlockSemaphoreInfo(cache_info->semaphore);
1120 if (cache_info->debug != MagickFalse)
1123 message[MagickPathExtent];
1125 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1126 cache_info->filename);
1127 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1129 RelinquishPixelCachePixels(cache_info);
1132 cache_info->server_info);
1133 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1134 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1135 cache_info->number_threads);
1136 if (cache_info->random_info != (
RandomInfo *) NULL)
1137 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1139 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1141 RelinquishSemaphoreInfo(&cache_info->semaphore);
1142 cache_info->signature=(~MagickCoreSignature);
1143 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1174static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1176 if (nexus_info->mapped == MagickFalse)
1177 (void) RelinquishAlignedMemory(nexus_info->cache);
1179 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1180 nexus_info->cache=(Quantum *) NULL;
1181 nexus_info->pixels=(Quantum *) NULL;
1182 nexus_info->metacontent=(
void *) NULL;
1183 nexus_info->length=0;
1184 nexus_info->mapped=MagickFalse;
1188 const size_t number_threads)
1193 assert(nexus_info != (
NexusInfo **) NULL);
1194 for (i=0; i < (ssize_t) (2*number_threads); i++)
1196 if (nexus_info[i]->cache != (Quantum *) NULL)
1197 RelinquishCacheNexusPixels(nexus_info[i]);
1198 nexus_info[i]->signature=(~MagickCoreSignature);
1200 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1201 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1230MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1233 *magick_restrict cache_info;
1236 id = GetOpenMPThreadId();
1238 assert(image != (
const Image *) NULL);
1239 assert(image->signature == MagickCoreSignature);
1240 assert(image->cache != (Cache) NULL);
1242 assert(cache_info->signature == MagickCoreSignature);
1243 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1244 (GetAuthenticMetacontentFromHandler) NULL)
1249 metacontent=cache_info->methods.
1250 get_authentic_metacontent_from_handler(image);
1251 return(metacontent);
1253 assert(
id < (
int) cache_info->number_threads);
1254 return(cache_info->nexus_info[
id]->metacontent);
1281static void *GetAuthenticMetacontentFromCache(
const Image *image)
1284 *magick_restrict cache_info;
1287 id = GetOpenMPThreadId();
1289 assert(image != (
const Image *) NULL);
1290 assert(image->signature == MagickCoreSignature);
1291 assert(image->cache != (Cache) NULL);
1293 assert(cache_info->signature == MagickCoreSignature);
1294 assert(
id < (
int) cache_info->number_threads);
1295 return(cache_info->nexus_info[
id]->metacontent);
1298#if defined(MAGICKCORE_OPENCL_SUPPORT)
1327MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1331 *magick_restrict cache_info;
1333 assert(image != (
const Image *) NULL);
1334 assert(device != (
const MagickCLDevice) NULL);
1336 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1338 (void) SyncImagePixelCache((
Image *) image,exception);
1341 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1342 return((cl_mem) NULL);
1343 LockSemaphoreInfo(cache_info->semaphore);
1344 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1345 (cache_info->opencl->device->context != device->context))
1346 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1347 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1349 assert(cache_info->pixels != (Quantum *) NULL);
1350 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1351 cache_info->length);
1353 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1354 RetainOpenCLMemObject(cache_info->opencl->buffer);
1355 UnlockSemaphoreInfo(cache_info->semaphore);
1356 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1357 return((cl_mem) NULL);
1358 assert(cache_info->opencl->pixels == cache_info->pixels);
1359 return(cache_info->opencl->buffer);
1398MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1399 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1403 *magick_restrict cache_info;
1406 *magick_restrict pixels;
1411 assert(image != (
Image *) NULL);
1412 assert(image->signature == MagickCoreSignature);
1413 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1414 nexus_info,exception);
1415 if (pixels == (Quantum *) NULL)
1416 return((Quantum *) NULL);
1418 assert(cache_info->signature == MagickCoreSignature);
1419 if (nexus_info->authentic_pixel_cache != MagickFalse)
1421 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1422 return((Quantum *) NULL);
1423 if (cache_info->metacontent_extent != 0)
1424 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1425 return((Quantum *) NULL);
1452static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1455 *magick_restrict cache_info;
1458 id = GetOpenMPThreadId();
1460 assert(image != (
const Image *) NULL);
1461 assert(image->signature == MagickCoreSignature);
1462 assert(image->cache != (Cache) NULL);
1464 assert(cache_info->signature == MagickCoreSignature);
1465 assert(
id < (
int) cache_info->number_threads);
1466 return(cache_info->nexus_info[
id]->pixels);
1493MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1496 *magick_restrict cache_info;
1499 id = GetOpenMPThreadId();
1501 assert(image != (
const Image *) NULL);
1502 assert(image->signature == MagickCoreSignature);
1503 assert(image->cache != (Cache) NULL);
1505 assert(cache_info->signature == MagickCoreSignature);
1506 if (cache_info->methods.get_authentic_pixels_from_handler !=
1507 (GetAuthenticPixelsFromHandler) NULL)
1508 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1509 assert(
id < (
int) cache_info->number_threads);
1510 return(cache_info->nexus_info[
id]->pixels);
1558MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1559 const ssize_t y,
const size_t columns,
const size_t rows,
1563 *magick_restrict cache_info;
1566 id = GetOpenMPThreadId();
1571 assert(image != (
Image *) NULL);
1572 assert(image->signature == MagickCoreSignature);
1573 assert(image->cache != (Cache) NULL);
1575 assert(cache_info->signature == MagickCoreSignature);
1576 if (cache_info->methods.get_authentic_pixels_handler !=
1577 (GetAuthenticPixelsHandler) NULL)
1579 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1583 assert(
id < (
int) cache_info->number_threads);
1584 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1585 cache_info->nexus_info[
id],exception);
1620static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1621 const ssize_t y,
const size_t columns,
const size_t rows,
1625 *magick_restrict cache_info;
1628 id = GetOpenMPThreadId();
1631 *magick_restrict pixels;
1633 assert(image != (
const Image *) NULL);
1634 assert(image->signature == MagickCoreSignature);
1635 assert(image->cache != (Cache) NULL);
1637 if (cache_info == (Cache) NULL)
1638 return((Quantum *) NULL);
1639 assert(cache_info->signature == MagickCoreSignature);
1640 assert(
id < (
int) cache_info->number_threads);
1641 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1642 cache_info->nexus_info[
id],exception);
1669MagickExport MagickSizeType GetImageExtent(
const Image *image)
1672 *magick_restrict cache_info;
1675 id = GetOpenMPThreadId();
1677 assert(image != (
Image *) NULL);
1678 assert(image->signature == MagickCoreSignature);
1679 if (IsEventLogging() != MagickFalse)
1680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1681 assert(image->cache != (Cache) NULL);
1683 assert(cache_info->signature == MagickCoreSignature);
1684 assert(
id < (
int) cache_info->number_threads);
1685 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1718static MagickBooleanType GetDynamicThrottlePolicy(
void)
1720 static MagickBooleanType
1721 check_policy = MagickTrue;
1723 static MagickBooleanType
1724 dynamic_throttle = MagickFalse;
1726 if (check_policy != MagickFalse)
1728 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1729 if (value != (
char *) NULL)
1731 dynamic_throttle=IsStringTrue(value);
1732 value=DestroyString(value);
1734 check_policy=MagickFalse;
1736 return(dynamic_throttle);
1739static inline MagickBooleanType ValidatePixelCacheMorphology(
1740 const Image *magick_restrict image)
1743 *magick_restrict cache_info;
1753 p=image->channel_map;
1754 q=cache_info->channel_map;
1755 if ((image->storage_class != cache_info->storage_class) ||
1756 (image->colorspace != cache_info->colorspace) ||
1757 (image->alpha_trait != cache_info->alpha_trait) ||
1758 (image->channels != cache_info->channels) ||
1759 (image->columns != cache_info->columns) ||
1760 (image->rows != cache_info->rows) ||
1761 (image->number_channels != cache_info->number_channels) ||
1762 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1763 (image->metacontent_extent != cache_info->metacontent_extent) ||
1764 (cache_info->nexus_info == (
NexusInfo **) NULL))
1765 return(MagickFalse);
1769static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1773 *magick_restrict cache_info;
1777 status = MagickTrue;
1779 static MagickSizeType
1780 cpu_throttle = MagickResourceInfinity,
1783 if (IsImageTTLExpired(image) != MagickFalse)
1788 (void) ThrowMagickException(exception,GetMagickModule(),
1789 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1790 return((Cache) NULL);
1792 if (cpu_throttle == MagickResourceInfinity)
1793 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1794 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1807#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1808 if (getloadavg(&load_average,1) != 1)
1811 load=MagickMax(load_average-(
double) GetOpenMPMaximumThreads(),0.0);
1812 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1814 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1815 MagickDelay(cpu_throttle);
1817 LockSemaphoreInfo(image->semaphore);
1818 assert(image->cache != (Cache) NULL);
1820#if defined(MAGICKCORE_OPENCL_SUPPORT)
1821 CopyOpenCLBuffer(cache_info);
1823 destroy=MagickFalse;
1824 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1826 LockSemaphoreInfo(cache_info->semaphore);
1827 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1838 clone_image=(*image);
1839 clone_image.semaphore=AcquireSemaphoreInfo();
1840 clone_image.reference_count=1;
1841 clone_image.cache=ClonePixelCache(cache_info);
1842 clone_info=(
CacheInfo *) clone_image.cache;
1843 status=OpenPixelCache(&clone_image,IOMode,exception);
1844 if (status == MagickFalse)
1845 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1848 if (clone != MagickFalse)
1849 status=ClonePixelCacheRepository(clone_info,cache_info,
1851 if (status == MagickFalse)
1852 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1856 image->cache=clone_info;
1859 RelinquishSemaphoreInfo(&clone_image.semaphore);
1861 UnlockSemaphoreInfo(cache_info->semaphore);
1863 if (destroy != MagickFalse)
1864 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1865 if (status != MagickFalse)
1870 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1872 image->type=UndefinedType;
1873 status=OpenPixelCache(image,IOMode,exception);
1875 if (cache_info->file != -1)
1876 (void) ClosePixelCacheOnDisk(cache_info);
1879 UnlockSemaphoreInfo(image->semaphore);
1880 if (status == MagickFalse)
1881 return((Cache) NULL);
1882 return(image->cache);
1908MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1911 *magick_restrict cache_info;
1913 assert(image != (
Image *) NULL);
1914 assert(image->signature == MagickCoreSignature);
1915 assert(image->cache != (Cache) NULL);
1917 assert(cache_info->signature == MagickCoreSignature);
1918 return(cache_info->type);
1952static inline MagickBooleanType CopyPixel(
const Image *image,
1953 const Quantum *source,Quantum *destination)
1958 if (source == (
const Quantum *) NULL)
1960 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1961 destination[GreenPixelChannel]=ClampToQuantum(
1962 image->background_color.green);
1963 destination[BluePixelChannel]=ClampToQuantum(
1964 image->background_color.blue);
1965 destination[BlackPixelChannel]=ClampToQuantum(
1966 image->background_color.black);
1967 destination[AlphaPixelChannel]=ClampToQuantum(
1968 image->background_color.alpha);
1969 return(MagickFalse);
1971 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1973 PixelChannel channel = GetPixelChannelChannel(image,i);
1974 destination[channel]=source[i];
1979MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1980 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1983 *magick_restrict cache_info;
1988 assert(image != (
Image *) NULL);
1989 assert(image->signature == MagickCoreSignature);
1990 assert(image->cache != (Cache) NULL);
1992 assert(cache_info->signature == MagickCoreSignature);
1993 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1994 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1995 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1996 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1997 return(CopyPixel(image,q,pixel));
2031static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2032 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2035 *magick_restrict cache_info;
2038 id = GetOpenMPThreadId();
2043 assert(image != (
const Image *) NULL);
2044 assert(image->signature == MagickCoreSignature);
2045 assert(image->cache != (Cache) NULL);
2047 assert(cache_info->signature == MagickCoreSignature);
2048 assert(
id < (
int) cache_info->number_threads);
2049 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2050 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2052 return(CopyPixel(image,q,pixel));
2086MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2087 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2090 *magick_restrict cache_info;
2093 id = GetOpenMPThreadId();
2098 assert(image != (
const Image *) NULL);
2099 assert(image->signature == MagickCoreSignature);
2100 assert(image->cache != (Cache) NULL);
2102 assert(cache_info->signature == MagickCoreSignature);
2103 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2104 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2105 (GetOneVirtualPixelFromHandler) NULL)
2106 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2107 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2108 assert(
id < (
int) cache_info->number_threads);
2109 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2110 1UL,1UL,cache_info->nexus_info[
id],exception);
2111 return(CopyPixel(image,p,pixel));
2148static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2149 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2153 *magick_restrict cache_info;
2156 id = GetOpenMPThreadId();
2161 assert(image != (
const Image *) NULL);
2162 assert(image->signature == MagickCoreSignature);
2163 assert(image->cache != (Cache) NULL);
2165 assert(cache_info->signature == MagickCoreSignature);
2166 assert(
id < (
int) cache_info->number_threads);
2167 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2168 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2169 cache_info->nexus_info[
id],exception);
2170 return(CopyPixel(image,p,pixel));
2207MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2208 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2212 *magick_restrict cache_info;
2215 id = GetOpenMPThreadId();
2220 assert(image != (
const Image *) NULL);
2221 assert(image->signature == MagickCoreSignature);
2222 assert(image->cache != (Cache) NULL);
2224 assert(cache_info->signature == MagickCoreSignature);
2225 assert(
id < (
int) cache_info->number_threads);
2226 GetPixelInfo(image,pixel);
2227 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2228 cache_info->nexus_info[
id],exception);
2229 if (p == (
const Quantum *) NULL)
2230 return(MagickFalse);
2231 GetPixelInfoPixel(image,p,pixel);
2257MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2260 *magick_restrict cache_info;
2262 assert(cache != (Cache) NULL);
2264 assert(cache_info->signature == MagickCoreSignature);
2265 if (IsEventLogging() != MagickFalse)
2266 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2267 cache_info->filename);
2268 return(cache_info->colorspace);
2294MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2297 *magick_restrict cache_info;
2299 assert(image != (
const Image *) NULL);
2300 assert(image->signature == MagickCoreSignature);
2301 assert(image->cache != (Cache) NULL);
2303 assert(cache_info->signature == MagickCoreSignature);
2304 return(cache_info->cache_filename);
2329MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2332 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2333 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2334 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2335 cache_methods->get_virtual_metacontent_from_handler=
2336 GetVirtualMetacontentFromCache;
2337 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2338 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2339 cache_methods->get_authentic_metacontent_from_handler=
2340 GetAuthenticMetacontentFromCache;
2341 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2342 cache_methods->get_one_authentic_pixel_from_handler=
2343 GetOneAuthenticPixelFromCache;
2344 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2345 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2346 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2374MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2378 *magick_restrict cache_info;
2383 assert(cache != NULL);
2385 assert(cache_info->signature == MagickCoreSignature);
2386 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2388 return((MagickSizeType) cache_info->columns*cache_info->rows);
2419MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2423 *magick_restrict cache_info;
2425 assert(image != (
const Image *) NULL);
2426 assert(image->signature == MagickCoreSignature);
2427 assert(image->cache != (Cache) NULL);
2428 assert(length != (MagickSizeType *) NULL);
2429 magick_unreferenced(exception);
2431 assert(cache_info->signature == MagickCoreSignature);
2432 *length=cache_info->length;
2433 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2434 return((
void *) NULL);
2435 return((
void *) cache_info->pixels);
2462MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2465 *magick_restrict cache_info;
2467 assert(cache != (Cache) NULL);
2469 assert(cache_info->signature == MagickCoreSignature);
2470 if (IsEventLogging() != MagickFalse)
2471 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2472 cache_info->filename);
2473 return(cache_info->storage_class);
2503MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2507 *magick_restrict cache_info;
2509 assert(image != (
Image *) NULL);
2510 assert(image->signature == MagickCoreSignature);
2511 if (IsEventLogging() != MagickFalse)
2512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2514 assert(cache_info->signature == MagickCoreSignature);
2515 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2516 if (GetImagePixelCacheType(image) == DiskCache)
2517 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2545MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2548 *magick_restrict cache_info;
2550 assert(image != (
Image *) NULL);
2551 assert(image->signature == MagickCoreSignature);
2552 assert(image->cache != (Cache) NULL);
2554 assert(cache_info->signature == MagickCoreSignature);
2555 return(cache_info->virtual_pixel_method);
2581static const void *GetVirtualMetacontentFromCache(
const Image *image)
2584 *magick_restrict cache_info;
2587 id = GetOpenMPThreadId();
2590 *magick_restrict metacontent;
2592 assert(image != (
const Image *) NULL);
2593 assert(image->signature == MagickCoreSignature);
2594 assert(image->cache != (Cache) NULL);
2596 assert(cache_info->signature == MagickCoreSignature);
2597 assert(
id < (
int) cache_info->number_threads);
2598 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2599 cache_info->nexus_info[
id]);
2600 return(metacontent);
2629MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2633 *magick_restrict cache_info;
2635 assert(cache != (Cache) NULL);
2637 assert(cache_info->signature == MagickCoreSignature);
2638 if (cache_info->storage_class == UndefinedClass)
2639 return((
void *) NULL);
2640 return(nexus_info->metacontent);
2667MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2670 *magick_restrict cache_info;
2673 id = GetOpenMPThreadId();
2676 *magick_restrict metacontent;
2678 assert(image != (
const Image *) NULL);
2679 assert(image->signature == MagickCoreSignature);
2680 assert(image->cache != (Cache) NULL);
2682 assert(cache_info->signature == MagickCoreSignature);
2683 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2685 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2687 if (metacontent != (
const void *) NULL)
2688 return(metacontent);
2690 assert(
id < (
int) cache_info->number_threads);
2691 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2692 cache_info->nexus_info[
id]);
2693 return(metacontent);
2736 0, 48, 12, 60, 3, 51, 15, 63,
2737 32, 16, 44, 28, 35, 19, 47, 31,
2738 8, 56, 4, 52, 11, 59, 7, 55,
2739 40, 24, 36, 20, 43, 27, 39, 23,
2740 2, 50, 14, 62, 1, 49, 13, 61,
2741 34, 18, 46, 30, 33, 17, 45, 29,
2742 10, 58, 6, 54, 9, 57, 5, 53,
2743 42, 26, 38, 22, 41, 25, 37, 21
2746static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2751 index=x+DitherMatrix[x & 0x07]-32L;
2754 if (index >= (ssize_t) columns)
2755 return((ssize_t) columns-1L);
2759static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2764 index=y+DitherMatrix[y & 0x07]-32L;
2767 if (index >= (ssize_t) rows)
2768 return((ssize_t) rows-1L);
2772static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2776 if (x >= (ssize_t) columns)
2777 return((ssize_t) (columns-1));
2781static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2785 if (y >= (ssize_t) rows)
2786 return((ssize_t) (rows-1));
2790static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2791 const MagickOffsetType y)
2793 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2794 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2795 return(MagickFalse);
2799static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2804 x=(double) columns*GetPseudoRandomValue(random_info);
2805 return(CastDoubleToSsizeT(x));
2808static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2813 y=(double) rows*GetPseudoRandomValue(random_info);
2814 return(CastDoubleToSsizeT(y));
2817static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2818 const size_t extent)
2823 modulo.quotient=offset;
2827 modulo.quotient=offset/((ssize_t) extent);
2828 modulo.remainder=offset % ((ssize_t) extent);
2830 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2833 modulo.remainder+=((ssize_t) extent);
2838MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2839 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2840 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2844 *magick_restrict cache_info;
2860 *magick_restrict virtual_nexus;
2863 *magick_restrict pixels,
2865 virtual_pixel[MaxPixelChannels];
2876 *magick_restrict virtual_metacontent;
2881 assert(image != (
const Image *) NULL);
2882 assert(image->signature == MagickCoreSignature);
2883 assert(image->cache != (Cache) NULL);
2885 assert(cache_info->signature == MagickCoreSignature);
2886 if (cache_info->type == UndefinedCache)
2887 return((
const Quantum *) NULL);
2888#if defined(MAGICKCORE_OPENCL_SUPPORT)
2889 CopyOpenCLBuffer(cache_info);
2891 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2892 ((image->channels & WriteMaskChannel) != 0) ||
2893 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2894 nexus_info,exception);
2895 if (pixels == (Quantum *) NULL)
2896 return((
const Quantum *) NULL);
2897 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2898 return((
const Quantum *) NULL);
2899 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2900 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2901 return((
const Quantum *) NULL);
2902 offset+=nexus_info->region.x;
2903 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2904 nexus_info->region.width-1L;
2905 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2906 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2907 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2908 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2916 if (nexus_info->authentic_pixel_cache != MagickFalse)
2918 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2919 if (status == MagickFalse)
2920 return((
const Quantum *) NULL);
2921 if (cache_info->metacontent_extent != 0)
2923 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2924 if (status == MagickFalse)
2925 return((
const Quantum *) NULL);
2932 virtual_nexus=nexus_info->virtual_nexus;
2934 s=(
unsigned char *) nexus_info->metacontent;
2935 (void) memset(virtual_pixel,0,cache_info->number_channels*
2936 sizeof(*virtual_pixel));
2937 virtual_metacontent=(
void *) NULL;
2938 switch (virtual_pixel_method)
2940 case BackgroundVirtualPixelMethod:
2941 case BlackVirtualPixelMethod:
2942 case GrayVirtualPixelMethod:
2943 case TransparentVirtualPixelMethod:
2944 case MaskVirtualPixelMethod:
2945 case WhiteVirtualPixelMethod:
2946 case EdgeVirtualPixelMethod:
2947 case CheckerTileVirtualPixelMethod:
2948 case HorizontalTileVirtualPixelMethod:
2949 case VerticalTileVirtualPixelMethod:
2951 if (cache_info->metacontent_extent != 0)
2956 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2957 cache_info->metacontent_extent);
2958 if (virtual_metacontent == (
void *) NULL)
2960 (void) ThrowMagickException(exception,GetMagickModule(),
2961 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2962 return((
const Quantum *) NULL);
2964 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2966 switch (virtual_pixel_method)
2968 case BlackVirtualPixelMethod:
2970 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2971 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2972 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2975 case GrayVirtualPixelMethod:
2977 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2978 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2980 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2983 case TransparentVirtualPixelMethod:
2985 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2986 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2987 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2990 case MaskVirtualPixelMethod:
2991 case WhiteVirtualPixelMethod:
2993 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2994 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2995 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
3000 SetPixelRed(image,ClampToQuantum(image->background_color.red),
3002 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
3004 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
3006 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
3008 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3018 for (v=0; v < (ssize_t) rows; v++)
3024 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3025 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3026 y_offset=EdgeY(y_offset,cache_info->rows);
3027 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3033 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
3034 x_offset,(ssize_t) columns-u);
3035 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3036 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3046 length=(MagickSizeType) 1;
3047 switch (virtual_pixel_method)
3049 case EdgeVirtualPixelMethod:
3052 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3053 EdgeX(x_offset,cache_info->columns),
3054 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3056 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3059 case RandomVirtualPixelMethod:
3061 if (cache_info->random_info == (
RandomInfo *) NULL)
3062 cache_info->random_info=AcquireRandomInfo();
3063 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3064 RandomX(cache_info->random_info,cache_info->columns),
3065 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3066 virtual_nexus,exception);
3067 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3070 case DitherVirtualPixelMethod:
3072 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3073 DitherX(x_offset,cache_info->columns),
3074 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3076 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3079 case TileVirtualPixelMethod:
3081 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3082 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3083 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3084 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3086 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3089 case MirrorVirtualPixelMethod:
3091 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3092 if ((x_modulo.quotient & 0x01) == 1L)
3093 x_modulo.remainder=(ssize_t) cache_info->columns-
3094 x_modulo.remainder-1L;
3095 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3096 if ((y_modulo.quotient & 0x01) == 1L)
3097 y_modulo.remainder=(ssize_t) cache_info->rows-
3098 y_modulo.remainder-1L;
3099 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3100 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3102 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3105 case HorizontalTileEdgeVirtualPixelMethod:
3107 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3108 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3109 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3110 virtual_nexus,exception);
3111 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3114 case VerticalTileEdgeVirtualPixelMethod:
3116 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3117 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3118 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3119 virtual_nexus,exception);
3120 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3123 case BackgroundVirtualPixelMethod:
3124 case BlackVirtualPixelMethod:
3125 case GrayVirtualPixelMethod:
3126 case TransparentVirtualPixelMethod:
3127 case MaskVirtualPixelMethod:
3128 case WhiteVirtualPixelMethod:
3131 r=virtual_metacontent;
3134 case CheckerTileVirtualPixelMethod:
3136 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3137 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3138 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3141 r=virtual_metacontent;
3144 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3145 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3147 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3150 case HorizontalTileVirtualPixelMethod:
3152 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3155 r=virtual_metacontent;
3158 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3159 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3160 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3161 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3163 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3166 case VerticalTileVirtualPixelMethod:
3168 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3171 r=virtual_metacontent;
3174 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3175 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3176 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3177 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3179 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3183 if (p == (
const Quantum *) NULL)
3185 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3187 q+=(ptrdiff_t) cache_info->number_channels;
3188 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3190 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3191 s+=(ptrdiff_t) cache_info->metacontent_extent;
3198 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3199 (
size_t) length,1UL,virtual_nexus,exception);
3200 if (p == (
const Quantum *) NULL)
3202 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3203 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3205 q+=(ptrdiff_t) (cache_info->number_channels*length);
3206 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3208 (void) memcpy(s,r,(
size_t) length);
3209 s+=(ptrdiff_t) (length*cache_info->metacontent_extent);
3212 if (u < (ssize_t) columns)
3218 if (virtual_metacontent != (
void *) NULL)
3219 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3220 if (v < (ssize_t) rows)
3221 return((
const Quantum *) NULL);
3259static const Quantum *GetVirtualPixelCache(
const Image *image,
3260 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3261 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3264 *magick_restrict cache_info;
3267 id = GetOpenMPThreadId();
3272 assert(image != (
const Image *) NULL);
3273 assert(image->signature == MagickCoreSignature);
3274 assert(image->cache != (Cache) NULL);
3276 assert(cache_info->signature == MagickCoreSignature);
3277 assert(
id < (
int) cache_info->number_threads);
3278 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3279 cache_info->nexus_info[
id],exception);
3306MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3309 *magick_restrict cache_info;
3312 id = GetOpenMPThreadId();
3314 assert(image != (
const Image *) NULL);
3315 assert(image->signature == MagickCoreSignature);
3316 assert(image->cache != (Cache) NULL);
3318 assert(cache_info->signature == MagickCoreSignature);
3319 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3320 return(cache_info->methods.get_virtual_pixels_handler(image));
3321 assert(
id < (
int) cache_info->number_threads);
3322 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3373MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3374 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3378 *magick_restrict cache_info;
3381 id = GetOpenMPThreadId();
3386 assert(image != (
const Image *) NULL);
3387 assert(image->signature == MagickCoreSignature);
3388 assert(image->cache != (Cache) NULL);
3390 assert(cache_info->signature == MagickCoreSignature);
3391 if (cache_info->methods.get_virtual_pixel_handler !=
3392 (GetVirtualPixelHandler) NULL)
3393 return(cache_info->methods.get_virtual_pixel_handler(image,
3394 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3395 assert(
id < (
int) cache_info->number_threads);
3396 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3397 columns,rows,cache_info->nexus_info[
id],exception);
3424static const Quantum *GetVirtualPixelsCache(
const Image *image)
3427 *magick_restrict cache_info;
3430 id = GetOpenMPThreadId();
3432 assert(image != (
const Image *) NULL);
3433 assert(image->signature == MagickCoreSignature);
3434 assert(image->cache != (Cache) NULL);
3436 assert(cache_info->signature == MagickCoreSignature);
3437 assert(
id < (
int) cache_info->number_threads);
3438 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3467MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3471 *magick_restrict cache_info;
3473 assert(cache != (Cache) NULL);
3475 assert(cache_info->signature == MagickCoreSignature);
3476 if (cache_info->storage_class == UndefinedClass)
3477 return((Quantum *) NULL);
3478 return((
const Quantum *) nexus_info->pixels);
3511static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3512 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3517 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3519 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3520 gamma=MagickSafeReciprocal(gamma);
3521 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3524static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3528 *magick_restrict cache_info;
3540 if (IsEventLogging() != MagickFalse)
3541 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3542 if ((image->channels & CompositeMaskChannel) == 0)
3544 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3547 if (cache_info == (Cache) NULL)
3548 return(MagickFalse);
3549 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3550 nexus_info->region.width,nexus_info->region.height,
3551 nexus_info->virtual_nexus,exception);
3552 q=nexus_info->pixels;
3553 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3554 return(MagickFalse);
3555 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3560 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3568 alpha=(double) GetPixelCompositeMask(image,p);
3569 for (i=0; i < (ssize_t) image->number_channels; i++)
3571 PixelChannel channel = GetPixelChannelChannel(image,i);
3572 PixelTrait traits = GetPixelChannelTraits(image,channel);
3573 if ((traits & UpdatePixelTrait) == 0)
3575 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3577 p+=(ptrdiff_t) GetPixelChannels(image);
3578 q+=(ptrdiff_t) GetPixelChannels(image);
3615static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3616 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3621 if ((count == 0) || (quantum == 0))
3623 length=count*quantum;
3624 if (quantum != (length/count))
3631 return(MagickFalse);
3634static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3643 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3645 if (*cache_info->cache_filename ==
'\0')
3646 file=AcquireUniqueFileResource(cache_info->cache_filename);
3652 if (IsPathAuthorized(ReadPolicyRights,cache_info->cache_filename) == MagickFalse)
3655 ThrowFileException(exception,OptionWarning,
"NotAuthorized",
3656 cache_info->cache_filename);
3657 return(MagickFalse);
3659 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_CLOEXEC |
3665 if (IsPathAuthorized(WritePolicyRights,cache_info->cache_filename) == MagickFalse)
3668 ThrowFileException(exception,OptionWarning,
"NotAuthorized",
3669 cache_info->cache_filename);
3670 return(MagickFalse);
3672 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CLOEXEC |
3673 O_CREAT | O_BINARY | O_EXCL,S_MODE);
3675 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CLOEXEC |
3682 if ((IsPathAuthorized(ReadPolicyRights,cache_info->cache_filename) == MagickFalse) ||
3683 (IsPathAuthorized(WritePolicyRights,cache_info->cache_filename) == MagickFalse))
3686 ThrowFileException(exception,OptionWarning,
"NotAuthorized",
3687 cache_info->cache_filename);
3688 return(MagickFalse);
3690 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CLOEXEC |
3691 O_CREAT | O_BINARY | O_EXCL,S_MODE);
3693 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CLOEXEC |
3699 return(MagickFalse);
3700 (void) AcquireMagickResource(FileResource,1);
3701 if (cache_info->file != -1)
3702 (void) ClosePixelCacheOnDisk(cache_info);
3703 cache_info->file=file;
3704 cache_info->disk_mode=mode;
3708static inline MagickOffsetType WritePixelCacheRegion(
3709 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3710 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3718 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3719 return((MagickOffsetType) -1);
3720 for (i=0; i < (MagickOffsetType) length; i+=count)
3722 count=MagickWrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3723 (MagickSizeType) i,MagickMaxBufferExtent));
3730static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3733 *magick_restrict cache_info;
3739 if (cache_info->debug != MagickFalse)
3742 format[MagickPathExtent],
3743 message[MagickPathExtent];
3745 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3746 (void) FormatLocaleString(message,MagickPathExtent,
3747 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3748 cache_info->cache_filename,cache_info->file,format);
3749 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3751 if (length != (MagickSizeType) ((MagickOffsetType) length))
3752 return(MagickFalse);
3753 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3755 return(MagickFalse);
3756 if ((MagickSizeType) offset < length)
3762 extent=(MagickOffsetType) length-1;
3763 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3766 return(MagickFalse);
3767#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3768 if (cache_info->synchronize != MagickFalse)
3769 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3770 return(MagickFalse);
3773 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3775 return(MagickFalse);
3779static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3783 *magick_restrict cache_info,
3787 format[MagickPathExtent],
3788 message[MagickPathExtent];
3805 assert(image != (
const Image *) NULL);
3806 assert(image->signature == MagickCoreSignature);
3807 assert(image->cache != (Cache) NULL);
3808 if (IsEventLogging() != MagickFalse)
3809 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3810 if (cache_anonymous_memory < 0)
3818 cache_anonymous_memory=0;
3819 value=GetPolicyValue(
"pixel-cache-memory");
3820 if (value == (
char *) NULL)
3821 value=GetPolicyValue(
"cache:memory-map");
3822 if (LocaleCompare(value,
"anonymous") == 0)
3824#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3825 cache_anonymous_memory=1;
3827 (void) ThrowMagickException(exception,GetMagickModule(),
3828 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3829 "`%s' (policy requires anonymous memory mapping)",image->filename);
3832 value=DestroyString(value);
3834 if ((image->columns == 0) || (image->rows == 0))
3835 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3837 assert(cache_info->signature == MagickCoreSignature);
3838 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3839 ((MagickSizeType) image->rows > cache_info->height_limit))
3841 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3842 "WidthOrHeightExceedsLimit",
"`%s' (%.17gx%.17g) > (%.17gx%.17g)",
3843 image->filename, (
double) image->columns, (
double) image->rows,
3844 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3845 return(MagickFalse);
3847 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3849 length=GetImageListLength(image);
3850 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3851 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3854 source_info=(*cache_info);
3855 source_info.file=(-1);
3856 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.17g]",
3857 image->filename,(
double) image->scene);
3858 cache_info->storage_class=image->storage_class;
3859 cache_info->colorspace=image->colorspace;
3860 cache_info->alpha_trait=image->alpha_trait;
3861 cache_info->channels=image->channels;
3862 cache_info->rows=image->rows;
3863 cache_info->columns=image->columns;
3864 status=ResetPixelChannelMap(image,exception);
3865 if (status == MagickFalse)
3866 return(MagickFalse);
3867 cache_info->number_channels=GetPixelChannels(image);
3868 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3869 sizeof(*image->channel_map));
3870 cache_info->metacontent_extent=image->metacontent_extent;
3871 cache_info->mode=mode;
3872 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3873 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3874 if (cache_info->metacontent_extent != 0)
3876 if (HeapOverflowCheckAdd(packet_size,cache_info->metacontent_extent) != MagickFalse)
3878 cache_info->storage_class=UndefinedClass;
3879 cache_info->length=0;
3880 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3883 packet_size+=cache_info->metacontent_extent;
3885 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3887 cache_info->storage_class=UndefinedClass;
3888 cache_info->length=0;
3889 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3892 columns=(size_t) (length/cache_info->rows/packet_size);
3893 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3894 ((ssize_t) cache_info->rows < 0))
3896 cache_info->storage_class=UndefinedClass;
3897 cache_info->length=0;
3898 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3901 cache_info->length=length;
3902 if (image->ping != MagickFalse)
3904 cache_info->type=PingCache;
3907 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3908 cache_info->columns*cache_info->rows);
3909 if (cache_info->mode == PersistMode)
3911 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3912 cache_info->metacontent_extent);
3913 if ((status != MagickFalse) &&
3914 (length == (MagickSizeType) ((
size_t) length)) &&
3915 ((cache_info->type == UndefinedCache) ||
3916 (cache_info->type == MemoryCache)))
3918 status=AcquireMagickResource(MemoryResource,cache_info->length);
3919 if (status != MagickFalse)
3922 if (cache_anonymous_memory <= 0)
3924 cache_info->mapped=MagickFalse;
3925 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3926 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3930 cache_info->mapped=MagickTrue;
3931 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3932 cache_info->length);
3934 if (cache_info->pixels == (Quantum *) NULL)
3936 RelinquishMagickResource(MemoryResource,cache_info->length);
3937 cache_info->mapped=source_info.mapped;
3938 cache_info->pixels=source_info.pixels;
3945 cache_info->type=MemoryCache;
3946 cache_info->metacontent=(
void *) NULL;
3947 if (cache_info->metacontent_extent != 0)
3948 cache_info->metacontent=(
void *) (cache_info->pixels+
3949 cache_info->number_channels*number_pixels);
3950 if ((source_info.storage_class != UndefinedClass) &&
3953 status=ClonePixelCacheRepository(cache_info,&source_info,
3955 RelinquishPixelCachePixels(&source_info);
3957 if (cache_info->debug != MagickFalse)
3959 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3960 MagickPathExtent,format);
3961 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3963 (void) FormatLocaleString(message,MagickPathExtent,
3964 "open %s (%s %s, %.17gx%.17gx%.17g %s)",
3965 cache_info->filename,cache_info->mapped != MagickFalse ?
3966 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3967 (
double) cache_info->rows,(
double)
3968 cache_info->number_channels,format);
3969 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3972 cache_info->storage_class=image->storage_class;
3975 if ((source_info.storage_class != UndefinedClass) &&
3977 RelinquishPixelCachePixels(&source_info);
3978 cache_info->type=UndefinedCache;
3979 return(MagickFalse);
3985 status=AcquireMagickResource(DiskResource,cache_info->length);
3986 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3988 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3996 server_info=AcquireDistributeCacheInfo(exception);
3999 status=OpenDistributePixelCache(server_info,image);
4000 if (status == MagickFalse)
4002 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4003 GetDistributeCacheHostname(server_info));
4004 server_info=DestroyDistributeCacheInfo(server_info);
4012 cache_info->type=DistributedCache;
4013 cache_info->server_info=server_info;
4014 (void) FormatLocaleString(cache_info->cache_filename,
4015 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
4018 cache_info->server_info));
4019 if ((source_info.storage_class != UndefinedClass) &&
4022 status=ClonePixelCacheRepository(cache_info,&source_info,
4024 RelinquishPixelCachePixels(&source_info);
4026 if (cache_info->debug != MagickFalse)
4028 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4029 MagickPathExtent,format);
4030 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4032 (void) FormatLocaleString(message,MagickPathExtent,
4033 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",
4034 cache_info->filename,cache_info->cache_filename,
4036 cache_info->server_info),type,(
double) cache_info->columns,
4037 (
double) cache_info->rows,(
double)
4038 cache_info->number_channels,format);
4039 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4044 if ((source_info.storage_class != UndefinedClass) &&
4046 RelinquishPixelCachePixels(&source_info);
4047 cache_info->type=UndefinedCache;
4048 return(MagickFalse);
4053 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4054 RelinquishPixelCachePixels(&source_info);
4055 cache_info->type=UndefinedCache;
4056 (void) memset(image->channel_map,0,MaxPixelChannels*
4057 sizeof(*image->channel_map));
4058 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4059 "CacheResourcesExhausted",
"`%s'",image->filename);
4060 return(MagickFalse);
4065 if (status == MagickFalse)
4067 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4068 RelinquishPixelCachePixels(&source_info);
4069 cache_info->type=UndefinedCache;
4070 (void) memset(image->channel_map,0,MaxPixelChannels*
4071 sizeof(*image->channel_map));
4072 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4073 "CacheResourcesExhausted",
"`%s'",image->filename);
4074 return(MagickFalse);
4076 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4077 (cache_info->mode != PersistMode))
4079 (void) ClosePixelCacheOnDisk(cache_info);
4080 *cache_info->cache_filename=
'\0';
4082 if (OpenPixelCacheOnDisk(cache_info,mode,exception) == MagickFalse)
4084 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4085 RelinquishPixelCachePixels(&source_info);
4086 cache_info->type=UndefinedCache;
4087 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4089 return(MagickFalse);
4091 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4092 cache_info->length);
4093 if (status == MagickFalse)
4095 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4096 RelinquishPixelCachePixels(&source_info);
4097 cache_info->type=UndefinedCache;
4098 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4100 return(MagickFalse);
4102 cache_info->type=DiskCache;
4103 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4104 cache_info->metacontent_extent);
4105 if (length == (MagickSizeType) ((
size_t) length))
4107 status=AcquireMagickResource(MapResource,cache_info->length);
4108 if (status != MagickFalse)
4110 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4111 cache_info->offset,(
size_t) cache_info->length);
4112 if (cache_info->pixels == (Quantum *) NULL)
4114 cache_info->mapped=source_info.mapped;
4115 cache_info->pixels=source_info.pixels;
4116 RelinquishMagickResource(MapResource,cache_info->length);
4123 (void) ClosePixelCacheOnDisk(cache_info);
4124 cache_info->type=MapCache;
4125 cache_info->mapped=MagickTrue;
4126 cache_info->metacontent=(
void *) NULL;
4127 if (cache_info->metacontent_extent != 0)
4128 cache_info->metacontent=(
void *) (cache_info->pixels+
4129 cache_info->number_channels*number_pixels);
4130 if ((source_info.storage_class != UndefinedClass) &&
4133 status=ClonePixelCacheRepository(cache_info,&source_info,
4135 RelinquishPixelCachePixels(&source_info);
4137 if (cache_info->debug != MagickFalse)
4139 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4140 MagickPathExtent,format);
4141 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4143 (void) FormatLocaleString(message,MagickPathExtent,
4144 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",
4145 cache_info->filename,cache_info->cache_filename,
4146 cache_info->file,type,(
double) cache_info->columns,
4147 (
double) cache_info->rows,(
double)
4148 cache_info->number_channels,format);
4149 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4154 if ((source_info.storage_class != UndefinedClass) &&
4156 RelinquishPixelCachePixels(&source_info);
4157 cache_info->type=UndefinedCache;
4158 return(MagickFalse);
4165 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4167 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4168 RelinquishPixelCachePixels(&source_info);
4170 if (cache_info->debug != MagickFalse)
4172 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4173 MagickPathExtent,format);
4174 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4176 (void) FormatLocaleString(message,MagickPathExtent,
4177 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",cache_info->filename,
4178 cache_info->cache_filename,cache_info->file,type,(
double)
4179 cache_info->columns,(
double) cache_info->rows,(
double)
4180 cache_info->number_channels,format);
4181 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4185 cache_info->type=UndefinedCache;
4186 return(MagickFalse);
4228MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4229 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4233 *magick_restrict cache_info,
4234 *magick_restrict clone_info;
4242 assert(image != (
Image *) NULL);
4243 assert(image->signature == MagickCoreSignature);
4244 if (IsEventLogging() != MagickFalse)
4245 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4246 assert(image->cache != (
void *) NULL);
4247 assert(filename != (
const char *) NULL);
4248 assert(offset != (MagickOffsetType *) NULL);
4249 page_size=GetMagickPageSize();
4251 assert(cache_info->signature == MagickCoreSignature);
4252#if defined(MAGICKCORE_OPENCL_SUPPORT)
4253 CopyOpenCLBuffer(cache_info);
4255 if (attach != MagickFalse)
4260 if (cache_info->debug != MagickFalse)
4261 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4262 "attach persistent cache");
4263 (void) CopyMagickString(cache_info->cache_filename,filename,
4265 cache_info->type=MapCache;
4266 cache_info->offset=(*offset);
4267 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4268 return(MagickFalse);
4269 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4270 ((MagickOffsetType) cache_info->length % page_size));
4276 status=AcquireMagickResource(DiskResource,cache_info->length);
4277 if (status == MagickFalse)
4279 cache_info->type=UndefinedCache;
4280 (void) memset(image->channel_map,0,MaxPixelChannels*
4281 sizeof(*image->channel_map));
4282 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4283 "CacheResourcesExhausted",
"`%s'",image->filename);
4284 return(MagickFalse);
4286 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4287 clone_info->type=DiskCache;
4288 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4289 clone_info->file=(-1);
4290 clone_info->storage_class=cache_info->storage_class;
4291 clone_info->colorspace=cache_info->colorspace;
4292 clone_info->alpha_trait=cache_info->alpha_trait;
4293 clone_info->channels=cache_info->channels;
4294 clone_info->columns=cache_info->columns;
4295 clone_info->rows=cache_info->rows;
4296 clone_info->number_channels=cache_info->number_channels;
4297 clone_info->metacontent_extent=cache_info->metacontent_extent;
4298 clone_info->mode=PersistMode;
4299 clone_info->length=cache_info->length;
4300 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4301 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4302 clone_info->offset=(*offset);
4303 status=OpenPixelCacheOnDisk(clone_info,WriteMode,exception);
4304 if (status != MagickFalse)
4305 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4306 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4307 ((MagickOffsetType) cache_info->length % page_size));
4308 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4350MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4351 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4355 *magick_restrict cache_info;
4364 *magick_restrict pixels;
4369 assert(image != (
const Image *) NULL);
4370 assert(image->signature == MagickCoreSignature);
4371 assert(image->cache != (Cache) NULL);
4372 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4373 if (cache_info == (Cache) NULL)
4374 return((Quantum *) NULL);
4375 assert(cache_info->signature == MagickCoreSignature);
4376 if ((columns == 0) || (rows == 0) ||
4377 (cache_info->columns == 0) || (cache_info->rows == 0) ||
4378 (x < 0) || (y < 0) ||
4379 (x >= (ssize_t) cache_info->columns) ||
4380 (y >= (ssize_t) cache_info->rows))
4382 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4383 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4384 return((Quantum *) NULL);
4386 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4387 return((Quantum *) NULL);
4388 offset=y*(MagickOffsetType) cache_info->columns;
4389 if (IsOffsetOverflow(offset,(MagickOffsetType) x) == MagickFalse)
4390 return((Quantum *) NULL);
4393 return((Quantum *) NULL);
4394 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4395 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns;
4396 if (IsOffsetOverflow(offset,(MagickOffsetType) columns-1) == MagickFalse)
4397 return((Quantum *) NULL);
4398 offset+=(MagickOffsetType) columns-1;
4399 if ((MagickSizeType) offset >= number_pixels)
4400 return((Quantum *) NULL);
4404 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4405 ((image->channels & WriteMaskChannel) != 0) ||
4406 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4407 nexus_info,exception);
4444static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4445 const ssize_t y,
const size_t columns,
const size_t rows,
4449 *magick_restrict cache_info;
4452 id = GetOpenMPThreadId();
4455 *magick_restrict pixels;
4457 assert(image != (
const Image *) NULL);
4458 assert(image->signature == MagickCoreSignature);
4459 assert(image->cache != (Cache) NULL);
4461 assert(cache_info->signature == MagickCoreSignature);
4462 assert(
id < (
int) cache_info->number_threads);
4463 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4464 cache_info->nexus_info[
id],exception);
4524MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4525 const ssize_t y,
const size_t columns,
const size_t rows,
4529 *magick_restrict cache_info;
4532 id = GetOpenMPThreadId();
4535 *magick_restrict pixels;
4537 assert(image != (
Image *) NULL);
4538 assert(image->signature == MagickCoreSignature);
4539 assert(image->cache != (Cache) NULL);
4541 assert(cache_info->signature == MagickCoreSignature);
4542 if (cache_info->methods.queue_authentic_pixels_handler !=
4543 (QueueAuthenticPixelsHandler) NULL)
4545 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4546 columns,rows,exception);
4549 assert(
id < (
int) cache_info->number_threads);
4550 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4551 cache_info->nexus_info[
id],exception);
4584static inline MagickOffsetType ReadPixelCacheRegion(
4585 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4586 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4594 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4595 return((MagickOffsetType) -1);
4596 for (i=0; i < (MagickOffsetType) length; i+=count)
4598 count=MagickRead(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4599 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4606static MagickBooleanType ReadPixelCacheMetacontent(
4627 if (cache_info->metacontent_extent == 0)
4628 return(MagickFalse);
4629 if (nexus_info->authentic_pixel_cache != MagickFalse)
4631 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4632 return(MagickFalse);
4633 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4634 nexus_info->region.x;
4635 length=(MagickSizeType) nexus_info->region.width*
4636 cache_info->metacontent_extent;
4637 extent=length*nexus_info->region.height;
4638 rows=nexus_info->region.height;
4640 q=(
unsigned char *) nexus_info->metacontent;
4641 switch (cache_info->type)
4652 if ((cache_info->columns == nexus_info->region.width) &&
4653 (extent == (MagickSizeType) ((
size_t) extent)))
4658 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4659 cache_info->metacontent_extent;
4660 for (y=0; y < (ssize_t) rows; y++)
4662 (void) memcpy(q,p,(
size_t) length);
4663 p+=(ptrdiff_t) (cache_info->metacontent_extent*cache_info->columns);
4664 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4665 nexus_info->region.width);
4674 LockSemaphoreInfo(cache_info->file_semaphore);
4675 if (OpenPixelCacheOnDisk(cache_info,IOMode,exception) == MagickFalse)
4677 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4678 cache_info->cache_filename);
4679 UnlockSemaphoreInfo(cache_info->file_semaphore);
4680 return(MagickFalse);
4682 if ((cache_info->columns == nexus_info->region.width) &&
4683 (extent <= MagickMaxBufferExtent))
4688 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4689 for (y=0; y < (ssize_t) rows; y++)
4691 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4692 (MagickOffsetType) extent*(MagickOffsetType)
4693 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4694 (MagickOffsetType) cache_info->metacontent_extent,length,
4695 (
unsigned char *) q);
4696 if (count != (MagickOffsetType) length)
4698 offset+=(MagickOffsetType) cache_info->columns;
4699 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4700 nexus_info->region.width);
4702 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4703 (void) ClosePixelCacheOnDisk(cache_info);
4704 UnlockSemaphoreInfo(cache_info->file_semaphore);
4707 case DistributedCache:
4715 LockSemaphoreInfo(cache_info->file_semaphore);
4716 region=nexus_info->region;
4717 if ((cache_info->columns != nexus_info->region.width) ||
4718 (extent > MagickMaxBufferExtent))
4725 for (y=0; y < (ssize_t) rows; y++)
4728 cache_info->server_info,®ion,length,(
unsigned char *) q);
4729 if (count != (MagickOffsetType) length)
4731 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4732 nexus_info->region.width);
4735 UnlockSemaphoreInfo(cache_info->file_semaphore);
4741 if (y < (ssize_t) rows)
4743 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4744 cache_info->cache_filename);
4745 return(MagickFalse);
4747 if ((cache_info->debug != MagickFalse) &&
4748 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4749 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4750 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
4751 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4752 nexus_info->region.x,(
double) nexus_info->region.y);
4784static MagickBooleanType ReadPixelCachePixels(
4806 if (nexus_info->authentic_pixel_cache != MagickFalse)
4808 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4809 return(MagickFalse);
4810 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4811 if ((offset/(ssize_t) cache_info->columns) != nexus_info->region.y)
4812 return(MagickFalse);
4813 offset+=nexus_info->region.x;
4814 number_channels=cache_info->number_channels;
4815 length=(MagickSizeType) number_channels*nexus_info->region.width*
4817 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4818 return(MagickFalse);
4819 rows=nexus_info->region.height;
4821 if ((extent == 0) || ((extent/length) != rows))
4822 return(MagickFalse);
4824 q=nexus_info->pixels;
4825 switch (cache_info->type)
4836 if ((cache_info->columns == nexus_info->region.width) &&
4837 (extent == (MagickSizeType) ((
size_t) extent)))
4842 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4844 for (y=0; y < (ssize_t) rows; y++)
4846 (void) memcpy(q,p,(
size_t) length);
4847 p+=(ptrdiff_t) (cache_info->number_channels*cache_info->columns);
4848 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4857 LockSemaphoreInfo(cache_info->file_semaphore);
4858 if (OpenPixelCacheOnDisk(cache_info,IOMode,exception) == MagickFalse)
4860 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4861 cache_info->cache_filename);
4862 UnlockSemaphoreInfo(cache_info->file_semaphore);
4863 return(MagickFalse);
4865 if ((cache_info->columns == nexus_info->region.width) &&
4866 (extent <= MagickMaxBufferExtent))
4871 for (y=0; y < (ssize_t) rows; y++)
4873 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4874 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4875 sizeof(*q),length,(
unsigned char *) q);
4876 if (count != (MagickOffsetType) length)
4878 offset+=(MagickOffsetType) cache_info->columns;
4879 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4881 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4882 (void) ClosePixelCacheOnDisk(cache_info);
4883 UnlockSemaphoreInfo(cache_info->file_semaphore);
4886 case DistributedCache:
4894 LockSemaphoreInfo(cache_info->file_semaphore);
4895 region=nexus_info->region;
4896 if ((cache_info->columns != nexus_info->region.width) ||
4897 (extent > MagickMaxBufferExtent))
4904 for (y=0; y < (ssize_t) rows; y++)
4907 cache_info->server_info,®ion,length,(
unsigned char *) q);
4908 if (count != (MagickOffsetType) length)
4910 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4913 UnlockSemaphoreInfo(cache_info->file_semaphore);
4919 if (y < (ssize_t) rows)
4921 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4922 cache_info->cache_filename);
4923 return(MagickFalse);
4925 if ((cache_info->debug != MagickFalse) &&
4926 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4927 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4928 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
4929 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4930 nexus_info->region.x,(
double) nexus_info->region.y);
4957MagickPrivate Cache ReferencePixelCache(Cache cache)
4960 *magick_restrict cache_info;
4962 assert(cache != (Cache *) NULL);
4964 assert(cache_info->signature == MagickCoreSignature);
4965 LockSemaphoreInfo(cache_info->semaphore);
4966 cache_info->reference_count++;
4967 UnlockSemaphoreInfo(cache_info->semaphore);
4993MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4996 *magick_restrict cache_info;
4998 assert(image != (
const Image *) NULL);
4999 assert(image->signature == MagickCoreSignature);
5000 assert(image->cache != (Cache) NULL);
5002 assert(cache_info->signature == MagickCoreSignature);
5003 cache_info->number_channels=GetPixelChannels(image);
5024MagickPrivate
void ResetCacheAnonymousMemory(
void)
5026 cache_anonymous_memory=0;
5058MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
5059 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
5067 assert(image != (
Image *) NULL);
5068 assert(image->signature == MagickCoreSignature);
5069 if (IsEventLogging() != MagickFalse)
5070 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5071 assert(image->cache != (
void *) NULL);
5072 extent=(MagickSizeType) columns*rows;
5073 if (extent > ((MagickSizeType) image->columns*image->rows))
5074 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5076 image->columns=columns;
5079 cache_info->columns=columns;
5080 cache_info->rows=rows;
5081 return(SyncImagePixelCache(image,exception));
5108MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5111 *magick_restrict cache_info;
5113 GetOneAuthenticPixelFromHandler
5114 get_one_authentic_pixel_from_handler;
5116 GetOneVirtualPixelFromHandler
5117 get_one_virtual_pixel_from_handler;
5122 assert(cache != (Cache) NULL);
5125 assert(cache_info->signature == MagickCoreSignature);
5126 if (IsEventLogging() != MagickFalse)
5127 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5128 cache_info->filename);
5129 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5130 cache_info->methods.get_virtual_pixel_handler=
5131 cache_methods->get_virtual_pixel_handler;
5132 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5133 cache_info->methods.destroy_pixel_handler=
5134 cache_methods->destroy_pixel_handler;
5135 if (cache_methods->get_virtual_metacontent_from_handler !=
5136 (GetVirtualMetacontentFromHandler) NULL)
5137 cache_info->methods.get_virtual_metacontent_from_handler=
5138 cache_methods->get_virtual_metacontent_from_handler;
5139 if (cache_methods->get_authentic_pixels_handler !=
5140 (GetAuthenticPixelsHandler) NULL)
5141 cache_info->methods.get_authentic_pixels_handler=
5142 cache_methods->get_authentic_pixels_handler;
5143 if (cache_methods->queue_authentic_pixels_handler !=
5144 (QueueAuthenticPixelsHandler) NULL)
5145 cache_info->methods.queue_authentic_pixels_handler=
5146 cache_methods->queue_authentic_pixels_handler;
5147 if (cache_methods->sync_authentic_pixels_handler !=
5148 (SyncAuthenticPixelsHandler) NULL)
5149 cache_info->methods.sync_authentic_pixels_handler=
5150 cache_methods->sync_authentic_pixels_handler;
5151 if (cache_methods->get_authentic_pixels_from_handler !=
5152 (GetAuthenticPixelsFromHandler) NULL)
5153 cache_info->methods.get_authentic_pixels_from_handler=
5154 cache_methods->get_authentic_pixels_from_handler;
5155 if (cache_methods->get_authentic_metacontent_from_handler !=
5156 (GetAuthenticMetacontentFromHandler) NULL)
5157 cache_info->methods.get_authentic_metacontent_from_handler=
5158 cache_methods->get_authentic_metacontent_from_handler;
5159 get_one_virtual_pixel_from_handler=
5160 cache_info->methods.get_one_virtual_pixel_from_handler;
5161 if (get_one_virtual_pixel_from_handler !=
5162 (GetOneVirtualPixelFromHandler) NULL)
5163 cache_info->methods.get_one_virtual_pixel_from_handler=
5164 cache_methods->get_one_virtual_pixel_from_handler;
5165 get_one_authentic_pixel_from_handler=
5166 cache_methods->get_one_authentic_pixel_from_handler;
5167 if (get_one_authentic_pixel_from_handler !=
5168 (GetOneAuthenticPixelFromHandler) NULL)
5169 cache_info->methods.get_one_authentic_pixel_from_handler=
5170 cache_methods->get_one_authentic_pixel_from_handler;
5211static inline MagickBooleanType AcquireCacheNexusPixels(
5212 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5215 nexus_info->length=0;
5216 nexus_info->mapped=MagickFalse;
5217 if (length != (MagickSizeType) ((
size_t) length))
5219 (void) ThrowMagickException(exception,GetMagickModule(),
5220 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5221 cache_info->filename);
5222 return(MagickFalse);
5224 if (cache_anonymous_memory <= 0)
5226 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5228 if (nexus_info->cache != (Quantum *) NULL)
5229 (void) memset(nexus_info->cache,0,(
size_t) length);
5233 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5234 if (nexus_info->cache != (Quantum *) NULL)
5235 nexus_info->mapped=MagickTrue;
5237 if (nexus_info->cache == (Quantum *) NULL)
5239 (void) ThrowMagickException(exception,GetMagickModule(),
5240 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5241 cache_info->filename);
5242 return(MagickFalse);
5244 nexus_info->length=length;
5248static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5251 if (nexus_info->length < CACHE_LINE_SIZE)
5253 if (mode == ReadMode)
5255 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5259 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5262static Quantum *SetPixelCacheNexusPixels(
5263 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5264 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5265 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5275 assert(cache_info != (
const CacheInfo *) NULL);
5276 assert(cache_info->signature == MagickCoreSignature);
5277 if (cache_info->type == UndefinedCache)
5278 return((Quantum *) NULL);
5279 assert(nexus_info->signature == MagickCoreSignature);
5280 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5281 if ((width == 0) || (height == 0))
5283 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5284 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5285 return((Quantum *) NULL);
5287 if (((MagickSizeType) width > cache_info->width_limit) ||
5288 ((MagickSizeType) height > cache_info->height_limit))
5290 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5291 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5292 return((Quantum *) NULL);
5294 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5295 (IsValidPixelOffset(y,height) == MagickFalse))
5297 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5298 "InvalidPixel",
"`%s'",cache_info->filename);
5299 return((Quantum *) NULL);
5301 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5302 (buffered == MagickFalse))
5304 if (((x >= 0) && (y >= 0) &&
5305 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5306 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5307 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5315 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5316 return((Quantum *) NULL);
5317 offset=y*(MagickOffsetType) cache_info->columns+x;
5318 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5319 cache_info->number_channels*offset;
5320 nexus_info->metacontent=(
void *) NULL;
5321 if (cache_info->metacontent_extent != 0)
5322 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5323 offset*(MagickOffsetType) cache_info->metacontent_extent;
5324 nexus_info->region.width=width;
5325 nexus_info->region.height=height;
5326 nexus_info->region.x=x;
5327 nexus_info->region.y=y;
5328 nexus_info->authentic_pixel_cache=MagickTrue;
5329 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5330 return(nexus_info->pixels);
5336 if (CacheOverflowSanityCheckGetSize(width,height,&number_pixels) != MagickFalse)
5338 (void) ThrowMagickException(exception,GetMagickModule(),
5339 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5340 cache_info->filename);
5341 return((Quantum *) NULL);
5348 packets=MagickMax(number_pixels,MagickMax(cache_info->columns,
5350 if ((CacheOverflowSanityCheckGetSize(packets,cache_info->number_channels,&length) != MagickFalse) ||
5351 (CacheOverflowSanityCheckGetSize(length,
sizeof(*nexus_info->pixels),&length) != MagickFalse))
5353 (void) ThrowMagickException(exception,GetMagickModule(),
5354 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5355 cache_info->filename);
5356 return((Quantum *) NULL);
5358 if (cache_info->metacontent_extent != 0)
5360 if ((CacheOverflowSanityCheckGetSize(number_pixels,cache_info->metacontent_extent,&extent) != MagickFalse) ||
5361 (extent > (MagickSizeType) (~((MagickSizeType) 0))-length))
5363 (void) ThrowMagickException(exception,GetMagickModule(),
5364 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5365 cache_info->filename);
5366 return((Quantum *) NULL);
5372 if (nexus_info->cache == (Quantum *) NULL)
5373 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5375 if (nexus_info->length < length)
5377 RelinquishCacheNexusPixels(nexus_info);
5378 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5380 if (status == MagickFalse)
5381 return((Quantum *) NULL);
5382 nexus_info->pixels=nexus_info->cache;
5383 nexus_info->metacontent=(
void *) NULL;
5384 if (cache_info->metacontent_extent != 0)
5385 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5386 cache_info->number_channels*number_pixels);
5387 nexus_info->region.width=width;
5388 nexus_info->region.height=height;
5389 nexus_info->region.x=x;
5390 nexus_info->region.y=y;
5391 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5392 MagickTrue : MagickFalse;
5393 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5394 return(nexus_info->pixels);
5427static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5431 *magick_restrict image_view;
5439 assert(image != (
Image *) NULL);
5440 assert(image->signature == MagickCoreSignature);
5441 if (IsEventLogging() != MagickFalse)
5442 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5443 assert(image->cache != (Cache) NULL);
5444 image->alpha_trait=BlendPixelTrait;
5446 image_view=AcquireVirtualCacheView(image,exception);
5447#if defined(MAGICKCORE_OPENMP_SUPPORT)
5448 #pragma omp parallel for schedule(static) shared(status) \
5449 magick_number_threads(image,image,image->rows,2)
5451 for (y=0; y < (ssize_t) image->rows; y++)
5459 if (status == MagickFalse)
5461 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5462 if (q == (Quantum *) NULL)
5467 for (x=0; x < (ssize_t) image->columns; x++)
5469 SetPixelAlpha(image,alpha,q);
5470 q+=(ptrdiff_t) GetPixelChannels(image);
5472 status=SyncCacheViewAuthenticPixels(image_view,exception);
5474 image_view=DestroyCacheView(image_view);
5478MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5479 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5482 *magick_restrict cache_info;
5487 assert(image != (
Image *) NULL);
5488 assert(image->signature == MagickCoreSignature);
5489 if (IsEventLogging() != MagickFalse)
5490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5491 assert(image->cache != (Cache) NULL);
5493 assert(cache_info->signature == MagickCoreSignature);
5494 method=cache_info->virtual_pixel_method;
5495 cache_info->virtual_pixel_method=virtual_pixel_method;
5496 if ((image->columns != 0) && (image->rows != 0))
5497 switch (virtual_pixel_method)
5499 case BackgroundVirtualPixelMethod:
5501 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5502 ((image->alpha_trait & BlendPixelTrait) == 0))
5503 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5504 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5505 (IsGrayColorspace(image->colorspace) != MagickFalse))
5506 (void) SetImageColorspace(image,sRGBColorspace,exception);
5509 case TransparentVirtualPixelMethod:
5511 if ((image->alpha_trait & BlendPixelTrait) == 0)
5512 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5521#if defined(MAGICKCORE_OPENCL_SUPPORT)
5546static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5548 assert(cache_info != (
CacheInfo *) NULL);
5549 assert(cache_info->signature == MagickCoreSignature);
5550 if ((cache_info->type != MemoryCache) ||
5551 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5556 LockSemaphoreInfo(cache_info->semaphore);
5557 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5558 UnlockSemaphoreInfo(cache_info->semaphore);
5561MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5564 *magick_restrict cache_info;
5566 assert(image != (
const Image *) NULL);
5568 CopyOpenCLBuffer(cache_info);
5601MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5605 *magick_restrict cache_info;
5613 assert(image != (
Image *) NULL);
5614 assert(image->signature == MagickCoreSignature);
5615 if (image->cache == (Cache) NULL)
5616 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5618 assert(cache_info->signature == MagickCoreSignature);
5619 if (cache_info->type == UndefinedCache)
5620 return(MagickFalse);
5621 if ((image->mask_trait & UpdatePixelTrait) != 0)
5623 if (((image->channels & WriteMaskChannel) != 0) &&
5624 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5625 return(MagickFalse);
5626 if (((image->channels & CompositeMaskChannel) != 0) &&
5627 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5628 return(MagickFalse);
5630 if (nexus_info->authentic_pixel_cache != MagickFalse)
5632 if (image->taint == MagickFalse)
5633 image->taint=MagickTrue;
5636 assert(cache_info->signature == MagickCoreSignature);
5637 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5638 if ((cache_info->metacontent_extent != 0) &&
5639 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5640 return(MagickFalse);
5641 if ((status != MagickFalse) && (image->taint == MagickFalse))
5642 image->taint=MagickTrue;
5673static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5677 *magick_restrict cache_info;
5680 id = GetOpenMPThreadId();
5685 assert(image != (
Image *) NULL);
5686 assert(image->signature == MagickCoreSignature);
5687 assert(image->cache != (Cache) NULL);
5689 assert(cache_info->signature == MagickCoreSignature);
5690 assert(
id < (
int) cache_info->number_threads);
5691 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5723MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5727 *magick_restrict cache_info;
5730 id = GetOpenMPThreadId();
5735 assert(image != (
Image *) NULL);
5736 assert(image->signature == MagickCoreSignature);
5737 assert(image->cache != (Cache) NULL);
5739 assert(cache_info->signature == MagickCoreSignature);
5740 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5742 status=cache_info->methods.sync_authentic_pixels_handler(image,
5746 assert(
id < (
int) cache_info->number_threads);
5747 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5779MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5783 *magick_restrict cache_info;
5785 assert(image != (
Image *) NULL);
5787 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5788 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5819static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5839 if (cache_info->metacontent_extent == 0)
5840 return(MagickFalse);
5841 if (nexus_info->authentic_pixel_cache != MagickFalse)
5843 if (nexus_info->metacontent == (
unsigned char *) NULL)
5844 return(MagickFalse);
5845 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5846 return(MagickFalse);
5847 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5848 nexus_info->region.x;
5849 length=(MagickSizeType) nexus_info->region.width*
5850 cache_info->metacontent_extent;
5851 extent=(MagickSizeType) length*nexus_info->region.height;
5852 rows=nexus_info->region.height;
5854 p=(
unsigned char *) nexus_info->metacontent;
5855 switch (cache_info->type)
5866 if ((cache_info->columns == nexus_info->region.width) &&
5867 (extent == (MagickSizeType) ((
size_t) extent)))
5872 q=(
unsigned char *) cache_info->metacontent+offset*
5873 (MagickOffsetType) cache_info->metacontent_extent;
5874 for (y=0; y < (ssize_t) rows; y++)
5876 (void) memcpy(q,p,(
size_t) length);
5877 p+=(ptrdiff_t) (nexus_info->region.width*
5878 cache_info->metacontent_extent);
5879 q+=(ptrdiff_t) (cache_info->columns*cache_info->metacontent_extent);
5888 LockSemaphoreInfo(cache_info->file_semaphore);
5889 if (OpenPixelCacheOnDisk(cache_info,IOMode,exception) == MagickFalse)
5891 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5892 cache_info->cache_filename);
5893 UnlockSemaphoreInfo(cache_info->file_semaphore);
5894 return(MagickFalse);
5896 if ((cache_info->columns == nexus_info->region.width) &&
5897 (extent <= MagickMaxBufferExtent))
5902 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5903 for (y=0; y < (ssize_t) rows; y++)
5905 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5906 (MagickOffsetType) extent*(MagickOffsetType)
5907 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5908 (MagickOffsetType) cache_info->metacontent_extent,length,
5909 (
const unsigned char *) p);
5910 if (count != (MagickOffsetType) length)
5912 p+=(ptrdiff_t) (cache_info->metacontent_extent*
5913 nexus_info->region.width);
5914 offset+=(MagickOffsetType) cache_info->columns;
5916 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5917 (void) ClosePixelCacheOnDisk(cache_info);
5918 UnlockSemaphoreInfo(cache_info->file_semaphore);
5921 case DistributedCache:
5929 LockSemaphoreInfo(cache_info->file_semaphore);
5930 region=nexus_info->region;
5931 if ((cache_info->columns != nexus_info->region.width) ||
5932 (extent > MagickMaxBufferExtent))
5939 for (y=0; y < (ssize_t) rows; y++)
5942 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5943 if (count != (MagickOffsetType) length)
5945 p+=(ptrdiff_t) (cache_info->metacontent_extent*
5946 nexus_info->region.width);
5949 UnlockSemaphoreInfo(cache_info->file_semaphore);
5955 if (y < (ssize_t) rows)
5957 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5958 cache_info->cache_filename);
5959 return(MagickFalse);
5961 if ((cache_info->debug != MagickFalse) &&
5962 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5963 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5964 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
5965 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5966 nexus_info->region.x,(
double) nexus_info->region.y);
5998static MagickBooleanType WritePixelCachePixels(
6019 if (nexus_info->authentic_pixel_cache != MagickFalse)
6021 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
6022 return(MagickFalse);
6023 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
6024 nexus_info->region.x;
6025 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
6027 extent=length*nexus_info->region.height;
6028 rows=nexus_info->region.height;
6030 p=nexus_info->pixels;
6031 switch (cache_info->type)
6042 if ((cache_info->columns == nexus_info->region.width) &&
6043 (extent == (MagickSizeType) ((
size_t) extent)))
6048 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
6050 for (y=0; y < (ssize_t) rows; y++)
6052 (void) memcpy(q,p,(
size_t) length);
6053 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6054 q+=(ptrdiff_t) (cache_info->number_channels*cache_info->columns);
6063 LockSemaphoreInfo(cache_info->file_semaphore);
6064 if (OpenPixelCacheOnDisk(cache_info,IOMode,exception) == MagickFalse)
6066 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6067 cache_info->cache_filename);
6068 UnlockSemaphoreInfo(cache_info->file_semaphore);
6069 return(MagickFalse);
6071 if ((cache_info->columns == nexus_info->region.width) &&
6072 (extent <= MagickMaxBufferExtent))
6077 for (y=0; y < (ssize_t) rows; y++)
6079 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6080 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
6081 sizeof(*p),length,(
const unsigned char *) p);
6082 if (count != (MagickOffsetType) length)
6084 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6085 offset+=(MagickOffsetType) cache_info->columns;
6087 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6088 (void) ClosePixelCacheOnDisk(cache_info);
6089 UnlockSemaphoreInfo(cache_info->file_semaphore);
6092 case DistributedCache:
6100 LockSemaphoreInfo(cache_info->file_semaphore);
6101 region=nexus_info->region;
6102 if ((cache_info->columns != nexus_info->region.width) ||
6103 (extent > MagickMaxBufferExtent))
6110 for (y=0; y < (ssize_t) rows; y++)
6113 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6114 if (count != (MagickOffsetType) length)
6116 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6119 UnlockSemaphoreInfo(cache_info->file_semaphore);
6125 if (y < (ssize_t) rows)
6127 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6128 cache_info->cache_filename);
6129 return(MagickFalse);
6131 if ((cache_info->debug != MagickFalse) &&
6132 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6133 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6134 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
6135 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6136 nexus_info->region.x,(
double) nexus_info->region.y);