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/quantum.h"
67#include "MagickCore/random_.h"
68#include "MagickCore/registry.h"
69#include "MagickCore/resource_.h"
70#include "MagickCore/semaphore.h"
71#include "MagickCore/splay-tree.h"
72#include "MagickCore/string_.h"
73#include "MagickCore/string-private.h"
74#include "MagickCore/timer-private.h"
75#include "MagickCore/thread-private.h"
76#include "MagickCore/utility.h"
77#include "MagickCore/utility-private.h"
78#if defined(MAGICKCORE_HAVE_ERRNO_H)
81#if defined(MAGICKCORE_HAVE_SYS_LOADAVG_H)
82# include <sys/loadavg.h>
84#if defined(MAGICKCORE_ZLIB_DELEGATE)
91#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
92#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
93 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
108#if defined(__cplusplus) || defined(c_plusplus)
117 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
119 *GetVirtualPixelsCache(
const Image *);
122 *GetVirtualMetacontentFromCache(
const Image *);
124static MagickBooleanType
125 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,Quantum *,
127 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
130 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
133 ReadPixelCacheMetacontent(
CacheInfo *magick_restrict,
142 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
144 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
146 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
147 const ssize_t,
const ssize_t,
const size_t,
const size_t,
151#if defined(MAGICKCORE_OPENCL_SUPPORT)
153 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
156#if defined(__cplusplus) || defined(c_plusplus)
167 cache_anonymous_memory = (-1);
191MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
194 *magick_restrict cache_info;
199 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
201 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
202 (void) memset(cache_info,0,
sizeof(*cache_info));
203 cache_info->type=UndefinedCache;
204 cache_info->mode=IOMode;
205 cache_info->disk_mode=IOMode;
206 cache_info->colorspace=sRGBColorspace;
207 cache_info->file=(-1);
208 cache_info->id=GetMagickThreadId();
209 cache_info->number_threads=number_threads;
210 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
211 cache_info->number_threads=GetOpenMPMaximumThreads();
212 if (cache_info->number_threads == 0)
213 cache_info->number_threads=1;
214 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
215 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
216 if (value != (
const char *) NULL)
218 cache_info->synchronize=IsStringTrue(value);
219 value=DestroyString(value);
221 value=GetPolicyValue(
"cache:synchronize");
222 if (value != (
const char *) NULL)
224 cache_info->synchronize=IsStringTrue(value);
225 value=DestroyString(value);
227 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
228 (MagickSizeType) MAGICK_SSIZE_MAX);
229 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
230 (MagickSizeType) MAGICK_SSIZE_MAX);
231 cache_info->semaphore=AcquireSemaphoreInfo();
232 cache_info->reference_count=1;
233 cache_info->file_semaphore=AcquireSemaphoreInfo();
234 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
236 cache_info->signature=MagickCoreSignature;
237 return((Cache ) cache_info);
262MagickPrivate
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
265 **magick_restrict nexus_info;
270 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
271 number_threads,
sizeof(*nexus_info)));
273 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
274 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
275 2*
sizeof(**nexus_info));
277 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
278 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
279 for (i=0; i < (ssize_t) (2*number_threads); i++)
281 nexus_info[i]=(*nexus_info+i);
282 if (i < (ssize_t) number_threads)
283 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
284 nexus_info[i]->signature=MagickCoreSignature;
317MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
321 *magick_restrict cache_info;
323 assert(image != (
const Image *) NULL);
324 assert(image->signature == MagickCoreSignature);
326 assert(exception->signature == MagickCoreSignature);
327 assert(image->cache != (Cache) NULL);
330 assert(cache_info->signature == MagickCoreSignature);
332 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
333 return((
void *) NULL);
334 *length=(size_t) cache_info->length;
335 return(cache_info->pixels);
356MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
359 cache_semaphore=AcquireSemaphoreInfo();
381MagickPrivate
void CacheComponentTerminus(
void)
384 ActivateSemaphoreInfo(&cache_semaphore);
386 RelinquishSemaphoreInfo(&cache_semaphore);
418static MagickBooleanType ClipPixelCacheNexus(
Image *image,
422 *magick_restrict cache_info;
434 if (IsEventLogging() != MagickFalse)
435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
436 if ((image->channels & WriteMaskChannel) == 0)
438 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
443 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
444 nexus_info->region.width,nexus_info->region.height,
445 nexus_info->virtual_nexus,exception);
446 q=nexus_info->pixels;
447 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
449 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
454 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
462 mask=(double) GetPixelWriteMask(image,p);
463 if (fabs(mask) >= MagickEpsilon)
472 src_alpha=GetPixelAlpha(image,p);
473 mask_alpha=QuantumScale*mask*(double) src_alpha;
474 dst_alpha=(double) GetPixelAlpha(image,q);
475 for (i=0; i < (ssize_t) image->number_channels; i++)
480 PixelChannel channel = GetPixelChannelChannel(image,i);
481 if (channel == AlphaPixelChannel)
483 traits=GetPixelChannelTraits(image,channel);
484 if ((traits & UpdatePixelTrait) == 0)
486 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha,
487 (
double) q[i],dst_alpha));
489 SetPixelAlpha(image,src_alpha,q);
491 p+=(ptrdiff_t) GetPixelChannels(image);
492 q+=(ptrdiff_t) GetPixelChannels(image);
520MagickPrivate Cache ClonePixelCache(
const Cache cache)
523 *magick_restrict clone_info;
526 *magick_restrict cache_info;
528 assert(cache != NULL);
530 assert(cache_info->signature == MagickCoreSignature);
531 if (IsEventLogging() != MagickFalse)
532 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
533 cache_info->filename);
534 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
535 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
536 return((Cache ) clone_info);
564MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
567 *magick_restrict cache_info,
568 *magick_restrict source_info;
570 assert(clone != (Cache) NULL);
572 assert(source_info->signature == MagickCoreSignature);
573 if (IsEventLogging() != MagickFalse)
574 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
575 source_info->filename);
576 assert(cache != (Cache) NULL);
578 assert(cache_info->signature == MagickCoreSignature);
579 source_info->methods=cache_info->methods;
611static MagickBooleanType ClonePixelCacheOnDisk(
632 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
633 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
635 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
636 (lseek(clone_info->file,0,SEEK_SET) < 0))
638 quantum=(size_t) MagickMaxBufferExtent;
639 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
641#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
642 if (cache_info->length < 0x7ffff000)
646 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
647 (
size_t) cache_info->length);
648 }
while ((count < 0) && (errno == EINTR));
649 if (count == (ssize_t) cache_info->length)
653 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
654 (lseek(clone_info->file,0,SEEK_SET) < 0))
658 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
660 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
661 if (buffer == (
unsigned char *) NULL)
664 while (extent < cache_info->length)
669 length=(size_t) MagickMin((MagickSizeType) quantum,cache_info->length-
671 count=MagickRead(cache_info->file,buffer,length);
674 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
682 while (offset < count)
684 number_bytes=MagickWrite(clone_info->file,buffer+offset,(
size_t) (count-
686 if (number_bytes <= 0)
688 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
691 offset+=number_bytes;
693 extent+=(MagickSizeType) offset;
696 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
697 return(extent == cache_info->length ? MagickTrue : MagickFalse);
700#if defined(MAGICKCORE_OPENMP_SUPPORT)
701static inline int GetCacheNumberThreads(
const CacheInfo *source,
702 const CacheInfo *destination,
const size_t chunk,
const int factor)
705 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
706 number_threads = 1UL,
707 workload_factor = 64UL << factor;
712 number_threads=(chunk <= workload_factor) ? 1UL :
713 (chunk >= (workload_factor << 6)) ? max_threads :
714 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
718 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
719 ((destination->type != MemoryCache) && (destination->type != MapCache)))
720 number_threads=MagickMin(number_threads,4);
721 return((
int) number_threads);
725static MagickBooleanType ClonePixelCacheRepository(
729#define cache_number_threads(source,destination,chunk,factor) \
730 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
737 **magick_restrict cache_nexus,
738 **magick_restrict clone_nexus;
746 assert(cache_info != (
CacheInfo *) NULL);
747 assert(clone_info != (
CacheInfo *) NULL);
749 if (cache_info->type == PingCache)
751 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
752 if ((cache_info->storage_class == clone_info->storage_class) &&
753 (cache_info->colorspace == clone_info->colorspace) &&
754 (cache_info->alpha_trait == clone_info->alpha_trait) &&
755 (cache_info->channels == clone_info->channels) &&
756 (cache_info->columns == clone_info->columns) &&
757 (cache_info->rows == clone_info->rows) &&
758 (cache_info->number_channels == clone_info->number_channels) &&
759 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
760 (cache_info->metacontent_extent == clone_info->metacontent_extent))
765 if (((cache_info->type == MemoryCache) ||
766 (cache_info->type == MapCache)) &&
767 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
769 (void) memcpy(clone_info->pixels,cache_info->pixels,
770 cache_info->number_channels*cache_info->columns*cache_info->rows*
771 sizeof(*cache_info->pixels));
772 if ((cache_info->metacontent_extent != 0) &&
773 (clone_info->metacontent_extent != 0))
774 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
775 cache_info->columns*cache_info->rows*
776 clone_info->metacontent_extent*
sizeof(
unsigned char));
779 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
780 return(ClonePixelCacheOnDisk(cache_info,clone_info));
785 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
786 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
787 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
788 optimize=(cache_info->number_channels == clone_info->number_channels) &&
789 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
790 MagickTrue : MagickFalse;
791 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
792 clone_info->number_channels*clone_info->columns);
794#if defined(MAGICKCORE_OPENMP_SUPPORT)
795 #pragma omp parallel for schedule(static) shared(status) \
796 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
798 for (y=0; y < (ssize_t) cache_info->rows; y++)
801 id = GetOpenMPThreadId();
809 if (status == MagickFalse)
811 if (y >= (ssize_t) clone_info->rows)
813 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
814 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
815 if (pixels == (Quantum *) NULL)
817 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
818 if (status == MagickFalse)
820 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
821 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
822 if (pixels == (Quantum *) NULL)
824 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
825 if (optimize != MagickFalse)
826 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
839 p=cache_nexus[id]->pixels;
840 q=clone_nexus[id]->pixels;
841 for (x=0; x < (ssize_t) cache_info->columns; x++)
846 if (x == (ssize_t) clone_info->columns)
848 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
856 channel=clone_info->channel_map[i].channel;
857 traits=cache_info->channel_map[channel].traits;
858 if (traits != UndefinedPixelTrait)
859 *q=*(p+cache_info->channel_map[channel].offset);
862 p+=(ptrdiff_t) cache_info->number_channels;
865 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
867 if ((cache_info->metacontent_extent != 0) &&
868 (clone_info->metacontent_extent != 0))
873 length=(size_t) MagickMin(cache_info->metacontent_extent,
874 clone_info->metacontent_extent);
875#if defined(MAGICKCORE_OPENMP_SUPPORT)
876 #pragma omp parallel for schedule(static) shared(status) \
877 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
879 for (y=0; y < (ssize_t) cache_info->rows; y++)
882 id = GetOpenMPThreadId();
887 if (status == MagickFalse)
889 if (y >= (ssize_t) clone_info->rows)
891 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
892 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
893 if (pixels == (Quantum *) NULL)
895 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
896 if (status == MagickFalse)
898 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
899 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
900 if (pixels == (Quantum *) NULL)
902 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
903 (cache_nexus[
id]->metacontent != (
void *) NULL))
904 (void) memcpy(clone_nexus[
id]->metacontent,
905 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
906 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
909 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
910 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
911 if (cache_info->debug != MagickFalse)
914 message[MagickPathExtent];
916 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
917 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
918 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
919 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
946static void DestroyImagePixelCache(
Image *image)
948 assert(image != (
Image *) NULL);
949 assert(image->signature == MagickCoreSignature);
950 if (IsEventLogging() != MagickFalse)
951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
952 if (image->cache != (
void *) NULL)
953 image->cache=DestroyPixelCache(image->cache);
978MagickExport
void DestroyImagePixels(
Image *image)
981 *magick_restrict cache_info;
983 assert(image != (
const Image *) NULL);
984 assert(image->signature == MagickCoreSignature);
985 if (IsEventLogging() != MagickFalse)
986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
987 assert(image->cache != (Cache) NULL);
989 assert(cache_info->signature == MagickCoreSignature);
990 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
992 cache_info->methods.destroy_pixel_handler(image);
995 image->cache=DestroyPixelCache(image->cache);
1021static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1027 if (cache_info->file != -1)
1029 status=close_utf8(cache_info->file);
1030 cache_info->file=(-1);
1031 RelinquishMagickResource(FileResource,1);
1033 return(status == -1 ? MagickFalse : MagickTrue);
1036static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1038 switch (cache_info->type)
1042 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1043#if defined(MAGICKCORE_OPENCL_SUPPORT)
1044 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1046 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1048 cache_info->pixels=(Quantum *) NULL;
1052 if (cache_info->mapped == MagickFalse)
1053 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1054 cache_info->pixels);
1057 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1058 cache_info->pixels=(Quantum *) NULL;
1060 RelinquishMagickResource(MemoryResource,cache_info->length);
1065 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1066 cache_info->pixels=(Quantum *) NULL;
1067 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1068 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1069 *cache_info->cache_filename=
'\0';
1070 RelinquishMagickResource(MapResource,cache_info->length);
1075 if (cache_info->file != -1)
1076 (void) ClosePixelCacheOnDisk(cache_info);
1077 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1078 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1079 *cache_info->cache_filename=
'\0';
1080 RelinquishMagickResource(DiskResource,cache_info->length);
1083 case DistributedCache:
1085 *cache_info->cache_filename=
'\0';
1087 cache_info->server_info);
1093 cache_info->type=UndefinedCache;
1094 cache_info->mapped=MagickFalse;
1095 cache_info->metacontent=(
void *) NULL;
1098MagickPrivate Cache DestroyPixelCache(Cache cache)
1101 *magick_restrict cache_info;
1103 assert(cache != (Cache) NULL);
1105 assert(cache_info->signature == MagickCoreSignature);
1106 if (IsEventLogging() != MagickFalse)
1107 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1108 cache_info->filename);
1109 LockSemaphoreInfo(cache_info->semaphore);
1110 cache_info->reference_count--;
1111 if (cache_info->reference_count != 0)
1113 UnlockSemaphoreInfo(cache_info->semaphore);
1114 return((Cache) NULL);
1116 UnlockSemaphoreInfo(cache_info->semaphore);
1117 if (cache_info->debug != MagickFalse)
1120 message[MagickPathExtent];
1122 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1123 cache_info->filename);
1124 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1126 RelinquishPixelCachePixels(cache_info);
1129 cache_info->server_info);
1130 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1131 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1132 cache_info->number_threads);
1133 if (cache_info->random_info != (
RandomInfo *) NULL)
1134 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1136 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1138 RelinquishSemaphoreInfo(&cache_info->semaphore);
1139 cache_info->signature=(~MagickCoreSignature);
1140 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1171static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1173 if (nexus_info->mapped == MagickFalse)
1174 (void) RelinquishAlignedMemory(nexus_info->cache);
1176 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1177 nexus_info->cache=(Quantum *) NULL;
1178 nexus_info->pixels=(Quantum *) NULL;
1179 nexus_info->metacontent=(
void *) NULL;
1180 nexus_info->length=0;
1181 nexus_info->mapped=MagickFalse;
1185 const size_t number_threads)
1190 assert(nexus_info != (
NexusInfo **) NULL);
1191 for (i=0; i < (ssize_t) (2*number_threads); i++)
1193 if (nexus_info[i]->cache != (Quantum *) NULL)
1194 RelinquishCacheNexusPixels(nexus_info[i]);
1195 nexus_info[i]->signature=(~MagickCoreSignature);
1197 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1198 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1227MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1230 *magick_restrict cache_info;
1233 id = GetOpenMPThreadId();
1235 assert(image != (
const Image *) NULL);
1236 assert(image->signature == MagickCoreSignature);
1237 assert(image->cache != (Cache) NULL);
1239 assert(cache_info->signature == MagickCoreSignature);
1240 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1241 (GetAuthenticMetacontentFromHandler) NULL)
1246 metacontent=cache_info->methods.
1247 get_authentic_metacontent_from_handler(image);
1248 return(metacontent);
1250 assert(
id < (
int) cache_info->number_threads);
1251 return(cache_info->nexus_info[
id]->metacontent);
1278static void *GetAuthenticMetacontentFromCache(
const Image *image)
1281 *magick_restrict cache_info;
1284 id = GetOpenMPThreadId();
1286 assert(image != (
const Image *) NULL);
1287 assert(image->signature == MagickCoreSignature);
1288 assert(image->cache != (Cache) NULL);
1290 assert(cache_info->signature == MagickCoreSignature);
1291 assert(
id < (
int) cache_info->number_threads);
1292 return(cache_info->nexus_info[
id]->metacontent);
1295#if defined(MAGICKCORE_OPENCL_SUPPORT)
1324MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1328 *magick_restrict cache_info;
1330 assert(image != (
const Image *) NULL);
1331 assert(device != (
const MagickCLDevice) NULL);
1333 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1335 (void) SyncImagePixelCache((
Image *) image,exception);
1338 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1339 return((cl_mem) NULL);
1340 LockSemaphoreInfo(cache_info->semaphore);
1341 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1342 (cache_info->opencl->device->context != device->context))
1343 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1344 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1346 assert(cache_info->pixels != (Quantum *) NULL);
1347 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1348 cache_info->length);
1350 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1351 RetainOpenCLMemObject(cache_info->opencl->buffer);
1352 UnlockSemaphoreInfo(cache_info->semaphore);
1353 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1354 return((cl_mem) NULL);
1355 assert(cache_info->opencl->pixels == cache_info->pixels);
1356 return(cache_info->opencl->buffer);
1395MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1396 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1400 *magick_restrict cache_info;
1403 *magick_restrict pixels;
1408 assert(image != (
Image *) NULL);
1409 assert(image->signature == MagickCoreSignature);
1410 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1411 nexus_info,exception);
1412 if (pixels == (Quantum *) NULL)
1413 return((Quantum *) NULL);
1415 assert(cache_info->signature == MagickCoreSignature);
1416 if (nexus_info->authentic_pixel_cache != MagickFalse)
1418 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1419 return((Quantum *) NULL);
1420 if (cache_info->metacontent_extent != 0)
1421 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1422 return((Quantum *) NULL);
1449static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1452 *magick_restrict cache_info;
1455 id = GetOpenMPThreadId();
1457 assert(image != (
const Image *) NULL);
1458 assert(image->signature == MagickCoreSignature);
1459 assert(image->cache != (Cache) NULL);
1461 assert(cache_info->signature == MagickCoreSignature);
1462 assert(
id < (
int) cache_info->number_threads);
1463 return(cache_info->nexus_info[
id]->pixels);
1490MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1493 *magick_restrict cache_info;
1496 id = GetOpenMPThreadId();
1498 assert(image != (
const Image *) NULL);
1499 assert(image->signature == MagickCoreSignature);
1500 assert(image->cache != (Cache) NULL);
1502 assert(cache_info->signature == MagickCoreSignature);
1503 if (cache_info->methods.get_authentic_pixels_from_handler !=
1504 (GetAuthenticPixelsFromHandler) NULL)
1505 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1506 assert(
id < (
int) cache_info->number_threads);
1507 return(cache_info->nexus_info[
id]->pixels);
1555MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1556 const ssize_t y,
const size_t columns,
const size_t rows,
1560 *magick_restrict cache_info;
1563 id = GetOpenMPThreadId();
1568 assert(image != (
Image *) NULL);
1569 assert(image->signature == MagickCoreSignature);
1570 assert(image->cache != (Cache) NULL);
1572 assert(cache_info->signature == MagickCoreSignature);
1573 if (cache_info->methods.get_authentic_pixels_handler !=
1574 (GetAuthenticPixelsHandler) NULL)
1576 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1580 assert(
id < (
int) cache_info->number_threads);
1581 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1582 cache_info->nexus_info[
id],exception);
1617static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1618 const ssize_t y,
const size_t columns,
const size_t rows,
1622 *magick_restrict cache_info;
1625 id = GetOpenMPThreadId();
1628 *magick_restrict pixels;
1630 assert(image != (
const Image *) NULL);
1631 assert(image->signature == MagickCoreSignature);
1632 assert(image->cache != (Cache) NULL);
1634 if (cache_info == (Cache) NULL)
1635 return((Quantum *) NULL);
1636 assert(cache_info->signature == MagickCoreSignature);
1637 assert(
id < (
int) cache_info->number_threads);
1638 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1639 cache_info->nexus_info[
id],exception);
1666MagickExport MagickSizeType GetImageExtent(
const Image *image)
1669 *magick_restrict cache_info;
1672 id = GetOpenMPThreadId();
1674 assert(image != (
Image *) NULL);
1675 assert(image->signature == MagickCoreSignature);
1676 if (IsEventLogging() != MagickFalse)
1677 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1678 assert(image->cache != (Cache) NULL);
1680 assert(cache_info->signature == MagickCoreSignature);
1681 assert(
id < (
int) cache_info->number_threads);
1682 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1715static MagickBooleanType GetDynamicThrottlePolicy(
void)
1717 static MagickBooleanType
1718 check_policy = MagickTrue;
1720 static MagickBooleanType
1721 dynamic_throttle = MagickFalse;
1723 if (check_policy != MagickFalse)
1725 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1726 if (value != (
char *) NULL)
1728 dynamic_throttle=IsStringTrue(value);
1729 value=DestroyString(value);
1731 check_policy=MagickFalse;
1733 return(dynamic_throttle);
1736static inline MagickBooleanType ValidatePixelCacheMorphology(
1737 const Image *magick_restrict image)
1740 *magick_restrict cache_info;
1750 p=image->channel_map;
1751 q=cache_info->channel_map;
1752 if ((image->storage_class != cache_info->storage_class) ||
1753 (image->colorspace != cache_info->colorspace) ||
1754 (image->alpha_trait != cache_info->alpha_trait) ||
1755 (image->channels != cache_info->channels) ||
1756 (image->columns != cache_info->columns) ||
1757 (image->rows != cache_info->rows) ||
1758 (image->number_channels != cache_info->number_channels) ||
1759 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1760 (image->metacontent_extent != cache_info->metacontent_extent) ||
1761 (cache_info->nexus_info == (
NexusInfo **) NULL))
1762 return(MagickFalse);
1766static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1770 *magick_restrict cache_info;
1774 status = MagickTrue;
1776 static MagickSizeType
1777 cpu_throttle = MagickResourceInfinity,
1780 if (IsImageTTLExpired(image) != MagickFalse)
1785 (void) ThrowMagickException(exception,GetMagickModule(),
1786 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1787 return((Cache) NULL);
1789 if (cpu_throttle == MagickResourceInfinity)
1790 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1791 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1804#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1805 if (getloadavg(&load_average,1) != 1)
1808 load=MagickMax(load_average-(
double) GetOpenMPMaximumThreads(),0.0);
1809 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1811 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1812 MagickDelay(cpu_throttle);
1814 LockSemaphoreInfo(image->semaphore);
1815 assert(image->cache != (Cache) NULL);
1817#if defined(MAGICKCORE_OPENCL_SUPPORT)
1818 CopyOpenCLBuffer(cache_info);
1820 destroy=MagickFalse;
1821 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1823 LockSemaphoreInfo(cache_info->semaphore);
1824 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1835 clone_image=(*image);
1836 clone_image.semaphore=AcquireSemaphoreInfo();
1837 clone_image.reference_count=1;
1838 clone_image.cache=ClonePixelCache(cache_info);
1839 clone_info=(
CacheInfo *) clone_image.cache;
1840 status=OpenPixelCache(&clone_image,IOMode,exception);
1841 if (status == MagickFalse)
1842 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1845 if (clone != MagickFalse)
1846 status=ClonePixelCacheRepository(clone_info,cache_info,
1848 if (status == MagickFalse)
1849 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1853 image->cache=clone_info;
1856 RelinquishSemaphoreInfo(&clone_image.semaphore);
1858 UnlockSemaphoreInfo(cache_info->semaphore);
1860 if (destroy != MagickFalse)
1861 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1862 if (status != MagickFalse)
1867 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1869 image->type=UndefinedType;
1870 status=OpenPixelCache(image,IOMode,exception);
1872 if (cache_info->file != -1)
1873 (void) ClosePixelCacheOnDisk(cache_info);
1876 UnlockSemaphoreInfo(image->semaphore);
1877 if (status == MagickFalse)
1878 return((Cache) NULL);
1879 return(image->cache);
1905MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1908 *magick_restrict cache_info;
1910 assert(image != (
Image *) NULL);
1911 assert(image->signature == MagickCoreSignature);
1912 assert(image->cache != (Cache) NULL);
1914 assert(cache_info->signature == MagickCoreSignature);
1915 return(cache_info->type);
1949static inline MagickBooleanType CopyPixel(
const Image *image,
1950 const Quantum *source,Quantum *destination)
1955 if (source == (
const Quantum *) NULL)
1957 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1958 destination[GreenPixelChannel]=ClampToQuantum(
1959 image->background_color.green);
1960 destination[BluePixelChannel]=ClampToQuantum(
1961 image->background_color.blue);
1962 destination[BlackPixelChannel]=ClampToQuantum(
1963 image->background_color.black);
1964 destination[AlphaPixelChannel]=ClampToQuantum(
1965 image->background_color.alpha);
1966 return(MagickFalse);
1968 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1970 PixelChannel channel = GetPixelChannelChannel(image,i);
1971 destination[channel]=source[i];
1976MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1977 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1980 *magick_restrict cache_info;
1985 assert(image != (
Image *) NULL);
1986 assert(image->signature == MagickCoreSignature);
1987 assert(image->cache != (Cache) NULL);
1989 assert(cache_info->signature == MagickCoreSignature);
1990 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1991 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1992 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1993 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1994 return(CopyPixel(image,q,pixel));
2028static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2029 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2032 *magick_restrict cache_info;
2035 id = GetOpenMPThreadId();
2040 assert(image != (
const Image *) NULL);
2041 assert(image->signature == MagickCoreSignature);
2042 assert(image->cache != (Cache) NULL);
2044 assert(cache_info->signature == MagickCoreSignature);
2045 assert(
id < (
int) cache_info->number_threads);
2046 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2047 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2049 return(CopyPixel(image,q,pixel));
2083MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2084 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2087 *magick_restrict cache_info;
2090 id = GetOpenMPThreadId();
2095 assert(image != (
const Image *) NULL);
2096 assert(image->signature == MagickCoreSignature);
2097 assert(image->cache != (Cache) NULL);
2099 assert(cache_info->signature == MagickCoreSignature);
2100 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2101 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2102 (GetOneVirtualPixelFromHandler) NULL)
2103 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2104 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2105 assert(
id < (
int) cache_info->number_threads);
2106 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2107 1UL,1UL,cache_info->nexus_info[
id],exception);
2108 return(CopyPixel(image,p,pixel));
2145static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2146 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2150 *magick_restrict cache_info;
2153 id = GetOpenMPThreadId();
2158 assert(image != (
const Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(image->cache != (Cache) NULL);
2162 assert(cache_info->signature == MagickCoreSignature);
2163 assert(
id < (
int) cache_info->number_threads);
2164 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2165 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2166 cache_info->nexus_info[
id],exception);
2167 return(CopyPixel(image,p,pixel));
2204MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2205 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2209 *magick_restrict cache_info;
2212 id = GetOpenMPThreadId();
2217 assert(image != (
const Image *) NULL);
2218 assert(image->signature == MagickCoreSignature);
2219 assert(image->cache != (Cache) NULL);
2221 assert(cache_info->signature == MagickCoreSignature);
2222 assert(
id < (
int) cache_info->number_threads);
2223 GetPixelInfo(image,pixel);
2224 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2225 cache_info->nexus_info[
id],exception);
2226 if (p == (
const Quantum *) NULL)
2227 return(MagickFalse);
2228 GetPixelInfoPixel(image,p,pixel);
2254MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2257 *magick_restrict cache_info;
2259 assert(cache != (Cache) NULL);
2261 assert(cache_info->signature == MagickCoreSignature);
2262 if (IsEventLogging() != MagickFalse)
2263 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2264 cache_info->filename);
2265 return(cache_info->colorspace);
2291MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2294 *magick_restrict cache_info;
2296 assert(image != (
const Image *) NULL);
2297 assert(image->signature == MagickCoreSignature);
2298 assert(image->cache != (Cache) NULL);
2300 assert(cache_info->signature == MagickCoreSignature);
2301 return(cache_info->cache_filename);
2326MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2329 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2330 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2331 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2332 cache_methods->get_virtual_metacontent_from_handler=
2333 GetVirtualMetacontentFromCache;
2334 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2335 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2336 cache_methods->get_authentic_metacontent_from_handler=
2337 GetAuthenticMetacontentFromCache;
2338 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2339 cache_methods->get_one_authentic_pixel_from_handler=
2340 GetOneAuthenticPixelFromCache;
2341 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2342 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2343 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2371MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2375 *magick_restrict cache_info;
2380 assert(cache != NULL);
2382 assert(cache_info->signature == MagickCoreSignature);
2383 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2385 return((MagickSizeType) cache_info->columns*cache_info->rows);
2416MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2420 *magick_restrict cache_info;
2422 assert(image != (
const Image *) NULL);
2423 assert(image->signature == MagickCoreSignature);
2424 assert(image->cache != (Cache) NULL);
2425 assert(length != (MagickSizeType *) NULL);
2426 magick_unreferenced(exception);
2428 assert(cache_info->signature == MagickCoreSignature);
2429 *length=cache_info->length;
2430 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2431 return((
void *) NULL);
2432 return((
void *) cache_info->pixels);
2459MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2462 *magick_restrict cache_info;
2464 assert(cache != (Cache) NULL);
2466 assert(cache_info->signature == MagickCoreSignature);
2467 if (IsEventLogging() != MagickFalse)
2468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2469 cache_info->filename);
2470 return(cache_info->storage_class);
2500MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2504 *magick_restrict cache_info;
2506 assert(image != (
Image *) NULL);
2507 assert(image->signature == MagickCoreSignature);
2508 if (IsEventLogging() != MagickFalse)
2509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2511 assert(cache_info->signature == MagickCoreSignature);
2512 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2513 if (GetImagePixelCacheType(image) == DiskCache)
2514 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2542MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2545 *magick_restrict cache_info;
2547 assert(image != (
Image *) NULL);
2548 assert(image->signature == MagickCoreSignature);
2549 assert(image->cache != (Cache) NULL);
2551 assert(cache_info->signature == MagickCoreSignature);
2552 return(cache_info->virtual_pixel_method);
2578static const void *GetVirtualMetacontentFromCache(
const Image *image)
2581 *magick_restrict cache_info;
2584 id = GetOpenMPThreadId();
2587 *magick_restrict metacontent;
2589 assert(image != (
const Image *) NULL);
2590 assert(image->signature == MagickCoreSignature);
2591 assert(image->cache != (Cache) NULL);
2593 assert(cache_info->signature == MagickCoreSignature);
2594 assert(
id < (
int) cache_info->number_threads);
2595 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2596 cache_info->nexus_info[
id]);
2597 return(metacontent);
2626MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2630 *magick_restrict cache_info;
2632 assert(cache != (Cache) NULL);
2634 assert(cache_info->signature == MagickCoreSignature);
2635 if (cache_info->storage_class == UndefinedClass)
2636 return((
void *) NULL);
2637 return(nexus_info->metacontent);
2664MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2667 *magick_restrict cache_info;
2670 id = GetOpenMPThreadId();
2673 *magick_restrict metacontent;
2675 assert(image != (
const Image *) NULL);
2676 assert(image->signature == MagickCoreSignature);
2677 assert(image->cache != (Cache) NULL);
2679 assert(cache_info->signature == MagickCoreSignature);
2680 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2682 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2684 if (metacontent != (
const void *) NULL)
2685 return(metacontent);
2687 assert(
id < (
int) cache_info->number_threads);
2688 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2689 cache_info->nexus_info[
id]);
2690 return(metacontent);
2733 0, 48, 12, 60, 3, 51, 15, 63,
2734 32, 16, 44, 28, 35, 19, 47, 31,
2735 8, 56, 4, 52, 11, 59, 7, 55,
2736 40, 24, 36, 20, 43, 27, 39, 23,
2737 2, 50, 14, 62, 1, 49, 13, 61,
2738 34, 18, 46, 30, 33, 17, 45, 29,
2739 10, 58, 6, 54, 9, 57, 5, 53,
2740 42, 26, 38, 22, 41, 25, 37, 21
2743static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2748 index=x+DitherMatrix[x & 0x07]-32L;
2751 if (index >= (ssize_t) columns)
2752 return((ssize_t) columns-1L);
2756static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2761 index=y+DitherMatrix[y & 0x07]-32L;
2764 if (index >= (ssize_t) rows)
2765 return((ssize_t) rows-1L);
2769static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2773 if (x >= (ssize_t) columns)
2774 return((ssize_t) (columns-1));
2778static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2782 if (y >= (ssize_t) rows)
2783 return((ssize_t) (rows-1));
2787static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2788 const MagickOffsetType y)
2790 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2791 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2792 return(MagickFalse);
2796static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2801 x=(double) columns*GetPseudoRandomValue(random_info);
2802 return(CastDoubleToSsizeT(x));
2805static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2810 y=(double) rows*GetPseudoRandomValue(random_info);
2811 return(CastDoubleToSsizeT(y));
2814static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2815 const size_t extent)
2820 modulo.quotient=offset;
2824 modulo.quotient=offset/((ssize_t) extent);
2825 modulo.remainder=offset % ((ssize_t) extent);
2827 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2830 modulo.remainder+=((ssize_t) extent);
2835MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2836 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2837 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2841 *magick_restrict cache_info;
2857 *magick_restrict virtual_nexus;
2860 *magick_restrict pixels,
2862 virtual_pixel[MaxPixelChannels];
2873 *magick_restrict virtual_metacontent;
2878 assert(image != (
const Image *) NULL);
2879 assert(image->signature == MagickCoreSignature);
2880 assert(image->cache != (Cache) NULL);
2882 assert(cache_info->signature == MagickCoreSignature);
2883 if (cache_info->type == UndefinedCache)
2884 return((
const Quantum *) NULL);
2885#if defined(MAGICKCORE_OPENCL_SUPPORT)
2886 CopyOpenCLBuffer(cache_info);
2888 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2889 ((image->channels & WriteMaskChannel) != 0) ||
2890 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2891 nexus_info,exception);
2892 if (pixels == (Quantum *) NULL)
2893 return((
const Quantum *) NULL);
2894 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2895 return((
const Quantum *) NULL);
2896 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2897 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2898 return((
const Quantum *) NULL);
2899 offset+=nexus_info->region.x;
2900 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2901 nexus_info->region.width-1L;
2902 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2903 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2904 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2905 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2913 if (nexus_info->authentic_pixel_cache != MagickFalse)
2915 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2916 if (status == MagickFalse)
2917 return((
const Quantum *) NULL);
2918 if (cache_info->metacontent_extent != 0)
2920 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2921 if (status == MagickFalse)
2922 return((
const Quantum *) NULL);
2929 virtual_nexus=nexus_info->virtual_nexus;
2931 s=(
unsigned char *) nexus_info->metacontent;
2932 (void) memset(virtual_pixel,0,cache_info->number_channels*
2933 sizeof(*virtual_pixel));
2934 virtual_metacontent=(
void *) NULL;
2935 switch (virtual_pixel_method)
2937 case BackgroundVirtualPixelMethod:
2938 case BlackVirtualPixelMethod:
2939 case GrayVirtualPixelMethod:
2940 case TransparentVirtualPixelMethod:
2941 case MaskVirtualPixelMethod:
2942 case WhiteVirtualPixelMethod:
2943 case EdgeVirtualPixelMethod:
2944 case CheckerTileVirtualPixelMethod:
2945 case HorizontalTileVirtualPixelMethod:
2946 case VerticalTileVirtualPixelMethod:
2948 if (cache_info->metacontent_extent != 0)
2953 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2954 cache_info->metacontent_extent);
2955 if (virtual_metacontent == (
void *) NULL)
2957 (void) ThrowMagickException(exception,GetMagickModule(),
2958 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2959 return((
const Quantum *) NULL);
2961 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2963 switch (virtual_pixel_method)
2965 case BlackVirtualPixelMethod:
2967 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2968 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2969 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2972 case GrayVirtualPixelMethod:
2974 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2975 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2977 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2980 case TransparentVirtualPixelMethod:
2982 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2983 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2984 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2987 case MaskVirtualPixelMethod:
2988 case WhiteVirtualPixelMethod:
2990 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2991 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2992 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2997 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2999 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
3001 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
3003 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
3005 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3015 for (v=0; v < (ssize_t) rows; v++)
3021 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3022 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3023 y_offset=EdgeY(y_offset,cache_info->rows);
3024 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3030 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
3031 x_offset,(ssize_t) columns-u);
3032 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3033 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3043 length=(MagickSizeType) 1;
3044 switch (virtual_pixel_method)
3046 case EdgeVirtualPixelMethod:
3049 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3050 EdgeX(x_offset,cache_info->columns),
3051 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3053 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3056 case RandomVirtualPixelMethod:
3058 if (cache_info->random_info == (
RandomInfo *) NULL)
3059 cache_info->random_info=AcquireRandomInfo();
3060 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3061 RandomX(cache_info->random_info,cache_info->columns),
3062 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3063 virtual_nexus,exception);
3064 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3067 case DitherVirtualPixelMethod:
3069 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3070 DitherX(x_offset,cache_info->columns),
3071 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3073 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3076 case TileVirtualPixelMethod:
3078 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3079 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3080 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3081 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3083 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3086 case MirrorVirtualPixelMethod:
3088 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3089 if ((x_modulo.quotient & 0x01) == 1L)
3090 x_modulo.remainder=(ssize_t) cache_info->columns-
3091 x_modulo.remainder-1L;
3092 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3093 if ((y_modulo.quotient & 0x01) == 1L)
3094 y_modulo.remainder=(ssize_t) cache_info->rows-
3095 y_modulo.remainder-1L;
3096 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3097 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3099 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3102 case HorizontalTileEdgeVirtualPixelMethod:
3104 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3105 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3106 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3107 virtual_nexus,exception);
3108 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3111 case VerticalTileEdgeVirtualPixelMethod:
3113 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3114 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3115 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3116 virtual_nexus,exception);
3117 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3120 case BackgroundVirtualPixelMethod:
3121 case BlackVirtualPixelMethod:
3122 case GrayVirtualPixelMethod:
3123 case TransparentVirtualPixelMethod:
3124 case MaskVirtualPixelMethod:
3125 case WhiteVirtualPixelMethod:
3128 r=virtual_metacontent;
3131 case CheckerTileVirtualPixelMethod:
3133 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3134 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3135 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3138 r=virtual_metacontent;
3141 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3142 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3144 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3147 case HorizontalTileVirtualPixelMethod:
3149 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3152 r=virtual_metacontent;
3155 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3156 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3157 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3158 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3160 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3163 case VerticalTileVirtualPixelMethod:
3165 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3168 r=virtual_metacontent;
3171 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3172 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3173 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3174 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3176 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3180 if (p == (
const Quantum *) NULL)
3182 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3184 q+=(ptrdiff_t) cache_info->number_channels;
3185 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3187 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3188 s+=(ptrdiff_t) cache_info->metacontent_extent;
3195 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3196 (
size_t) length,1UL,virtual_nexus,exception);
3197 if (p == (
const Quantum *) NULL)
3199 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3200 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3202 q+=(ptrdiff_t) (cache_info->number_channels*length);
3203 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3205 (void) memcpy(s,r,(
size_t) length);
3206 s+=(ptrdiff_t) (length*cache_info->metacontent_extent);
3209 if (u < (ssize_t) columns)
3215 if (virtual_metacontent != (
void *) NULL)
3216 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3217 if (v < (ssize_t) rows)
3218 return((
const Quantum *) NULL);
3256static const Quantum *GetVirtualPixelCache(
const Image *image,
3257 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3258 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3261 *magick_restrict cache_info;
3264 id = GetOpenMPThreadId();
3269 assert(image != (
const Image *) NULL);
3270 assert(image->signature == MagickCoreSignature);
3271 assert(image->cache != (Cache) NULL);
3273 assert(cache_info->signature == MagickCoreSignature);
3274 assert(
id < (
int) cache_info->number_threads);
3275 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3276 cache_info->nexus_info[
id],exception);
3303MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3306 *magick_restrict cache_info;
3309 id = GetOpenMPThreadId();
3311 assert(image != (
const Image *) NULL);
3312 assert(image->signature == MagickCoreSignature);
3313 assert(image->cache != (Cache) NULL);
3315 assert(cache_info->signature == MagickCoreSignature);
3316 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3317 return(cache_info->methods.get_virtual_pixels_handler(image));
3318 assert(
id < (
int) cache_info->number_threads);
3319 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3370MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3371 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3375 *magick_restrict cache_info;
3378 id = GetOpenMPThreadId();
3383 assert(image != (
const Image *) NULL);
3384 assert(image->signature == MagickCoreSignature);
3385 assert(image->cache != (Cache) NULL);
3387 assert(cache_info->signature == MagickCoreSignature);
3388 if (cache_info->methods.get_virtual_pixel_handler !=
3389 (GetVirtualPixelHandler) NULL)
3390 return(cache_info->methods.get_virtual_pixel_handler(image,
3391 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3392 assert(
id < (
int) cache_info->number_threads);
3393 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3394 columns,rows,cache_info->nexus_info[
id],exception);
3421static const Quantum *GetVirtualPixelsCache(
const Image *image)
3424 *magick_restrict cache_info;
3427 id = GetOpenMPThreadId();
3429 assert(image != (
const Image *) NULL);
3430 assert(image->signature == MagickCoreSignature);
3431 assert(image->cache != (Cache) NULL);
3433 assert(cache_info->signature == MagickCoreSignature);
3434 assert(
id < (
int) cache_info->number_threads);
3435 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3464MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3468 *magick_restrict cache_info;
3470 assert(cache != (Cache) NULL);
3472 assert(cache_info->signature == MagickCoreSignature);
3473 if (cache_info->storage_class == UndefinedClass)
3474 return((Quantum *) NULL);
3475 return((
const Quantum *) nexus_info->pixels);
3508static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3509 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3514 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3516 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3517 gamma=MagickSafeReciprocal(gamma);
3518 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3521static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3525 *magick_restrict cache_info;
3537 if (IsEventLogging() != MagickFalse)
3538 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3539 if ((image->channels & CompositeMaskChannel) == 0)
3541 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3544 if (cache_info == (Cache) NULL)
3545 return(MagickFalse);
3546 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3547 nexus_info->region.width,nexus_info->region.height,
3548 nexus_info->virtual_nexus,exception);
3549 q=nexus_info->pixels;
3550 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3551 return(MagickFalse);
3552 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3557 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3565 alpha=(double) GetPixelCompositeMask(image,p);
3566 for (i=0; i < (ssize_t) image->number_channels; i++)
3568 PixelChannel channel = GetPixelChannelChannel(image,i);
3569 PixelTrait traits = GetPixelChannelTraits(image,channel);
3570 if ((traits & UpdatePixelTrait) == 0)
3572 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3574 p+=(ptrdiff_t) GetPixelChannels(image);
3575 q+=(ptrdiff_t) GetPixelChannels(image);
3612static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3613 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3618 if ((count == 0) || (quantum == 0))
3620 length=count*quantum;
3621 if (quantum != (length/count))
3628 return(MagickFalse);
3631static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3640 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3642 if (*cache_info->cache_filename ==
'\0')
3643 file=AcquireUniqueFileResource(cache_info->cache_filename);
3649 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_CLOEXEC | O_BINARY,0);
3654 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CLOEXEC | O_CREAT |
3655 O_BINARY | O_EXCL,S_MODE);
3657 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CLOEXEC | O_BINARY,S_MODE);
3663 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CLOEXEC | O_CREAT | O_BINARY |
3666 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CLOEXEC | O_BINARY,S_MODE);
3671 return(MagickFalse);
3672 (void) AcquireMagickResource(FileResource,1);
3673 if (cache_info->file != -1)
3674 (void) ClosePixelCacheOnDisk(cache_info);
3675 cache_info->file=file;
3676 cache_info->disk_mode=mode;
3680static inline MagickOffsetType WritePixelCacheRegion(
3681 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3682 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3690 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3691 return((MagickOffsetType) -1);
3692 for (i=0; i < (MagickOffsetType) length; i+=count)
3694 count=MagickWrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3695 (MagickSizeType) i,MagickMaxBufferExtent));
3702static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3705 *magick_restrict cache_info;
3711 if (cache_info->debug != MagickFalse)
3714 format[MagickPathExtent],
3715 message[MagickPathExtent];
3717 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3718 (void) FormatLocaleString(message,MagickPathExtent,
3719 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3720 cache_info->cache_filename,cache_info->file,format);
3721 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3723 if (length != (MagickSizeType) ((MagickOffsetType) length))
3724 return(MagickFalse);
3725 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3727 return(MagickFalse);
3728 if ((MagickSizeType) offset < length)
3734 extent=(MagickOffsetType) length-1;
3735 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3738 return(MagickFalse);
3739#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3740 if (cache_info->synchronize != MagickFalse)
3741 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3742 return(MagickFalse);
3745 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3747 return(MagickFalse);
3751static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3755 *magick_restrict cache_info,
3759 format[MagickPathExtent],
3760 message[MagickPathExtent];
3777 assert(image != (
const Image *) NULL);
3778 assert(image->signature == MagickCoreSignature);
3779 assert(image->cache != (Cache) NULL);
3780 if (IsEventLogging() != MagickFalse)
3781 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3782 if (cache_anonymous_memory < 0)
3790 cache_anonymous_memory=0;
3791 value=GetPolicyValue(
"pixel-cache-memory");
3792 if (value == (
char *) NULL)
3793 value=GetPolicyValue(
"cache:memory-map");
3794 if (LocaleCompare(value,
"anonymous") == 0)
3796#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3797 cache_anonymous_memory=1;
3799 (void) ThrowMagickException(exception,GetMagickModule(),
3800 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3801 "`%s' (policy requires anonymous memory mapping)",image->filename);
3804 value=DestroyString(value);
3806 if ((image->columns == 0) || (image->rows == 0))
3807 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3809 assert(cache_info->signature == MagickCoreSignature);
3810 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3811 ((MagickSizeType) image->rows > cache_info->height_limit))
3813 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3814 "WidthOrHeightExceedsLimit",
"`%s' (%.17gx%.17g) > (%.17gx%.17g)",
3815 image->filename, (double) image->columns, (
double) image->rows,
3816 (double) cache_info->width_limit,(
double) cache_info->height_limit);
3817 return(MagickFalse);
3819 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3821 length=GetImageListLength(image);
3822 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3823 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3826 source_info=(*cache_info);
3827 source_info.file=(-1);
3828 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.17g]",
3829 image->filename,(
double) image->scene);
3830 cache_info->storage_class=image->storage_class;
3831 cache_info->colorspace=image->colorspace;
3832 cache_info->alpha_trait=image->alpha_trait;
3833 cache_info->channels=image->channels;
3834 cache_info->rows=image->rows;
3835 cache_info->columns=image->columns;
3836 status=ResetPixelChannelMap(image,exception);
3837 if (status == MagickFalse)
3838 return(MagickFalse);
3839 cache_info->number_channels=GetPixelChannels(image);
3840 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3841 sizeof(*image->channel_map));
3842 cache_info->metacontent_extent=image->metacontent_extent;
3843 cache_info->mode=mode;
3844 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3845 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3846 if (cache_info->metacontent_extent != 0)
3848 if (HeapOverflowCheckAdd(packet_size,cache_info->metacontent_extent) != MagickFalse)
3850 cache_info->storage_class=UndefinedClass;
3851 cache_info->length=0;
3852 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3855 packet_size+=cache_info->metacontent_extent;
3857 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3859 cache_info->storage_class=UndefinedClass;
3860 cache_info->length=0;
3861 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3864 columns=(size_t) (length/cache_info->rows/packet_size);
3865 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3866 ((ssize_t) cache_info->rows < 0))
3868 cache_info->storage_class=UndefinedClass;
3869 cache_info->length=0;
3870 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3873 cache_info->length=length;
3874 if (image->ping != MagickFalse)
3876 cache_info->type=PingCache;
3879 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3880 cache_info->columns*cache_info->rows);
3881 if (cache_info->mode == PersistMode)
3883 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3884 cache_info->metacontent_extent);
3885 if ((status != MagickFalse) &&
3886 (length == (MagickSizeType) ((
size_t) length)) &&
3887 ((cache_info->type == UndefinedCache) ||
3888 (cache_info->type == MemoryCache)))
3890 status=AcquireMagickResource(MemoryResource,cache_info->length);
3891 if (status != MagickFalse)
3894 if (cache_anonymous_memory <= 0)
3896 cache_info->mapped=MagickFalse;
3897 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3898 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3902 cache_info->mapped=MagickTrue;
3903 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3904 cache_info->length);
3906 if (cache_info->pixels == (Quantum *) NULL)
3908 RelinquishMagickResource(MemoryResource,cache_info->length);
3909 cache_info->mapped=source_info.mapped;
3910 cache_info->pixels=source_info.pixels;
3917 cache_info->type=MemoryCache;
3918 cache_info->metacontent=(
void *) NULL;
3919 if (cache_info->metacontent_extent != 0)
3920 cache_info->metacontent=(
void *) (cache_info->pixels+
3921 cache_info->number_channels*number_pixels);
3922 if ((source_info.storage_class != UndefinedClass) &&
3925 status=ClonePixelCacheRepository(cache_info,&source_info,
3927 RelinquishPixelCachePixels(&source_info);
3929 if (cache_info->debug != MagickFalse)
3931 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3932 MagickPathExtent,format);
3933 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3935 (void) FormatLocaleString(message,MagickPathExtent,
3936 "open %s (%s %s, %.17gx%.17gx%.17g %s)",
3937 cache_info->filename,cache_info->mapped != MagickFalse ?
3938 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3939 (double) cache_info->rows,(double)
3940 cache_info->number_channels,format);
3941 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3944 cache_info->storage_class=image->storage_class;
3947 if ((source_info.storage_class != UndefinedClass) &&
3949 RelinquishPixelCachePixels(&source_info);
3950 cache_info->type=UndefinedCache;
3951 return(MagickFalse);
3957 status=AcquireMagickResource(DiskResource,cache_info->length);
3958 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3960 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3968 server_info=AcquireDistributeCacheInfo(exception);
3971 status=OpenDistributePixelCache(server_info,image);
3972 if (status == MagickFalse)
3974 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3975 GetDistributeCacheHostname(server_info));
3976 server_info=DestroyDistributeCacheInfo(server_info);
3984 cache_info->type=DistributedCache;
3985 cache_info->server_info=server_info;
3986 (void) FormatLocaleString(cache_info->cache_filename,
3987 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3990 cache_info->server_info));
3991 if ((source_info.storage_class != UndefinedClass) &&
3994 status=ClonePixelCacheRepository(cache_info,&source_info,
3996 RelinquishPixelCachePixels(&source_info);
3998 if (cache_info->debug != MagickFalse)
4000 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4001 MagickPathExtent,format);
4002 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4004 (void) FormatLocaleString(message,MagickPathExtent,
4005 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",
4006 cache_info->filename,cache_info->cache_filename,
4008 cache_info->server_info),type,(double) cache_info->columns,
4009 (
double) cache_info->rows,(double)
4010 cache_info->number_channels,format);
4011 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4016 if ((source_info.storage_class != UndefinedClass) &&
4018 RelinquishPixelCachePixels(&source_info);
4019 cache_info->type=UndefinedCache;
4020 return(MagickFalse);
4025 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4026 RelinquishPixelCachePixels(&source_info);
4027 cache_info->type=UndefinedCache;
4028 (void) memset(image->channel_map,0,MaxPixelChannels*
4029 sizeof(*image->channel_map));
4030 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4031 "CacheResourcesExhausted",
"`%s'",image->filename);
4032 return(MagickFalse);
4037 if (status == MagickFalse)
4039 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4040 RelinquishPixelCachePixels(&source_info);
4041 cache_info->type=UndefinedCache;
4042 (void) memset(image->channel_map,0,MaxPixelChannels*
4043 sizeof(*image->channel_map));
4044 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4045 "CacheResourcesExhausted",
"`%s'",image->filename);
4046 return(MagickFalse);
4048 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4049 (cache_info->mode != PersistMode))
4051 (void) ClosePixelCacheOnDisk(cache_info);
4052 *cache_info->cache_filename=
'\0';
4054 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4056 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4057 RelinquishPixelCachePixels(&source_info);
4058 cache_info->type=UndefinedCache;
4059 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4061 return(MagickFalse);
4063 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4064 cache_info->length);
4065 if (status == MagickFalse)
4067 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4068 RelinquishPixelCachePixels(&source_info);
4069 cache_info->type=UndefinedCache;
4070 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4072 return(MagickFalse);
4074 cache_info->type=DiskCache;
4075 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4076 cache_info->metacontent_extent);
4077 if (length == (MagickSizeType) ((
size_t) length))
4079 status=AcquireMagickResource(MapResource,cache_info->length);
4080 if (status != MagickFalse)
4082 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4083 cache_info->offset,(
size_t) cache_info->length);
4084 if (cache_info->pixels == (Quantum *) NULL)
4086 cache_info->mapped=source_info.mapped;
4087 cache_info->pixels=source_info.pixels;
4088 RelinquishMagickResource(MapResource,cache_info->length);
4095 (void) ClosePixelCacheOnDisk(cache_info);
4096 cache_info->type=MapCache;
4097 cache_info->mapped=MagickTrue;
4098 cache_info->metacontent=(
void *) NULL;
4099 if (cache_info->metacontent_extent != 0)
4100 cache_info->metacontent=(
void *) (cache_info->pixels+
4101 cache_info->number_channels*number_pixels);
4102 if ((source_info.storage_class != UndefinedClass) &&
4105 status=ClonePixelCacheRepository(cache_info,&source_info,
4107 RelinquishPixelCachePixels(&source_info);
4109 if (cache_info->debug != MagickFalse)
4111 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4112 MagickPathExtent,format);
4113 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4115 (void) FormatLocaleString(message,MagickPathExtent,
4116 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",
4117 cache_info->filename,cache_info->cache_filename,
4118 cache_info->file,type,(
double) cache_info->columns,
4119 (double) cache_info->rows,(
double)
4120 cache_info->number_channels,format);
4121 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4126 if ((source_info.storage_class != UndefinedClass) &&
4128 RelinquishPixelCachePixels(&source_info);
4129 cache_info->type=UndefinedCache;
4130 return(MagickFalse);
4137 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4139 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4140 RelinquishPixelCachePixels(&source_info);
4142 if (cache_info->debug != MagickFalse)
4144 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4145 MagickPathExtent,format);
4146 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4148 (void) FormatLocaleString(message,MagickPathExtent,
4149 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",cache_info->filename,
4150 cache_info->cache_filename,cache_info->file,type,(
double)
4151 cache_info->columns,(double) cache_info->rows,(
double)
4152 cache_info->number_channels,format);
4153 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4157 cache_info->type=UndefinedCache;
4158 return(MagickFalse);
4200MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4201 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4205 *magick_restrict cache_info,
4206 *magick_restrict clone_info;
4214 assert(image != (
Image *) NULL);
4215 assert(image->signature == MagickCoreSignature);
4216 if (IsEventLogging() != MagickFalse)
4217 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4218 assert(image->cache != (
void *) NULL);
4219 assert(filename != (
const char *) NULL);
4220 assert(offset != (MagickOffsetType *) NULL);
4221 page_size=GetMagickPageSize();
4223 assert(cache_info->signature == MagickCoreSignature);
4224#if defined(MAGICKCORE_OPENCL_SUPPORT)
4225 CopyOpenCLBuffer(cache_info);
4227 if (attach != MagickFalse)
4232 if (cache_info->debug != MagickFalse)
4233 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4234 "attach persistent cache");
4235 (void) CopyMagickString(cache_info->cache_filename,filename,
4237 cache_info->type=MapCache;
4238 cache_info->offset=(*offset);
4239 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4240 return(MagickFalse);
4241 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4242 ((MagickOffsetType) cache_info->length % page_size));
4248 status=AcquireMagickResource(DiskResource,cache_info->length);
4249 if (status == MagickFalse)
4251 cache_info->type=UndefinedCache;
4252 (void) memset(image->channel_map,0,MaxPixelChannels*
4253 sizeof(*image->channel_map));
4254 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4255 "CacheResourcesExhausted",
"`%s'",image->filename);
4256 return(MagickFalse);
4258 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4259 clone_info->type=DiskCache;
4260 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4261 clone_info->file=(-1);
4262 clone_info->storage_class=cache_info->storage_class;
4263 clone_info->colorspace=cache_info->colorspace;
4264 clone_info->alpha_trait=cache_info->alpha_trait;
4265 clone_info->channels=cache_info->channels;
4266 clone_info->columns=cache_info->columns;
4267 clone_info->rows=cache_info->rows;
4268 clone_info->number_channels=cache_info->number_channels;
4269 clone_info->metacontent_extent=cache_info->metacontent_extent;
4270 clone_info->mode=PersistMode;
4271 clone_info->length=cache_info->length;
4272 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4273 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4274 clone_info->offset=(*offset);
4275 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4276 if (status != MagickFalse)
4277 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4278 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4279 ((MagickOffsetType) cache_info->length % page_size));
4280 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4322MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4323 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4327 *magick_restrict cache_info;
4336 *magick_restrict pixels;
4341 assert(image != (
const Image *) NULL);
4342 assert(image->signature == MagickCoreSignature);
4343 assert(image->cache != (Cache) NULL);
4344 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4345 if (cache_info == (Cache) NULL)
4346 return((Quantum *) NULL);
4347 assert(cache_info->signature == MagickCoreSignature);
4348 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4349 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4350 (y >= (ssize_t) cache_info->rows))
4352 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4353 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4354 return((Quantum *) NULL);
4356 if ((columns == 0) || (rows == 0) ||
4357 ((MagickSizeType) columns > (MagickSizeType) (cache_info->columns-x)) ||
4358 ((MagickSizeType) rows > (MagickSizeType) (cache_info->rows-y)))
4360 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4361 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4362 return((Quantum *) NULL);
4364 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4365 return((Quantum *) NULL);
4366 offset=y*(MagickOffsetType) cache_info->columns;
4367 if (IsOffsetOverflow(offset,(MagickOffsetType) x) == MagickFalse)
4368 return((Quantum *) NULL);
4371 return((Quantum *) NULL);
4372 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4373 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns;
4374 if (IsOffsetOverflow(offset,(MagickOffsetType) columns-1) == MagickFalse)
4375 return((Quantum *) NULL);
4376 offset+=(MagickOffsetType) columns-1;
4377 if ((MagickSizeType) offset >= number_pixels)
4378 return((Quantum *) NULL);
4382 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4383 ((image->channels & WriteMaskChannel) != 0) ||
4384 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4385 nexus_info,exception);
4422static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4423 const ssize_t y,
const size_t columns,
const size_t rows,
4427 *magick_restrict cache_info;
4430 id = GetOpenMPThreadId();
4433 *magick_restrict pixels;
4435 assert(image != (
const Image *) NULL);
4436 assert(image->signature == MagickCoreSignature);
4437 assert(image->cache != (Cache) NULL);
4439 assert(cache_info->signature == MagickCoreSignature);
4440 assert(
id < (
int) cache_info->number_threads);
4441 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4442 cache_info->nexus_info[
id],exception);
4502MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4503 const ssize_t y,
const size_t columns,
const size_t rows,
4507 *magick_restrict cache_info;
4510 id = GetOpenMPThreadId();
4513 *magick_restrict pixels;
4515 assert(image != (
Image *) NULL);
4516 assert(image->signature == MagickCoreSignature);
4517 assert(image->cache != (Cache) NULL);
4519 assert(cache_info->signature == MagickCoreSignature);
4520 if (cache_info->methods.queue_authentic_pixels_handler !=
4521 (QueueAuthenticPixelsHandler) NULL)
4523 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4524 columns,rows,exception);
4527 assert(
id < (
int) cache_info->number_threads);
4528 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4529 cache_info->nexus_info[
id],exception);
4562static inline MagickOffsetType ReadPixelCacheRegion(
4563 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4564 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4572 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4573 return((MagickOffsetType) -1);
4574 for (i=0; i < (MagickOffsetType) length; i+=count)
4576 count=MagickRead(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4577 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4584static MagickBooleanType ReadPixelCacheMetacontent(
4605 if (cache_info->metacontent_extent == 0)
4606 return(MagickFalse);
4607 if (nexus_info->authentic_pixel_cache != MagickFalse)
4609 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4610 return(MagickFalse);
4611 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4612 nexus_info->region.x;
4613 length=(MagickSizeType) nexus_info->region.width*
4614 cache_info->metacontent_extent;
4615 extent=length*nexus_info->region.height;
4616 rows=nexus_info->region.height;
4618 q=(
unsigned char *) nexus_info->metacontent;
4619 switch (cache_info->type)
4630 if ((cache_info->columns == nexus_info->region.width) &&
4631 (extent == (MagickSizeType) ((
size_t) extent)))
4636 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4637 cache_info->metacontent_extent;
4638 for (y=0; y < (ssize_t) rows; y++)
4640 (void) memcpy(q,p,(
size_t) length);
4641 p+=(ptrdiff_t) (cache_info->metacontent_extent*cache_info->columns);
4642 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4643 nexus_info->region.width);
4652 LockSemaphoreInfo(cache_info->file_semaphore);
4653 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4655 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4656 cache_info->cache_filename);
4657 UnlockSemaphoreInfo(cache_info->file_semaphore);
4658 return(MagickFalse);
4660 if ((cache_info->columns == nexus_info->region.width) &&
4661 (extent <= MagickMaxBufferExtent))
4666 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4667 for (y=0; y < (ssize_t) rows; y++)
4669 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4670 (MagickOffsetType) extent*(MagickOffsetType)
4671 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4672 (MagickOffsetType) cache_info->metacontent_extent,length,
4673 (
unsigned char *) q);
4674 if (count != (MagickOffsetType) length)
4676 offset+=(MagickOffsetType) cache_info->columns;
4677 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4678 nexus_info->region.width);
4680 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4681 (
void) ClosePixelCacheOnDisk(cache_info);
4682 UnlockSemaphoreInfo(cache_info->file_semaphore);
4685 case DistributedCache:
4693 LockSemaphoreInfo(cache_info->file_semaphore);
4694 region=nexus_info->region;
4695 if ((cache_info->columns != nexus_info->region.width) ||
4696 (extent > MagickMaxBufferExtent))
4703 for (y=0; y < (ssize_t) rows; y++)
4706 cache_info->server_info,®ion,length,(
unsigned char *) q);
4707 if (count != (MagickOffsetType) length)
4709 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4710 nexus_info->region.width);
4713 UnlockSemaphoreInfo(cache_info->file_semaphore);
4719 if (y < (ssize_t) rows)
4721 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4722 cache_info->cache_filename);
4723 return(MagickFalse);
4725 if ((cache_info->debug != MagickFalse) &&
4726 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4727 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4728 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(double)
4729 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4730 nexus_info->region.x,(
double) nexus_info->region.y);
4762static MagickBooleanType ReadPixelCachePixels(
4784 if (nexus_info->authentic_pixel_cache != MagickFalse)
4786 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4787 return(MagickFalse);
4788 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4789 if ((offset/(ssize_t) cache_info->columns) != nexus_info->region.y)
4790 return(MagickFalse);
4791 offset+=nexus_info->region.x;
4792 number_channels=cache_info->number_channels;
4793 length=(MagickSizeType) number_channels*nexus_info->region.width*
4795 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4796 return(MagickFalse);
4797 rows=nexus_info->region.height;
4799 if ((extent == 0) || ((extent/length) != rows))
4800 return(MagickFalse);
4802 q=nexus_info->pixels;
4803 switch (cache_info->type)
4814 if ((cache_info->columns == nexus_info->region.width) &&
4815 (extent == (MagickSizeType) ((
size_t) extent)))
4820 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4822 for (y=0; y < (ssize_t) rows; y++)
4824 (void) memcpy(q,p,(
size_t) length);
4825 p+=(ptrdiff_t) (cache_info->number_channels*cache_info->columns);
4826 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4835 LockSemaphoreInfo(cache_info->file_semaphore);
4836 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4838 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4839 cache_info->cache_filename);
4840 UnlockSemaphoreInfo(cache_info->file_semaphore);
4841 return(MagickFalse);
4843 if ((cache_info->columns == nexus_info->region.width) &&
4844 (extent <= MagickMaxBufferExtent))
4849 for (y=0; y < (ssize_t) rows; y++)
4851 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4852 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4853 sizeof(*q),length,(
unsigned char *) q);
4854 if (count != (MagickOffsetType) length)
4856 offset+=(MagickOffsetType) cache_info->columns;
4857 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4859 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4860 (
void) ClosePixelCacheOnDisk(cache_info);
4861 UnlockSemaphoreInfo(cache_info->file_semaphore);
4864 case DistributedCache:
4872 LockSemaphoreInfo(cache_info->file_semaphore);
4873 region=nexus_info->region;
4874 if ((cache_info->columns != nexus_info->region.width) ||
4875 (extent > MagickMaxBufferExtent))
4882 for (y=0; y < (ssize_t) rows; y++)
4885 cache_info->server_info,®ion,length,(
unsigned char *) q);
4886 if (count != (MagickOffsetType) length)
4888 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4891 UnlockSemaphoreInfo(cache_info->file_semaphore);
4897 if (y < (ssize_t) rows)
4899 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4900 cache_info->cache_filename);
4901 return(MagickFalse);
4903 if ((cache_info->debug != MagickFalse) &&
4904 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4905 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4906 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(double)
4907 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4908 nexus_info->region.x,(
double) nexus_info->region.y);
4935MagickPrivate Cache ReferencePixelCache(Cache cache)
4938 *magick_restrict cache_info;
4940 assert(cache != (Cache *) NULL);
4942 assert(cache_info->signature == MagickCoreSignature);
4943 LockSemaphoreInfo(cache_info->semaphore);
4944 cache_info->reference_count++;
4945 UnlockSemaphoreInfo(cache_info->semaphore);
4971MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4974 *magick_restrict cache_info;
4976 assert(image != (
const Image *) NULL);
4977 assert(image->signature == MagickCoreSignature);
4978 assert(image->cache != (Cache) NULL);
4980 assert(cache_info->signature == MagickCoreSignature);
4981 cache_info->number_channels=GetPixelChannels(image);
5002MagickPrivate
void ResetCacheAnonymousMemory(
void)
5004 cache_anonymous_memory=0;
5036MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
5037 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
5045 assert(image != (
Image *) NULL);
5046 assert(image->signature == MagickCoreSignature);
5047 if (IsEventLogging() != MagickFalse)
5048 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5049 assert(image->cache != (
void *) NULL);
5050 extent=(MagickSizeType) columns*rows;
5051 if (extent > ((MagickSizeType) image->columns*image->rows))
5052 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5054 image->columns=columns;
5057 cache_info->columns=columns;
5058 cache_info->rows=rows;
5059 return(SyncImagePixelCache(image,exception));
5086MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5089 *magick_restrict cache_info;
5091 GetOneAuthenticPixelFromHandler
5092 get_one_authentic_pixel_from_handler;
5094 GetOneVirtualPixelFromHandler
5095 get_one_virtual_pixel_from_handler;
5100 assert(cache != (Cache) NULL);
5103 assert(cache_info->signature == MagickCoreSignature);
5104 if (IsEventLogging() != MagickFalse)
5105 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5106 cache_info->filename);
5107 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5108 cache_info->methods.get_virtual_pixel_handler=
5109 cache_methods->get_virtual_pixel_handler;
5110 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5111 cache_info->methods.destroy_pixel_handler=
5112 cache_methods->destroy_pixel_handler;
5113 if (cache_methods->get_virtual_metacontent_from_handler !=
5114 (GetVirtualMetacontentFromHandler) NULL)
5115 cache_info->methods.get_virtual_metacontent_from_handler=
5116 cache_methods->get_virtual_metacontent_from_handler;
5117 if (cache_methods->get_authentic_pixels_handler !=
5118 (GetAuthenticPixelsHandler) NULL)
5119 cache_info->methods.get_authentic_pixels_handler=
5120 cache_methods->get_authentic_pixels_handler;
5121 if (cache_methods->queue_authentic_pixels_handler !=
5122 (QueueAuthenticPixelsHandler) NULL)
5123 cache_info->methods.queue_authentic_pixels_handler=
5124 cache_methods->queue_authentic_pixels_handler;
5125 if (cache_methods->sync_authentic_pixels_handler !=
5126 (SyncAuthenticPixelsHandler) NULL)
5127 cache_info->methods.sync_authentic_pixels_handler=
5128 cache_methods->sync_authentic_pixels_handler;
5129 if (cache_methods->get_authentic_pixels_from_handler !=
5130 (GetAuthenticPixelsFromHandler) NULL)
5131 cache_info->methods.get_authentic_pixels_from_handler=
5132 cache_methods->get_authentic_pixels_from_handler;
5133 if (cache_methods->get_authentic_metacontent_from_handler !=
5134 (GetAuthenticMetacontentFromHandler) NULL)
5135 cache_info->methods.get_authentic_metacontent_from_handler=
5136 cache_methods->get_authentic_metacontent_from_handler;
5137 get_one_virtual_pixel_from_handler=
5138 cache_info->methods.get_one_virtual_pixel_from_handler;
5139 if (get_one_virtual_pixel_from_handler !=
5140 (GetOneVirtualPixelFromHandler) NULL)
5141 cache_info->methods.get_one_virtual_pixel_from_handler=
5142 cache_methods->get_one_virtual_pixel_from_handler;
5143 get_one_authentic_pixel_from_handler=
5144 cache_methods->get_one_authentic_pixel_from_handler;
5145 if (get_one_authentic_pixel_from_handler !=
5146 (GetOneAuthenticPixelFromHandler) NULL)
5147 cache_info->methods.get_one_authentic_pixel_from_handler=
5148 cache_methods->get_one_authentic_pixel_from_handler;
5189static inline MagickBooleanType AcquireCacheNexusPixels(
5190 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5193 if (length != (MagickSizeType) ((
size_t) length))
5195 (void) ThrowMagickException(exception,GetMagickModule(),
5196 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5197 cache_info->filename);
5198 return(MagickFalse);
5200 nexus_info->length=0;
5201 nexus_info->mapped=MagickFalse;
5202 if (cache_anonymous_memory <= 0)
5204 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5206 if (nexus_info->cache != (Quantum *) NULL)
5207 (
void) memset(nexus_info->cache,0,(
size_t) length);
5211 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5212 if (nexus_info->cache != (Quantum *) NULL)
5213 nexus_info->mapped=MagickTrue;
5215 if (nexus_info->cache == (Quantum *) NULL)
5217 (void) ThrowMagickException(exception,GetMagickModule(),
5218 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5219 cache_info->filename);
5220 return(MagickFalse);
5222 nexus_info->length=length;
5226static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5229 if (nexus_info->length < CACHE_LINE_SIZE)
5231 if (mode == ReadMode)
5233 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5237 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5240static Quantum *SetPixelCacheNexusPixels(
5241 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5242 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5243 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5253 assert(cache_info != (
const CacheInfo *) NULL);
5254 assert(cache_info->signature == MagickCoreSignature);
5255 if (cache_info->type == UndefinedCache)
5256 return((Quantum *) NULL);
5257 assert(nexus_info->signature == MagickCoreSignature);
5258 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5259 if ((width == 0) || (height == 0))
5261 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5262 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5263 return((Quantum *) NULL);
5265 if (((MagickSizeType) width > cache_info->width_limit) ||
5266 ((MagickSizeType) height > cache_info->height_limit))
5268 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5269 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5270 return((Quantum *) NULL);
5272 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5273 (IsValidPixelOffset(y,height) == MagickFalse))
5275 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5276 "InvalidPixel",
"`%s'",cache_info->filename);
5277 return((Quantum *) NULL);
5279 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5280 (buffered == MagickFalse))
5282 if (((x >= 0) && (y >= 0) &&
5283 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5284 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5285 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5293 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5294 return((Quantum *) NULL);
5295 offset=y*(MagickOffsetType) cache_info->columns+x;
5296 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5297 cache_info->number_channels*offset;
5298 nexus_info->metacontent=(
void *) NULL;
5299 if (cache_info->metacontent_extent != 0)
5300 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5301 offset*(MagickOffsetType) cache_info->metacontent_extent;
5302 nexus_info->region.width=width;
5303 nexus_info->region.height=height;
5304 nexus_info->region.x=x;
5305 nexus_info->region.y=y;
5306 nexus_info->authentic_pixel_cache=MagickTrue;
5307 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5308 return(nexus_info->pixels);
5314 if (CacheOverflowSanityCheckGetSize(width,height,&number_pixels) != MagickFalse)
5316 (void) ThrowMagickException(exception,GetMagickModule(),
5317 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5318 cache_info->filename);
5319 return((Quantum *) NULL);
5326 packets=MagickMax(number_pixels,MagickMax(cache_info->columns,
5328 if ((CacheOverflowSanityCheckGetSize(packets,cache_info->number_channels,&length) != MagickFalse) ||
5329 (CacheOverflowSanityCheckGetSize(length,
sizeof(*nexus_info->pixels),&length) != MagickFalse))
5331 (void) ThrowMagickException(exception,GetMagickModule(),
5332 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5333 cache_info->filename);
5334 return((Quantum *) NULL);
5336 if (cache_info->metacontent_extent != 0)
5338 if ((CacheOverflowSanityCheckGetSize(number_pixels,cache_info->metacontent_extent,&extent) != MagickFalse) ||
5339 (extent > (MagickSizeType) (~((MagickSizeType) 0))-length))
5341 (void) ThrowMagickException(exception,GetMagickModule(),
5342 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5343 cache_info->filename);
5344 return((Quantum *) NULL);
5350 if (nexus_info->cache == (Quantum *) NULL)
5351 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5353 if (nexus_info->length < length)
5355 RelinquishCacheNexusPixels(nexus_info);
5356 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5358 if (status == MagickFalse)
5359 return((Quantum *) NULL);
5360 nexus_info->pixels=nexus_info->cache;
5361 nexus_info->metacontent=(
void *) NULL;
5362 if (cache_info->metacontent_extent != 0)
5363 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5364 cache_info->number_channels*number_pixels);
5365 nexus_info->region.width=width;
5366 nexus_info->region.height=height;
5367 nexus_info->region.x=x;
5368 nexus_info->region.y=y;
5369 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5370 MagickTrue : MagickFalse;
5371 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5372 return(nexus_info->pixels);
5405static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5409 *magick_restrict image_view;
5417 assert(image != (
Image *) NULL);
5418 assert(image->signature == MagickCoreSignature);
5419 if (IsEventLogging() != MagickFalse)
5420 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5421 assert(image->cache != (Cache) NULL);
5422 image->alpha_trait=BlendPixelTrait;
5424 image_view=AcquireVirtualCacheView(image,exception);
5425#if defined(MAGICKCORE_OPENMP_SUPPORT)
5426 #pragma omp parallel for schedule(static) shared(status) \
5427 magick_number_threads(image,image,image->rows,2)
5429 for (y=0; y < (ssize_t) image->rows; y++)
5437 if (status == MagickFalse)
5439 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5440 if (q == (Quantum *) NULL)
5445 for (x=0; x < (ssize_t) image->columns; x++)
5447 SetPixelAlpha(image,alpha,q);
5448 q+=(ptrdiff_t) GetPixelChannels(image);
5450 status=SyncCacheViewAuthenticPixels(image_view,exception);
5452 image_view=DestroyCacheView(image_view);
5456MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5457 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5460 *magick_restrict cache_info;
5465 assert(image != (
Image *) NULL);
5466 assert(image->signature == MagickCoreSignature);
5467 if (IsEventLogging() != MagickFalse)
5468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5469 assert(image->cache != (Cache) NULL);
5471 assert(cache_info->signature == MagickCoreSignature);
5472 method=cache_info->virtual_pixel_method;
5473 cache_info->virtual_pixel_method=virtual_pixel_method;
5474 if ((image->columns != 0) && (image->rows != 0))
5475 switch (virtual_pixel_method)
5477 case BackgroundVirtualPixelMethod:
5479 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5480 ((image->alpha_trait & BlendPixelTrait) == 0))
5481 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5482 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5483 (IsGrayColorspace(image->colorspace) != MagickFalse))
5484 (void) SetImageColorspace(image,sRGBColorspace,exception);
5487 case TransparentVirtualPixelMethod:
5489 if ((image->alpha_trait & BlendPixelTrait) == 0)
5490 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5499#if defined(MAGICKCORE_OPENCL_SUPPORT)
5524static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5526 assert(cache_info != (
CacheInfo *) NULL);
5527 assert(cache_info->signature == MagickCoreSignature);
5528 if ((cache_info->type != MemoryCache) ||
5529 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5534 LockSemaphoreInfo(cache_info->semaphore);
5535 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5536 UnlockSemaphoreInfo(cache_info->semaphore);
5539MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5542 *magick_restrict cache_info;
5544 assert(image != (
const Image *) NULL);
5546 CopyOpenCLBuffer(cache_info);
5579MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5583 *magick_restrict cache_info;
5591 assert(image != (
Image *) NULL);
5592 assert(image->signature == MagickCoreSignature);
5593 if (image->cache == (Cache) NULL)
5594 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5596 assert(cache_info->signature == MagickCoreSignature);
5597 if (cache_info->type == UndefinedCache)
5598 return(MagickFalse);
5599 if ((image->mask_trait & UpdatePixelTrait) != 0)
5601 if (((image->channels & WriteMaskChannel) != 0) &&
5602 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5603 return(MagickFalse);
5604 if (((image->channels & CompositeMaskChannel) != 0) &&
5605 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5606 return(MagickFalse);
5608 if (nexus_info->authentic_pixel_cache != MagickFalse)
5610 if (image->taint == MagickFalse)
5611 image->taint=MagickTrue;
5614 assert(cache_info->signature == MagickCoreSignature);
5615 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5616 if ((cache_info->metacontent_extent != 0) &&
5617 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5618 return(MagickFalse);
5619 if ((status != MagickFalse) && (image->taint == MagickFalse))
5620 image->taint=MagickTrue;
5651static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5655 *magick_restrict cache_info;
5658 id = GetOpenMPThreadId();
5663 assert(image != (
Image *) NULL);
5664 assert(image->signature == MagickCoreSignature);
5665 assert(image->cache != (Cache) NULL);
5667 assert(cache_info->signature == MagickCoreSignature);
5668 assert(
id < (
int) cache_info->number_threads);
5669 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5701MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5705 *magick_restrict cache_info;
5708 id = GetOpenMPThreadId();
5713 assert(image != (
Image *) NULL);
5714 assert(image->signature == MagickCoreSignature);
5715 assert(image->cache != (Cache) NULL);
5717 assert(cache_info->signature == MagickCoreSignature);
5718 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5720 status=cache_info->methods.sync_authentic_pixels_handler(image,
5724 assert(
id < (
int) cache_info->number_threads);
5725 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5757MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5761 *magick_restrict cache_info;
5763 assert(image != (
Image *) NULL);
5765 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5766 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5797static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5817 if (cache_info->metacontent_extent == 0)
5818 return(MagickFalse);
5819 if (nexus_info->authentic_pixel_cache != MagickFalse)
5821 if (nexus_info->metacontent == (
unsigned char *) NULL)
5822 return(MagickFalse);
5823 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5824 return(MagickFalse);
5825 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5826 nexus_info->region.x;
5827 length=(MagickSizeType) nexus_info->region.width*
5828 cache_info->metacontent_extent;
5829 extent=(MagickSizeType) length*nexus_info->region.height;
5830 rows=nexus_info->region.height;
5832 p=(
unsigned char *) nexus_info->metacontent;
5833 switch (cache_info->type)
5844 if ((cache_info->columns == nexus_info->region.width) &&
5845 (extent == (MagickSizeType) ((
size_t) extent)))
5850 q=(
unsigned char *) cache_info->metacontent+offset*
5851 (MagickOffsetType) cache_info->metacontent_extent;
5852 for (y=0; y < (ssize_t) rows; y++)
5854 (void) memcpy(q,p,(
size_t) length);
5855 p+=(ptrdiff_t) (nexus_info->region.width*
5856 cache_info->metacontent_extent);
5857 q+=(ptrdiff_t) (cache_info->columns*cache_info->metacontent_extent);
5866 LockSemaphoreInfo(cache_info->file_semaphore);
5867 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5869 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5870 cache_info->cache_filename);
5871 UnlockSemaphoreInfo(cache_info->file_semaphore);
5872 return(MagickFalse);
5874 if ((cache_info->columns == nexus_info->region.width) &&
5875 (extent <= MagickMaxBufferExtent))
5880 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5881 for (y=0; y < (ssize_t) rows; y++)
5883 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5884 (MagickOffsetType) extent*(MagickOffsetType)
5885 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5886 (MagickOffsetType) cache_info->metacontent_extent,length,
5887 (
const unsigned char *) p);
5888 if (count != (MagickOffsetType) length)
5890 p+=(ptrdiff_t) (cache_info->metacontent_extent*
5891 nexus_info->region.width);
5892 offset+=(MagickOffsetType) cache_info->columns;
5894 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5895 (void) ClosePixelCacheOnDisk(cache_info);
5896 UnlockSemaphoreInfo(cache_info->file_semaphore);
5899 case DistributedCache:
5907 LockSemaphoreInfo(cache_info->file_semaphore);
5908 region=nexus_info->region;
5909 if ((cache_info->columns != nexus_info->region.width) ||
5910 (extent > MagickMaxBufferExtent))
5917 for (y=0; y < (ssize_t) rows; y++)
5920 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5921 if (count != (MagickOffsetType) length)
5923 p+=(ptrdiff_t) (cache_info->metacontent_extent*
5924 nexus_info->region.width);
5927 UnlockSemaphoreInfo(cache_info->file_semaphore);
5933 if (y < (ssize_t) rows)
5935 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5936 cache_info->cache_filename);
5937 return(MagickFalse);
5939 if ((cache_info->debug != MagickFalse) &&
5940 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5941 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5942 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(double)
5943 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5944 nexus_info->region.x,(
double) nexus_info->region.y);
5976static MagickBooleanType WritePixelCachePixels(
5997 if (nexus_info->authentic_pixel_cache != MagickFalse)
5999 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
6000 return(MagickFalse);
6001 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
6002 nexus_info->region.x;
6003 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
6005 extent=length*nexus_info->region.height;
6006 rows=nexus_info->region.height;
6008 p=nexus_info->pixels;
6009 switch (cache_info->type)
6020 if ((cache_info->columns == nexus_info->region.width) &&
6021 (extent == (MagickSizeType) ((
size_t) extent)))
6026 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
6028 for (y=0; y < (ssize_t) rows; y++)
6030 (void) memcpy(q,p,(
size_t) length);
6031 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6032 q+=(ptrdiff_t) (cache_info->number_channels*cache_info->columns);
6041 LockSemaphoreInfo(cache_info->file_semaphore);
6042 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6044 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6045 cache_info->cache_filename);
6046 UnlockSemaphoreInfo(cache_info->file_semaphore);
6047 return(MagickFalse);
6049 if ((cache_info->columns == nexus_info->region.width) &&
6050 (extent <= MagickMaxBufferExtent))
6055 for (y=0; y < (ssize_t) rows; y++)
6057 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6058 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
6059 sizeof(*p),length,(
const unsigned char *) p);
6060 if (count != (MagickOffsetType) length)
6062 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6063 offset+=(MagickOffsetType) cache_info->columns;
6065 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6066 (void) ClosePixelCacheOnDisk(cache_info);
6067 UnlockSemaphoreInfo(cache_info->file_semaphore);
6070 case DistributedCache:
6078 LockSemaphoreInfo(cache_info->file_semaphore);
6079 region=nexus_info->region;
6080 if ((cache_info->columns != nexus_info->region.width) ||
6081 (extent > MagickMaxBufferExtent))
6088 for (y=0; y < (ssize_t) rows; y++)
6091 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6092 if (count != (MagickOffsetType) length)
6094 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6097 UnlockSemaphoreInfo(cache_info->file_semaphore);
6103 if (y < (ssize_t) rows)
6105 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6106 cache_info->cache_filename);
6107 return(MagickFalse);
6109 if ((cache_info->debug != MagickFalse) &&
6110 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6111 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6112 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(double)
6113 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6114 nexus_info->region.x,(
double) nexus_info->region.y);