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)
113 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
117 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
118 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
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,
128 const ssize_t,
const ssize_t,Quantum *,ExceptionInfo *),
129 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
130 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
131 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
133 ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
134 NexusInfo *magick_restrict,ExceptionInfo *),
135 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
136 WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
138 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
142 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
143 const size_t,ExceptionInfo *),
144 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
145 const size_t,ExceptionInfo *),
146 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
147 const ssize_t,
const ssize_t,
const size_t,
const size_t,
148 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
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));
200 if (cache_info == (CacheInfo *) NULL)
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)));
272 if (nexus_info == (NexusInfo **) NULL)
273 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
274 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
275 2*
sizeof(**nexus_info));
276 if (*nexus_info == (NexusInfo *) NULL)
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,
318 ExceptionInfo *exception)
321 *magick_restrict cache_info;
323 assert(image != (
const Image *) NULL);
324 assert(image->signature == MagickCoreSignature);
325 assert(exception != (ExceptionInfo *) NULL);
326 assert(exception->signature == MagickCoreSignature);
327 assert(image->cache != (Cache) NULL);
329 cache_info=(CacheInfo *) image->cache;
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,
419 NexusInfo *nexus_info,ExceptionInfo *exception)
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))
440 cache_info=(CacheInfo *) image->cache;
441 if (cache_info == (CacheInfo *) NULL)
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);
529 cache_info=(
const CacheInfo *) cache;
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);
571 source_info=(CacheInfo *) clone;
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);
577 cache_info=(CacheInfo *) cache;
578 assert(cache_info->signature == MagickCoreSignature);
579 source_info->methods=cache_info->methods;
611static MagickBooleanType ClonePixelCacheOnDisk(
612 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
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(
726 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
727 ExceptionInfo *exception)
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);
748 assert(exception != (ExceptionInfo *) 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);
988 cache_info=(CacheInfo *) image->cache;
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';
1086 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
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);
1104 cache_info=(CacheInfo *) cache;
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);
1127 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1128 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
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;
1184MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
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);
1238 cache_info=(CacheInfo *) image->cache;
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);
1289 cache_info=(CacheInfo *) image->cache;
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,
1325 MagickCLDevice device,ExceptionInfo *exception)
1328 *magick_restrict cache_info;
1330 assert(image != (
const Image *) NULL);
1331 assert(device != (
const MagickCLDevice) NULL);
1332 cache_info=(CacheInfo *) image->cache;
1333 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1335 (void) SyncImagePixelCache((Image *) image,exception);
1336 cache_info=(CacheInfo *) image->cache;
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,
1397 ExceptionInfo *exception)
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);
1414 cache_info=(CacheInfo *) image->cache;
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);
1460 cache_info=(CacheInfo *) image->cache;
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);
1501 cache_info=(CacheInfo *) image->cache;
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,
1557 ExceptionInfo *exception)
1560 *magick_restrict cache_info;
1563 id = GetOpenMPThreadId();
1568 assert(image != (Image *) NULL);
1569 assert(image->signature == MagickCoreSignature);
1570 assert(image->cache != (Cache) NULL);
1571 cache_info=(CacheInfo *) image->cache;
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,
1619 ExceptionInfo *exception)
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);
1633 cache_info=(CacheInfo *) image->cache;
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);
1679 cache_info=(CacheInfo *) image->cache;
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;
1742 const PixelChannelMap
1749 cache_info=(CacheInfo *) image->cache;
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,
1767 ExceptionInfo *exception)
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);
1816 cache_info=(CacheInfo *) image->cache;
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);
1871 cache_info=(CacheInfo *) image->cache;
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);
1913 cache_info=(CacheInfo *) image->cache;
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);
1988 cache_info=(CacheInfo *) image->cache;
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);
2043 cache_info=(CacheInfo *) image->cache;
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);
2098 cache_info=(CacheInfo *) image->cache;
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,
2147 Quantum *pixel,ExceptionInfo *exception)
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);
2161 cache_info=(CacheInfo *) image->cache;
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,
2206 PixelInfo *pixel,ExceptionInfo *exception)
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);
2220 cache_info=(CacheInfo *) image->cache;
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);
2260 cache_info=(CacheInfo *) cache;
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);
2299 cache_info=(CacheInfo *) image->cache;
2300 assert(cache_info->signature == MagickCoreSignature);
2301 return(cache_info->cache_filename);
2326MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2328 assert(cache_methods != (CacheMethods *) NULL);
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,
2372 NexusInfo *magick_restrict nexus_info)
2375 *magick_restrict cache_info;
2380 assert(cache != NULL);
2381 cache_info=(CacheInfo *) cache;
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,
2417 ExceptionInfo *magick_unused(exception))
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);
2427 cache_info=(CacheInfo *) image->cache;
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);
2465 cache_info=(CacheInfo *) cache;
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);
2510 cache_info=(CacheInfo *) image->cache;
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);
2550 cache_info=(CacheInfo *) image->cache;
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);
2592 cache_info=(CacheInfo *) image->cache;
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,
2627 NexusInfo *magick_restrict nexus_info)
2630 *magick_restrict cache_info;
2632 assert(cache != (Cache) NULL);
2633 cache_info=(CacheInfo *) cache;
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);
2678 cache_info=(CacheInfo *) image->cache;
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,
2838 ExceptionInfo *exception)
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);
2881 cache_info=(CacheInfo *) image->cache;
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);
3272 cache_info=(CacheInfo *) image->cache;
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);
3314 cache_info=(CacheInfo *) image->cache;
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,
3372 ExceptionInfo *exception)
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);
3386 cache_info=(CacheInfo *) image->cache;
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);
3432 cache_info=(CacheInfo *) image->cache;
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,
3465 NexusInfo *magick_restrict nexus_info)
3468 *magick_restrict cache_info;
3470 assert(cache != (Cache) NULL);
3471 cache_info=(CacheInfo *) cache;
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,
3522 ExceptionInfo *exception)
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))
3543 cache_info=(CacheInfo *) image->cache;
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;
3710 cache_info=(CacheInfo *) image->cache;
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,
3752 ExceptionInfo *exception)
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);
3808 cache_info=(CacheInfo *) image->cache;
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);
3969 if (server_info != (DistributeCacheInfo *) NULL)
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(
3988 (DistributeCacheInfo *) cache_info->server_info),
3989 GetDistributeCachePort((DistributeCacheInfo *)
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,
4007 GetDistributeCacheFile((DistributeCacheInfo *)
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,
4202 ExceptionInfo *exception)
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();
4222 cache_info=(CacheInfo *) image->cache;
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,
4324 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
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 (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4357 return((Quantum *) NULL);
4358 offset=y*(MagickOffsetType) cache_info->columns;
4359 if (IsOffsetOverflow(offset,(MagickOffsetType) x) == MagickFalse)
4360 return((Quantum *) NULL);
4363 return((Quantum *) NULL);
4364 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4365 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns;
4366 if (IsOffsetOverflow(offset,(MagickOffsetType) columns-1) == MagickFalse)
4367 return((Quantum *) NULL);
4368 offset+=(MagickOffsetType) columns-1;
4369 if ((MagickSizeType) offset >= number_pixels)
4370 return((Quantum *) NULL);
4374 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4375 ((image->channels & WriteMaskChannel) != 0) ||
4376 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4377 nexus_info,exception);
4414static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4415 const ssize_t y,
const size_t columns,
const size_t rows,
4416 ExceptionInfo *exception)
4419 *magick_restrict cache_info;
4422 id = GetOpenMPThreadId();
4425 *magick_restrict pixels;
4427 assert(image != (
const Image *) NULL);
4428 assert(image->signature == MagickCoreSignature);
4429 assert(image->cache != (Cache) NULL);
4430 cache_info=(CacheInfo *) image->cache;
4431 assert(cache_info->signature == MagickCoreSignature);
4432 assert(
id < (
int) cache_info->number_threads);
4433 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4434 cache_info->nexus_info[
id],exception);
4494MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4495 const ssize_t y,
const size_t columns,
const size_t rows,
4496 ExceptionInfo *exception)
4499 *magick_restrict cache_info;
4502 id = GetOpenMPThreadId();
4505 *magick_restrict pixels;
4507 assert(image != (Image *) NULL);
4508 assert(image->signature == MagickCoreSignature);
4509 assert(image->cache != (Cache) NULL);
4510 cache_info=(CacheInfo *) image->cache;
4511 assert(cache_info->signature == MagickCoreSignature);
4512 if (cache_info->methods.queue_authentic_pixels_handler !=
4513 (QueueAuthenticPixelsHandler) NULL)
4515 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4516 columns,rows,exception);
4519 assert(
id < (
int) cache_info->number_threads);
4520 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4521 cache_info->nexus_info[
id],exception);
4554static inline MagickOffsetType ReadPixelCacheRegion(
4555 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4556 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4564 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4565 return((MagickOffsetType) -1);
4566 for (i=0; i < (MagickOffsetType) length; i+=count)
4568 count=MagickRead(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4569 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4576static MagickBooleanType ReadPixelCacheMetacontent(
4577 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4578 ExceptionInfo *exception)
4597 if (cache_info->metacontent_extent == 0)
4598 return(MagickFalse);
4599 if (nexus_info->authentic_pixel_cache != MagickFalse)
4601 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4602 return(MagickFalse);
4603 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4604 nexus_info->region.x;
4605 length=(MagickSizeType) nexus_info->region.width*
4606 cache_info->metacontent_extent;
4607 extent=length*nexus_info->region.height;
4608 rows=nexus_info->region.height;
4610 q=(
unsigned char *) nexus_info->metacontent;
4611 switch (cache_info->type)
4622 if ((cache_info->columns == nexus_info->region.width) &&
4623 (extent == (MagickSizeType) ((
size_t) extent)))
4628 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4629 cache_info->metacontent_extent;
4630 for (y=0; y < (ssize_t) rows; y++)
4632 (void) memcpy(q,p,(
size_t) length);
4633 p+=(ptrdiff_t) (cache_info->metacontent_extent*cache_info->columns);
4634 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4635 nexus_info->region.width);
4644 LockSemaphoreInfo(cache_info->file_semaphore);
4645 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4647 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4648 cache_info->cache_filename);
4649 UnlockSemaphoreInfo(cache_info->file_semaphore);
4650 return(MagickFalse);
4652 if ((cache_info->columns == nexus_info->region.width) &&
4653 (extent <= MagickMaxBufferExtent))
4658 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4659 for (y=0; y < (ssize_t) rows; y++)
4661 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4662 (MagickOffsetType) extent*(MagickOffsetType)
4663 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4664 (MagickOffsetType) cache_info->metacontent_extent,length,
4665 (
unsigned char *) q);
4666 if (count != (MagickOffsetType) length)
4668 offset+=(MagickOffsetType) cache_info->columns;
4669 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4670 nexus_info->region.width);
4672 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4673 (void) ClosePixelCacheOnDisk(cache_info);
4674 UnlockSemaphoreInfo(cache_info->file_semaphore);
4677 case DistributedCache:
4685 LockSemaphoreInfo(cache_info->file_semaphore);
4686 region=nexus_info->region;
4687 if ((cache_info->columns != nexus_info->region.width) ||
4688 (extent > MagickMaxBufferExtent))
4695 for (y=0; y < (ssize_t) rows; y++)
4697 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4698 cache_info->server_info,®ion,length,(
unsigned char *) q);
4699 if (count != (MagickOffsetType) length)
4701 q+=(ptrdiff_t) (cache_info->metacontent_extent*
4702 nexus_info->region.width);
4705 UnlockSemaphoreInfo(cache_info->file_semaphore);
4711 if (y < (ssize_t) rows)
4713 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4714 cache_info->cache_filename);
4715 return(MagickFalse);
4717 if ((cache_info->debug != MagickFalse) &&
4718 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4719 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4720 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
4721 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4722 nexus_info->region.x,(
double) nexus_info->region.y);
4754static MagickBooleanType ReadPixelCachePixels(
4755 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4756 ExceptionInfo *exception)
4776 if (nexus_info->authentic_pixel_cache != MagickFalse)
4778 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4779 return(MagickFalse);
4780 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4781 if ((offset/(ssize_t) cache_info->columns) != nexus_info->region.y)
4782 return(MagickFalse);
4783 offset+=nexus_info->region.x;
4784 number_channels=cache_info->number_channels;
4785 length=(MagickSizeType) number_channels*nexus_info->region.width*
4787 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4788 return(MagickFalse);
4789 rows=nexus_info->region.height;
4791 if ((extent == 0) || ((extent/length) != rows))
4792 return(MagickFalse);
4794 q=nexus_info->pixels;
4795 switch (cache_info->type)
4806 if ((cache_info->columns == nexus_info->region.width) &&
4807 (extent == (MagickSizeType) ((
size_t) extent)))
4812 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4814 for (y=0; y < (ssize_t) rows; y++)
4816 (void) memcpy(q,p,(
size_t) length);
4817 p+=(ptrdiff_t) (cache_info->number_channels*cache_info->columns);
4818 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4827 LockSemaphoreInfo(cache_info->file_semaphore);
4828 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4830 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4831 cache_info->cache_filename);
4832 UnlockSemaphoreInfo(cache_info->file_semaphore);
4833 return(MagickFalse);
4835 if ((cache_info->columns == nexus_info->region.width) &&
4836 (extent <= MagickMaxBufferExtent))
4841 for (y=0; y < (ssize_t) rows; y++)
4843 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4844 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4845 sizeof(*q),length,(
unsigned char *) q);
4846 if (count != (MagickOffsetType) length)
4848 offset+=(MagickOffsetType) cache_info->columns;
4849 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4851 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4852 (void) ClosePixelCacheOnDisk(cache_info);
4853 UnlockSemaphoreInfo(cache_info->file_semaphore);
4856 case DistributedCache:
4864 LockSemaphoreInfo(cache_info->file_semaphore);
4865 region=nexus_info->region;
4866 if ((cache_info->columns != nexus_info->region.width) ||
4867 (extent > MagickMaxBufferExtent))
4874 for (y=0; y < (ssize_t) rows; y++)
4876 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4877 cache_info->server_info,®ion,length,(
unsigned char *) q);
4878 if (count != (MagickOffsetType) length)
4880 q+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
4883 UnlockSemaphoreInfo(cache_info->file_semaphore);
4889 if (y < (ssize_t) rows)
4891 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4892 cache_info->cache_filename);
4893 return(MagickFalse);
4895 if ((cache_info->debug != MagickFalse) &&
4896 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4897 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4898 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
4899 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4900 nexus_info->region.x,(
double) nexus_info->region.y);
4927MagickPrivate Cache ReferencePixelCache(Cache cache)
4930 *magick_restrict cache_info;
4932 assert(cache != (Cache *) NULL);
4933 cache_info=(CacheInfo *) cache;
4934 assert(cache_info->signature == MagickCoreSignature);
4935 LockSemaphoreInfo(cache_info->semaphore);
4936 cache_info->reference_count++;
4937 UnlockSemaphoreInfo(cache_info->semaphore);
4963MagickPrivate
void ResetPixelCacheChannels(Image *image)
4966 *magick_restrict cache_info;
4968 assert(image != (
const Image *) NULL);
4969 assert(image->signature == MagickCoreSignature);
4970 assert(image->cache != (Cache) NULL);
4971 cache_info=(CacheInfo *) image->cache;
4972 assert(cache_info->signature == MagickCoreSignature);
4973 cache_info->number_channels=GetPixelChannels(image);
4994MagickPrivate
void ResetCacheAnonymousMemory(
void)
4996 cache_anonymous_memory=0;
5028MagickExport MagickBooleanType ReshapePixelCache(Image *image,
5029 const size_t columns,
const size_t rows,ExceptionInfo *exception)
5037 assert(image != (Image *) NULL);
5038 assert(image->signature == MagickCoreSignature);
5039 if (IsEventLogging() != MagickFalse)
5040 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5041 assert(image->cache != (
void *) NULL);
5042 extent=(MagickSizeType) columns*rows;
5043 if (extent > ((MagickSizeType) image->columns*image->rows))
5044 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5046 image->columns=columns;
5048 cache_info=(CacheInfo *) image->cache;
5049 cache_info->columns=columns;
5050 cache_info->rows=rows;
5051 return(SyncImagePixelCache(image,exception));
5078MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5081 *magick_restrict cache_info;
5083 GetOneAuthenticPixelFromHandler
5084 get_one_authentic_pixel_from_handler;
5086 GetOneVirtualPixelFromHandler
5087 get_one_virtual_pixel_from_handler;
5092 assert(cache != (Cache) NULL);
5093 assert(cache_methods != (CacheMethods *) NULL);
5094 cache_info=(CacheInfo *) cache;
5095 assert(cache_info->signature == MagickCoreSignature);
5096 if (IsEventLogging() != MagickFalse)
5097 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5098 cache_info->filename);
5099 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5100 cache_info->methods.get_virtual_pixel_handler=
5101 cache_methods->get_virtual_pixel_handler;
5102 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5103 cache_info->methods.destroy_pixel_handler=
5104 cache_methods->destroy_pixel_handler;
5105 if (cache_methods->get_virtual_metacontent_from_handler !=
5106 (GetVirtualMetacontentFromHandler) NULL)
5107 cache_info->methods.get_virtual_metacontent_from_handler=
5108 cache_methods->get_virtual_metacontent_from_handler;
5109 if (cache_methods->get_authentic_pixels_handler !=
5110 (GetAuthenticPixelsHandler) NULL)
5111 cache_info->methods.get_authentic_pixels_handler=
5112 cache_methods->get_authentic_pixels_handler;
5113 if (cache_methods->queue_authentic_pixels_handler !=
5114 (QueueAuthenticPixelsHandler) NULL)
5115 cache_info->methods.queue_authentic_pixels_handler=
5116 cache_methods->queue_authentic_pixels_handler;
5117 if (cache_methods->sync_authentic_pixels_handler !=
5118 (SyncAuthenticPixelsHandler) NULL)
5119 cache_info->methods.sync_authentic_pixels_handler=
5120 cache_methods->sync_authentic_pixels_handler;
5121 if (cache_methods->get_authentic_pixels_from_handler !=
5122 (GetAuthenticPixelsFromHandler) NULL)
5123 cache_info->methods.get_authentic_pixels_from_handler=
5124 cache_methods->get_authentic_pixels_from_handler;
5125 if (cache_methods->get_authentic_metacontent_from_handler !=
5126 (GetAuthenticMetacontentFromHandler) NULL)
5127 cache_info->methods.get_authentic_metacontent_from_handler=
5128 cache_methods->get_authentic_metacontent_from_handler;
5129 get_one_virtual_pixel_from_handler=
5130 cache_info->methods.get_one_virtual_pixel_from_handler;
5131 if (get_one_virtual_pixel_from_handler !=
5132 (GetOneVirtualPixelFromHandler) NULL)
5133 cache_info->methods.get_one_virtual_pixel_from_handler=
5134 cache_methods->get_one_virtual_pixel_from_handler;
5135 get_one_authentic_pixel_from_handler=
5136 cache_methods->get_one_authentic_pixel_from_handler;
5137 if (get_one_authentic_pixel_from_handler !=
5138 (GetOneAuthenticPixelFromHandler) NULL)
5139 cache_info->methods.get_one_authentic_pixel_from_handler=
5140 cache_methods->get_one_authentic_pixel_from_handler;
5181static inline MagickBooleanType AcquireCacheNexusPixels(
5182 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5183 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5185 if (length != (MagickSizeType) ((
size_t) length))
5187 (void) ThrowMagickException(exception,GetMagickModule(),
5188 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5189 cache_info->filename);
5190 return(MagickFalse);
5192 nexus_info->length=0;
5193 nexus_info->mapped=MagickFalse;
5194 if (cache_anonymous_memory <= 0)
5196 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5198 if (nexus_info->cache != (Quantum *) NULL)
5199 (void) memset(nexus_info->cache,0,(
size_t) length);
5203 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5204 if (nexus_info->cache != (Quantum *) NULL)
5205 nexus_info->mapped=MagickTrue;
5207 if (nexus_info->cache == (Quantum *) NULL)
5209 (void) ThrowMagickException(exception,GetMagickModule(),
5210 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5211 cache_info->filename);
5212 return(MagickFalse);
5214 nexus_info->length=length;
5218static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5221 if (nexus_info->length < CACHE_LINE_SIZE)
5223 if (mode == ReadMode)
5225 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5229 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5232static Quantum *SetPixelCacheNexusPixels(
5233 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5234 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5235 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5236 ExceptionInfo *exception)
5245 assert(cache_info != (
const CacheInfo *) NULL);
5246 assert(cache_info->signature == MagickCoreSignature);
5247 if (cache_info->type == UndefinedCache)
5248 return((Quantum *) NULL);
5249 assert(nexus_info->signature == MagickCoreSignature);
5250 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5251 if ((width == 0) || (height == 0))
5253 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5254 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5255 return((Quantum *) NULL);
5257 if (((MagickSizeType) width > cache_info->width_limit) ||
5258 ((MagickSizeType) height > cache_info->height_limit))
5260 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5261 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5262 return((Quantum *) NULL);
5264 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5265 (IsValidPixelOffset(y,height) == MagickFalse))
5267 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5268 "InvalidPixel",
"`%s'",cache_info->filename);
5269 return((Quantum *) NULL);
5271 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5272 (buffered == MagickFalse))
5274 if (((x >= 0) && (y >= 0) &&
5275 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5276 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5277 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5285 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5286 return((Quantum *) NULL);
5287 offset=y*(MagickOffsetType) cache_info->columns+x;
5288 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5289 cache_info->number_channels*offset;
5290 nexus_info->metacontent=(
void *) NULL;
5291 if (cache_info->metacontent_extent != 0)
5292 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5293 offset*(MagickOffsetType) cache_info->metacontent_extent;
5294 nexus_info->region.width=width;
5295 nexus_info->region.height=height;
5296 nexus_info->region.x=x;
5297 nexus_info->region.y=y;
5298 nexus_info->authentic_pixel_cache=MagickTrue;
5299 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5300 return(nexus_info->pixels);
5306 if (CacheOverflowSanityCheckGetSize(width,height,&number_pixels) != MagickFalse)
5308 (void) ThrowMagickException(exception,GetMagickModule(),
5309 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5310 cache_info->filename);
5311 return((Quantum *) NULL);
5318 packets=MagickMax(number_pixels,MagickMax(cache_info->columns,
5320 if ((CacheOverflowSanityCheckGetSize(packets,cache_info->number_channels,&length) != MagickFalse) ||
5321 (CacheOverflowSanityCheckGetSize(length,
sizeof(*nexus_info->pixels),&length) != MagickFalse))
5323 (void) ThrowMagickException(exception,GetMagickModule(),
5324 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5325 cache_info->filename);
5326 return((Quantum *) NULL);
5328 if (cache_info->metacontent_extent != 0)
5330 if ((CacheOverflowSanityCheckGetSize(number_pixels,cache_info->metacontent_extent,&extent) != MagickFalse) ||
5331 (extent > (MagickSizeType) (~((MagickSizeType) 0))-length))
5333 (void) ThrowMagickException(exception,GetMagickModule(),
5334 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5335 cache_info->filename);
5336 return((Quantum *) NULL);
5342 if (nexus_info->cache == (Quantum *) NULL)
5343 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5345 if (nexus_info->length < length)
5347 RelinquishCacheNexusPixels(nexus_info);
5348 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5350 if (status == MagickFalse)
5351 return((Quantum *) NULL);
5352 nexus_info->pixels=nexus_info->cache;
5353 nexus_info->metacontent=(
void *) NULL;
5354 if (cache_info->metacontent_extent != 0)
5355 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5356 cache_info->number_channels*number_pixels);
5357 nexus_info->region.width=width;
5358 nexus_info->region.height=height;
5359 nexus_info->region.x=x;
5360 nexus_info->region.y=y;
5361 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5362 MagickTrue : MagickFalse;
5363 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5364 return(nexus_info->pixels);
5397static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5398 ExceptionInfo *exception)
5401 *magick_restrict image_view;
5409 assert(image != (Image *) NULL);
5410 assert(image->signature == MagickCoreSignature);
5411 if (IsEventLogging() != MagickFalse)
5412 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5413 assert(image->cache != (Cache) NULL);
5414 image->alpha_trait=BlendPixelTrait;
5416 image_view=AcquireVirtualCacheView(image,exception);
5417#if defined(MAGICKCORE_OPENMP_SUPPORT)
5418 #pragma omp parallel for schedule(static) shared(status) \
5419 magick_number_threads(image,image,image->rows,2)
5421 for (y=0; y < (ssize_t) image->rows; y++)
5429 if (status == MagickFalse)
5431 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5432 if (q == (Quantum *) NULL)
5437 for (x=0; x < (ssize_t) image->columns; x++)
5439 SetPixelAlpha(image,alpha,q);
5440 q+=(ptrdiff_t) GetPixelChannels(image);
5442 status=SyncCacheViewAuthenticPixels(image_view,exception);
5444 image_view=DestroyCacheView(image_view);
5448MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5449 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5452 *magick_restrict cache_info;
5457 assert(image != (Image *) NULL);
5458 assert(image->signature == MagickCoreSignature);
5459 if (IsEventLogging() != MagickFalse)
5460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5461 assert(image->cache != (Cache) NULL);
5462 cache_info=(CacheInfo *) image->cache;
5463 assert(cache_info->signature == MagickCoreSignature);
5464 method=cache_info->virtual_pixel_method;
5465 cache_info->virtual_pixel_method=virtual_pixel_method;
5466 if ((image->columns != 0) && (image->rows != 0))
5467 switch (virtual_pixel_method)
5469 case BackgroundVirtualPixelMethod:
5471 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5472 ((image->alpha_trait & BlendPixelTrait) == 0))
5473 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5474 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5475 (IsGrayColorspace(image->colorspace) != MagickFalse))
5476 (void) SetImageColorspace(image,sRGBColorspace,exception);
5479 case TransparentVirtualPixelMethod:
5481 if ((image->alpha_trait & BlendPixelTrait) == 0)
5482 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5491#if defined(MAGICKCORE_OPENCL_SUPPORT)
5516static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5518 assert(cache_info != (CacheInfo *) NULL);
5519 assert(cache_info->signature == MagickCoreSignature);
5520 if ((cache_info->type != MemoryCache) ||
5521 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5526 LockSemaphoreInfo(cache_info->semaphore);
5527 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5528 UnlockSemaphoreInfo(cache_info->semaphore);
5531MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5534 *magick_restrict cache_info;
5536 assert(image != (
const Image *) NULL);
5537 cache_info=(CacheInfo *) image->cache;
5538 CopyOpenCLBuffer(cache_info);
5571MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5572 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5575 *magick_restrict cache_info;
5583 assert(image != (Image *) NULL);
5584 assert(image->signature == MagickCoreSignature);
5585 if (image->cache == (Cache) NULL)
5586 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5587 cache_info=(CacheInfo *) image->cache;
5588 assert(cache_info->signature == MagickCoreSignature);
5589 if (cache_info->type == UndefinedCache)
5590 return(MagickFalse);
5591 if ((image->mask_trait & UpdatePixelTrait) != 0)
5593 if (((image->channels & WriteMaskChannel) != 0) &&
5594 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5595 return(MagickFalse);
5596 if (((image->channels & CompositeMaskChannel) != 0) &&
5597 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5598 return(MagickFalse);
5600 if (nexus_info->authentic_pixel_cache != MagickFalse)
5602 if (image->taint == MagickFalse)
5603 image->taint=MagickTrue;
5606 assert(cache_info->signature == MagickCoreSignature);
5607 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5608 if ((cache_info->metacontent_extent != 0) &&
5609 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5610 return(MagickFalse);
5611 if ((status != MagickFalse) && (image->taint == MagickFalse))
5612 image->taint=MagickTrue;
5643static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5644 ExceptionInfo *exception)
5647 *magick_restrict cache_info;
5650 id = GetOpenMPThreadId();
5655 assert(image != (Image *) NULL);
5656 assert(image->signature == MagickCoreSignature);
5657 assert(image->cache != (Cache) NULL);
5658 cache_info=(CacheInfo *) image->cache;
5659 assert(cache_info->signature == MagickCoreSignature);
5660 assert(
id < (
int) cache_info->number_threads);
5661 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5693MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5694 ExceptionInfo *exception)
5697 *magick_restrict cache_info;
5700 id = GetOpenMPThreadId();
5705 assert(image != (Image *) NULL);
5706 assert(image->signature == MagickCoreSignature);
5707 assert(image->cache != (Cache) NULL);
5708 cache_info=(CacheInfo *) image->cache;
5709 assert(cache_info->signature == MagickCoreSignature);
5710 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5712 status=cache_info->methods.sync_authentic_pixels_handler(image,
5716 assert(
id < (
int) cache_info->number_threads);
5717 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5749MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5750 ExceptionInfo *exception)
5753 *magick_restrict cache_info;
5755 assert(image != (Image *) NULL);
5756 assert(exception != (ExceptionInfo *) NULL);
5757 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5758 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5789static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5790 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5809 if (cache_info->metacontent_extent == 0)
5810 return(MagickFalse);
5811 if (nexus_info->authentic_pixel_cache != MagickFalse)
5813 if (nexus_info->metacontent == (
unsigned char *) NULL)
5814 return(MagickFalse);
5815 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5816 return(MagickFalse);
5817 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5818 nexus_info->region.x;
5819 length=(MagickSizeType) nexus_info->region.width*
5820 cache_info->metacontent_extent;
5821 extent=(MagickSizeType) length*nexus_info->region.height;
5822 rows=nexus_info->region.height;
5824 p=(
unsigned char *) nexus_info->metacontent;
5825 switch (cache_info->type)
5836 if ((cache_info->columns == nexus_info->region.width) &&
5837 (extent == (MagickSizeType) ((
size_t) extent)))
5842 q=(
unsigned char *) cache_info->metacontent+offset*
5843 (MagickOffsetType) cache_info->metacontent_extent;
5844 for (y=0; y < (ssize_t) rows; y++)
5846 (void) memcpy(q,p,(
size_t) length);
5847 p+=(ptrdiff_t) (nexus_info->region.width*
5848 cache_info->metacontent_extent);
5849 q+=(ptrdiff_t) (cache_info->columns*cache_info->metacontent_extent);
5858 LockSemaphoreInfo(cache_info->file_semaphore);
5859 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5861 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5862 cache_info->cache_filename);
5863 UnlockSemaphoreInfo(cache_info->file_semaphore);
5864 return(MagickFalse);
5866 if ((cache_info->columns == nexus_info->region.width) &&
5867 (extent <= MagickMaxBufferExtent))
5872 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5873 for (y=0; y < (ssize_t) rows; y++)
5875 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5876 (MagickOffsetType) extent*(MagickOffsetType)
5877 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5878 (MagickOffsetType) cache_info->metacontent_extent,length,
5879 (
const unsigned char *) p);
5880 if (count != (MagickOffsetType) length)
5882 p+=(ptrdiff_t) (cache_info->metacontent_extent*
5883 nexus_info->region.width);
5884 offset+=(MagickOffsetType) cache_info->columns;
5886 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5887 (void) ClosePixelCacheOnDisk(cache_info);
5888 UnlockSemaphoreInfo(cache_info->file_semaphore);
5891 case DistributedCache:
5899 LockSemaphoreInfo(cache_info->file_semaphore);
5900 region=nexus_info->region;
5901 if ((cache_info->columns != nexus_info->region.width) ||
5902 (extent > MagickMaxBufferExtent))
5909 for (y=0; y < (ssize_t) rows; y++)
5911 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5912 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5913 if (count != (MagickOffsetType) length)
5915 p+=(ptrdiff_t) (cache_info->metacontent_extent*
5916 nexus_info->region.width);
5919 UnlockSemaphoreInfo(cache_info->file_semaphore);
5925 if (y < (ssize_t) rows)
5927 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5928 cache_info->cache_filename);
5929 return(MagickFalse);
5931 if ((cache_info->debug != MagickFalse) &&
5932 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5933 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5934 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
5935 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5936 nexus_info->region.x,(
double) nexus_info->region.y);
5968static MagickBooleanType WritePixelCachePixels(
5969 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5970 ExceptionInfo *exception)
5989 if (nexus_info->authentic_pixel_cache != MagickFalse)
5991 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5992 return(MagickFalse);
5993 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5994 nexus_info->region.x;
5995 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5997 extent=length*nexus_info->region.height;
5998 rows=nexus_info->region.height;
6000 p=nexus_info->pixels;
6001 switch (cache_info->type)
6012 if ((cache_info->columns == nexus_info->region.width) &&
6013 (extent == (MagickSizeType) ((
size_t) extent)))
6018 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
6020 for (y=0; y < (ssize_t) rows; y++)
6022 (void) memcpy(q,p,(
size_t) length);
6023 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6024 q+=(ptrdiff_t) (cache_info->number_channels*cache_info->columns);
6033 LockSemaphoreInfo(cache_info->file_semaphore);
6034 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6036 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6037 cache_info->cache_filename);
6038 UnlockSemaphoreInfo(cache_info->file_semaphore);
6039 return(MagickFalse);
6041 if ((cache_info->columns == nexus_info->region.width) &&
6042 (extent <= MagickMaxBufferExtent))
6047 for (y=0; y < (ssize_t) rows; y++)
6049 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6050 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
6051 sizeof(*p),length,(
const unsigned char *) p);
6052 if (count != (MagickOffsetType) length)
6054 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6055 offset+=(MagickOffsetType) cache_info->columns;
6057 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6058 (void) ClosePixelCacheOnDisk(cache_info);
6059 UnlockSemaphoreInfo(cache_info->file_semaphore);
6062 case DistributedCache:
6070 LockSemaphoreInfo(cache_info->file_semaphore);
6071 region=nexus_info->region;
6072 if ((cache_info->columns != nexus_info->region.width) ||
6073 (extent > MagickMaxBufferExtent))
6080 for (y=0; y < (ssize_t) rows; y++)
6082 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6083 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6084 if (count != (MagickOffsetType) length)
6086 p+=(ptrdiff_t) (cache_info->number_channels*nexus_info->region.width);
6089 UnlockSemaphoreInfo(cache_info->file_semaphore);
6095 if (y < (ssize_t) rows)
6097 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6098 cache_info->cache_filename);
6099 return(MagickFalse);
6101 if ((cache_info->debug != MagickFalse) &&
6102 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6103 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6104 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
6105 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6106 nexus_info->region.x,(
double) nexus_info->region.y);