43 #include "magick/studio.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/cache.h"
47 #include "magick/cache-private.h"
48 #include "magick/color-private.h"
49 #include "magick/colorspace.h"
50 #include "magick/colorspace-private.h"
51 #include "magick/composite-private.h"
52 #include "magick/distribute-cache-private.h"
53 #include "magick/exception.h"
54 #include "magick/exception-private.h"
55 #include "magick/geometry.h"
56 #include "magick/list.h"
57 #include "magick/log.h"
58 #include "magick/magick.h"
59 #include "magick/memory_.h"
60 #include "magick/memory-private.h"
61 #include "magick/nt-base-private.h"
62 #include "magick/option.h"
63 #include "magick/pixel.h"
64 #include "magick/pixel-accessor.h"
65 #include "magick/pixel-private.h"
66 #include "magick/policy.h"
67 #include "magick/quantum.h"
68 #include "magick/random_.h"
69 #include "magick/registry.h"
70 #include "magick/resource_.h"
71 #include "magick/semaphore.h"
72 #include "magick/splay-tree.h"
73 #include "magick/string_.h"
74 #include "magick/string-private.h"
75 #include "magick/thread-private.h"
76 #include "magick/timer-private.h"
77 #include "magick/utility.h"
78 #include "magick/utility-private.h"
79 #if defined(MAGICKCORE_ZLIB_DELEGATE)
86 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
87 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
88 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
103 #if defined(__cplusplus) || defined(c_plusplus)
111 static const IndexPacket
112 *GetVirtualIndexesFromCache(const
Image *);
115 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
117 *GetVirtualPixelsCache(const Image *);
119 static MagickBooleanType
120 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
122 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
123 const ssize_t,const ssize_t,PixelPacket *,ExceptionInfo *),
124 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
125 OpenPixelCacheOnDisk(
CacheInfo *,const MapMode),
126 ReadPixelCacheIndexes(CacheInfo *magick_restrict,
NexusInfo *magick_restrict,
128 ReadPixelCachePixels(CacheInfo *magick_restrict,
NexusInfo *magick_restrict,
130 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
131 WritePixelCacheIndexes(CacheInfo *,
NexusInfo *magick_restrict,
133 WritePixelCachePixels(CacheInfo *,
NexusInfo *magick_restrict,
137 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const
size_t,
138 const
size_t,ExceptionInfo *),
139 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const
size_t,
140 const
size_t,ExceptionInfo *),
141 *SetPixelCacheNexusPixels(const CacheInfo *magick_restrict,const MapMode,
142 const ssize_t,const ssize_t,const
size_t,const
size_t,
143 const MagickBooleanType,
NexusInfo *magick_restrict,ExceptionInfo *)
146 #if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(CacheInfo *magick_restrict);
151 #if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
167 #if defined(MAGICKCORE_OPENCL_SUPPORT)
174 for (i=0; i < (ssize_t) info->event_count; i++)
175 clEnv->library->clReleaseEvent(info->events[i]);
176 info->events=(cl_event *) RelinquishMagickMemory(info->events);
177 DestroySemaphoreInfo(&info->events_semaphore);
178 if (info->buffer != (cl_mem) NULL)
180 clEnv->library->clReleaseMemObject(info->buffer);
181 info->buffer=(cl_mem) NULL;
186 static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
187 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
202 magick_unreferenced(event);
203 magick_unreferenced(event_command_exec_status);
205 clEnv=GetDefaultOpenCLEnv();
206 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
214 status=clEnv->library->clGetEventInfo(info->events[i],
215 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
216 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
218 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
219 &RelinquishPixelCachePixelsDelayed,info);
224 RelinquishMagickResource(MemoryResource,info->length);
225 (void) RelinquishOpenCLCacheInfo(clEnv,info);
226 (void) RelinquishAlignedMemory(pixels);
229 static MagickBooleanType RelinquishOpenCLBuffer(
235 assert(cache_info != (
CacheInfo *) NULL);
238 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
243 cl_uint *event_count)
252 events=(cl_event *) NULL;
253 LockSemaphoreInfo(opencl_info->events_semaphore);
254 *event_count=opencl_info->event_count;
255 if (*event_count > 0)
257 events=AcquireQuantumMemory(*event_count,
sizeof(*events));
258 if (events == (cl_event *) NULL)
262 for (i=0; i < opencl_info->event_count; i++)
263 events[i]=opencl_info->events[i];
266 UnlockSemaphoreInfo(opencl_info->events_semaphore);
271 #if defined(MAGICKCORE_OPENCL_SUPPORT)
297 extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
300 *magick_restrict cache_info;
305 assert(image != (
const Image *) NULL);
306 assert(event != (cl_event) NULL);
309 clEnv=GetDefaultOpenCLEnv();
310 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
312 clEnv->library->clWaitForEvents(1,&event);
315 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
316 if (cache_info->opencl->events == (cl_event *) NULL)
318 cache_info->opencl->events=AcquireMagickMemory(
sizeof(
319 *cache_info->opencl->events));
320 cache_info->opencl->event_count=1;
323 cache_info->opencl->events=ResizeQuantumMemory(cache_info->opencl->events,
324 ++cache_info->opencl->event_count,
sizeof(*cache_info->opencl->events));
325 if (cache_info->opencl->events == (cl_event *) NULL)
326 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
327 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
328 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
354 MagickExport Cache AcquirePixelCache(
const size_t number_threads)
357 *magick_restrict cache_info;
362 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
364 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
365 (void) memset(cache_info,0,
sizeof(*cache_info));
366 cache_info->type=UndefinedCache;
367 cache_info->mode=IOMode;
368 cache_info->disk_mode=IOMode;
369 cache_info->colorspace=sRGBColorspace;
370 cache_info->channels=4;
371 cache_info->file=(-1);
372 cache_info->id=GetMagickThreadId();
373 cache_info->number_threads=number_threads;
374 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
375 cache_info->number_threads=GetOpenMPMaximumThreads();
376 if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
377 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
378 if (cache_info->number_threads == 0)
379 cache_info->number_threads=1;
380 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
381 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
382 if (value != (
const char *) NULL)
384 cache_info->synchronize=IsStringTrue(value);
385 value=DestroyString(value);
387 value=GetPolicyValue(
"cache:synchronize");
388 if (value != (
const char *) NULL)
390 cache_info->synchronize=IsStringTrue(value);
391 value=DestroyString(value);
393 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
394 (MagickSizeType) MAGICK_SSIZE_MAX);
395 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
396 (MagickSizeType) MAGICK_SSIZE_MAX);
397 cache_info->semaphore=AllocateSemaphoreInfo();
398 cache_info->reference_count=1;
399 cache_info->file_semaphore=AllocateSemaphoreInfo();
400 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
401 cache_info->signature=MagickCoreSignature;
402 return((Cache ) cache_info);
427 MagickExport
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
430 **magick_restrict nexus_info;
435 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
436 number_threads,
sizeof(*nexus_info)));
438 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
439 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
440 2*
sizeof(**nexus_info));
442 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
443 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
444 for (i=0; i < (ssize_t) (2*number_threads); i++)
446 nexus_info[i]=(*nexus_info+i);
447 if (i < (ssize_t) number_threads)
448 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
449 nexus_info[i]->signature=MagickCoreSignature;
482 MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
486 *magick_restrict cache_info;
488 assert(image != (
const Image *) NULL);
489 assert(image->signature == MagickCoreSignature);
491 assert(exception->signature == MagickCoreSignature);
492 assert(image->cache != (Cache) NULL);
494 assert(cache_info->signature == MagickCoreSignature);
497 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
498 return((
const void *) NULL);
499 *length=cache_info->length;
500 return((
const void *) cache_info->pixels);
521 MagickExport MagickBooleanType CacheComponentGenesis(
void)
524 cache_semaphore=AllocateSemaphoreInfo();
546 MagickExport
void CacheComponentTerminus(
void)
549 ActivateSemaphoreInfo(&cache_semaphore);
551 DestroySemaphoreInfo(&cache_semaphore);
583 static MagickBooleanType ClipPixelCacheNexus(
Image *image,
587 *magick_restrict cache_info;
593 *magick_restrict nexus_indexes,
594 *magick_restrict indexes;
600 **magick_restrict clip_nexus;
612 if (IsEventLogging() != MagickFalse)
613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
614 if ((image->clip_mask == (
Image *) NULL) ||
615 (image->storage_class == PseudoClass))
617 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
620 if (cache_info == (Cache) NULL)
622 clip_nexus=AcquirePixelCacheNexus(1);
623 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
624 nexus_info->region.width,nexus_info->region.height,
625 nexus_info->virtual_nexus,exception);
626 indexes=nexus_info->virtual_nexus->indexes;
627 q=nexus_info->pixels;
628 nexus_indexes=nexus_info->indexes;
629 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
630 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
631 nexus_info->region.height,clip_nexus[0],exception);
636 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
641 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
646 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
647 if (fabs(mask_alpha) >= MagickEpsilon)
649 SetPixelRed(q,mask_alpha*MagickOver_((MagickRealType) p->red,
650 (MagickRealType) GetPixelOpacity(p),(MagickRealType) q->red,
651 (MagickRealType) GetPixelOpacity(q)));
652 SetPixelGreen(q,mask_alpha*MagickOver_((MagickRealType) p->green,
653 (MagickRealType) GetPixelOpacity(p),(MagickRealType) q->green,
654 (MagickRealType) GetPixelOpacity(q)));
655 SetPixelBlue(q,mask_alpha*MagickOver_((MagickRealType) p->blue,
656 (MagickRealType) GetPixelOpacity(p),(MagickRealType) q->blue,
657 (MagickRealType) GetPixelOpacity(q)));
658 SetPixelOpacity(q,GetPixelOpacity(p));
659 if (cache_info->active_index_channel != MagickFalse)
660 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
668 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
694 MagickExport Cache ClonePixelCache(
const Cache cache)
697 *magick_restrict clone_info;
700 *magick_restrict cache_info;
702 assert(cache != NULL);
704 assert(cache_info->signature == MagickCoreSignature);
705 if (IsEventLogging() != MagickFalse)
706 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
707 cache_info->filename);
708 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
709 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
710 return((Cache ) clone_info);
738 MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
741 *magick_restrict cache_info,
742 *magick_restrict source_info;
744 assert(clone != (Cache) NULL);
746 assert(source_info->signature == MagickCoreSignature);
747 if (IsEventLogging() != MagickFalse)
748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
749 source_info->filename);
750 assert(cache != (Cache) NULL);
752 assert(cache_info->signature == MagickCoreSignature);
753 source_info->methods=cache_info->methods;
785 static MagickBooleanType ClonePixelCacheOnDisk(
806 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
807 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
809 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
810 (lseek(clone_info->file,0,SEEK_SET) < 0))
812 quantum=(size_t) MagickMaxBufferExtent;
813 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
815 #if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
816 if (cache_info->length < 0x7ffff000)
818 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
819 (
size_t) cache_info->length);
820 if (count == (ssize_t) cache_info->length)
822 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
823 (lseek(clone_info->file,0,SEEK_SET) < 0))
827 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
829 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
830 if (buffer == (
unsigned char *) NULL)
831 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
833 while ((count=read(cache_info->file,buffer,quantum)) > 0)
838 number_bytes=write(clone_info->file,buffer,(
size_t) count);
839 if (number_bytes != count)
841 extent+=number_bytes;
843 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
844 if (extent != cache_info->length)
849 static MagickBooleanType ClonePixelCacheRepository(
853 #define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
854 #define cache_number_threads(source,destination,chunk,multithreaded) \
855 num_threads((multithreaded) == 0 ? 1 : \
856 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
857 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
858 MagickMax(MagickMin(GetMagickResourceLimit(ThreadResource),2),1) : \
859 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
865 **magick_restrict cache_nexus,
866 **magick_restrict clone_nexus;
874 assert(cache_info != (
CacheInfo *) NULL);
875 assert(clone_info != (
CacheInfo *) NULL);
877 if (cache_info->type == PingCache)
879 if ((cache_info->storage_class == clone_info->storage_class) &&
880 (cache_info->colorspace == clone_info->colorspace) &&
881 (cache_info->channels == clone_info->channels) &&
882 (cache_info->columns == clone_info->columns) &&
883 (cache_info->rows == clone_info->rows) &&
884 (cache_info->active_index_channel == clone_info->active_index_channel))
889 if (((cache_info->type == MemoryCache) ||
890 (cache_info->type == MapCache)) &&
891 ((clone_info->type == MemoryCache) ||
892 (clone_info->type == MapCache)))
894 (void) memcpy(clone_info->pixels,cache_info->pixels,
895 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
896 if ((cache_info->active_index_channel != MagickFalse) &&
897 (clone_info->active_index_channel != MagickFalse))
898 (void) memcpy(clone_info->indexes,cache_info->indexes,
899 cache_info->columns*cache_info->rows*
900 sizeof(*cache_info->indexes));
903 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
904 return(ClonePixelCacheOnDisk(cache_info,clone_info));
909 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
910 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
911 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
912 sizeof(*cache_info->pixels);
914 #if defined(MAGICKCORE_OPENMP_SUPPORT)
915 #pragma omp parallel for schedule(static) shared(status) \
916 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
918 for (y=0; y < (ssize_t) cache_info->rows; y++)
921 id = GetOpenMPThreadId();
926 if (status == MagickFalse)
928 if (y >= (ssize_t) clone_info->rows)
930 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
931 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
934 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
935 if (status == MagickFalse)
937 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
938 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
941 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
942 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
943 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
945 if ((cache_info->active_index_channel != MagickFalse) &&
946 (clone_info->active_index_channel != MagickFalse))
951 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
952 sizeof(*cache_info->indexes);
953 #if defined(MAGICKCORE_OPENMP_SUPPORT)
954 #pragma omp parallel for schedule(static) shared(status) \
955 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
957 for (y=0; y < (ssize_t) cache_info->rows; y++)
960 id = GetOpenMPThreadId();
965 if (status == MagickFalse)
967 if (y >= (ssize_t) clone_info->rows)
969 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
970 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
973 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
974 if (status == MagickFalse)
976 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
977 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
980 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
981 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
984 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
985 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
986 if (cache_info->debug != MagickFalse)
989 message[MaxTextExtent];
991 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
992 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
993 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
994 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1021 static void DestroyImagePixelCache(
Image *image)
1023 assert(image != (
Image *) NULL);
1024 assert(image->signature == MagickCoreSignature);
1025 if (IsEventLogging() != MagickFalse)
1026 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1027 if (image->cache != (
void *) NULL)
1028 image->cache=DestroyPixelCache(image->cache);
1053 MagickExport
void DestroyImagePixels(
Image *image)
1056 *magick_restrict cache_info;
1058 assert(image != (
const Image *) NULL);
1059 assert(image->signature == MagickCoreSignature);
1060 if (IsEventLogging() != MagickFalse)
1061 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1062 assert(image->cache != (Cache) NULL);
1064 assert(cache_info->signature == MagickCoreSignature);
1065 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1067 cache_info->methods.destroy_pixel_handler(image);
1070 image->cache=DestroyPixelCache(image->cache);
1096 static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1102 if (cache_info->file != -1)
1104 status=close(cache_info->file);
1105 cache_info->file=(-1);
1106 RelinquishMagickResource(FileResource,1);
1108 return(status == -1 ? MagickFalse : MagickTrue);
1111 static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1113 switch (cache_info->type)
1117 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1118 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1119 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1125 if (cache_info->mapped == MagickFalse)
1126 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1127 cache_info->pixels);
1130 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1133 RelinquishMagickResource(MemoryResource,cache_info->length);
1138 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1140 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1141 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1142 *cache_info->cache_filename=
'\0';
1143 RelinquishMagickResource(MapResource,cache_info->length);
1147 if (cache_info->file != -1)
1148 (void) ClosePixelCacheOnDisk(cache_info);
1149 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1150 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1151 *cache_info->cache_filename=
'\0';
1152 RelinquishMagickResource(DiskResource,cache_info->length);
1155 case DistributedCache:
1157 *cache_info->cache_filename=
'\0';
1159 cache_info->server_info);
1165 cache_info->type=UndefinedCache;
1166 cache_info->mapped=MagickFalse;
1167 cache_info->indexes=(IndexPacket *) NULL;
1170 MagickExport Cache DestroyPixelCache(Cache cache)
1173 *magick_restrict cache_info;
1175 assert(cache != (Cache) NULL);
1177 assert(cache_info->signature == MagickCoreSignature);
1178 if (IsEventLogging() != MagickFalse)
1179 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1180 cache_info->filename);
1181 LockSemaphoreInfo(cache_info->semaphore);
1182 cache_info->reference_count--;
1183 if (cache_info->reference_count != 0)
1185 UnlockSemaphoreInfo(cache_info->semaphore);
1186 return((Cache) NULL);
1188 UnlockSemaphoreInfo(cache_info->semaphore);
1189 if (cache_info->debug != MagickFalse)
1192 message[MaxTextExtent];
1194 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1195 cache_info->filename);
1196 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1198 RelinquishPixelCachePixels(cache_info);
1201 cache_info->server_info);
1202 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1203 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1204 cache_info->number_threads);
1205 if (cache_info->random_info != (
RandomInfo *) NULL)
1206 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1208 DestroySemaphoreInfo(&cache_info->file_semaphore);
1210 DestroySemaphoreInfo(&cache_info->semaphore);
1211 cache_info->signature=(~MagickCoreSignature);
1212 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1243 static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1245 if (nexus_info->mapped == MagickFalse)
1246 (void) RelinquishAlignedMemory(nexus_info->cache);
1248 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1251 nexus_info->indexes=(IndexPacket *) NULL;
1252 nexus_info->length=0;
1253 nexus_info->mapped=MagickFalse;
1257 const size_t number_threads)
1262 assert(nexus_info != (
NexusInfo **) NULL);
1263 for (i=0; i < (ssize_t) (2*number_threads); i++)
1266 RelinquishCacheNexusPixels(nexus_info[i]);
1267 nexus_info[i]->signature=(~MagickCoreSignature);
1269 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1270 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1297 static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1300 *magick_restrict cache_info;
1303 id = GetOpenMPThreadId();
1305 assert(image != (
const Image *) NULL);
1306 assert(image->signature == MagickCoreSignature);
1307 assert(image->cache != (Cache) NULL);
1309 assert(cache_info->signature == MagickCoreSignature);
1310 assert(
id < (
int) cache_info->number_threads);
1311 return(cache_info->nexus_info[
id]->indexes);
1339 MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1342 *magick_restrict cache_info;
1345 id = GetOpenMPThreadId();
1347 assert(image != (
const Image *) NULL);
1348 assert(image->signature == MagickCoreSignature);
1349 assert(image->cache != (Cache) NULL);
1351 assert(cache_info->signature == MagickCoreSignature);
1352 if (cache_info->methods.get_authentic_indexes_from_handler !=
1353 (GetAuthenticIndexesFromHandler) NULL)
1354 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1355 assert(
id < (
int) cache_info->number_threads);
1356 return(cache_info->nexus_info[
id]->indexes);
1359 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1383 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1387 *magick_restrict cache_info;
1398 assert(image != (
const Image *) NULL);
1400 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1402 SyncImagePixelCache((
Image *) image,exception);
1405 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1406 return((cl_mem) NULL);
1407 LockSemaphoreInfo(cache_info->semaphore);
1408 clEnv=GetDefaultOpenCLEnv();
1411 assert(cache_info->pixels != NULL);
1412 context=GetOpenCLContext(clEnv);
1414 sizeof(*cache_info->opencl));
1415 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1416 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1417 cache_info->opencl->length=cache_info->length;
1418 cache_info->opencl->pixels=cache_info->pixels;
1419 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1420 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1421 if (status != CL_SUCCESS)
1422 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1425 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1426 UnlockSemaphoreInfo(cache_info->semaphore);
1428 return((cl_mem) NULL);
1429 return(cache_info->opencl->buffer);
1469 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1473 *magick_restrict cache_info;
1476 *magick_restrict pixels;
1481 assert(image != (
Image *) NULL);
1482 assert(image->signature == MagickCoreSignature);
1483 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1484 nexus_info,exception);
1488 assert(cache_info->signature == MagickCoreSignature);
1489 if (nexus_info->authentic_pixel_cache != MagickFalse)
1491 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1493 if (cache_info->active_index_channel != MagickFalse)
1494 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1525 *magick_restrict cache_info;
1528 id = GetOpenMPThreadId();
1530 assert(image != (
const Image *) NULL);
1531 assert(image->signature == MagickCoreSignature);
1532 assert(image->cache != (Cache) NULL);
1534 assert(cache_info->signature == MagickCoreSignature);
1535 assert(
id < (
int) cache_info->number_threads);
1536 return(cache_info->nexus_info[
id]->pixels);
1565 *magick_restrict cache_info;
1568 id = GetOpenMPThreadId();
1570 assert(image != (
const Image *) NULL);
1571 assert(image->signature == MagickCoreSignature);
1572 assert(image->cache != (Cache) NULL);
1574 assert(cache_info->signature == MagickCoreSignature);
1575 if (cache_info->methods.get_authentic_pixels_from_handler !=
1576 (GetAuthenticPixelsFromHandler) NULL)
1577 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1578 assert(
id < (
int) cache_info->number_threads);
1579 return(cache_info->nexus_info[
id]->pixels);
1629 const ssize_t y,
const size_t columns,
const size_t rows,
1633 *magick_restrict cache_info;
1636 id = GetOpenMPThreadId();
1638 assert(image != (
Image *) NULL);
1639 assert(image->signature == MagickCoreSignature);
1640 assert(image->cache != (Cache) NULL);
1642 assert(cache_info->signature == MagickCoreSignature);
1643 if (cache_info->methods.get_authentic_pixels_handler !=
1644 (GetAuthenticPixelsHandler) NULL)
1645 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1647 assert(
id < (
int) cache_info->number_threads);
1648 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1649 cache_info->nexus_info[
id],exception));
1684 const ssize_t y,
const size_t columns,
const size_t rows,
1688 *magick_restrict cache_info;
1691 id = GetOpenMPThreadId();
1693 assert(image != (
const Image *) NULL);
1694 assert(image->signature == MagickCoreSignature);
1695 assert(image->cache != (Cache) NULL);
1697 if (cache_info == (Cache) NULL)
1699 assert(cache_info->signature == MagickCoreSignature);
1700 assert(
id < (
int) cache_info->number_threads);
1701 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1702 cache_info->nexus_info[
id],exception));
1728 MagickExport MagickSizeType GetImageExtent(
const Image *image)
1731 *magick_restrict cache_info;
1734 id = GetOpenMPThreadId();
1736 assert(image != (
Image *) NULL);
1737 assert(image->signature == MagickCoreSignature);
1738 if (IsEventLogging() != MagickFalse)
1739 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1740 assert(image->cache != (Cache) NULL);
1742 assert(cache_info->signature == MagickCoreSignature);
1743 assert(
id < (
int) cache_info->number_threads);
1744 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1747 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1775 extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1776 cl_uint *event_count)
1779 *magick_restrict cache_info;
1784 assert(image != (
const Image *) NULL);
1785 assert(event_count != (cl_uint *) NULL);
1788 events=(cl_event *) NULL;
1790 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1825 static inline MagickBooleanType ValidatePixelCacheMorphology(
1826 const Image *magick_restrict image)
1829 *magick_restrict cache_info;
1835 if ((image->storage_class != cache_info->storage_class) ||
1836 (image->colorspace != cache_info->colorspace) ||
1837 (image->channels != cache_info->channels) ||
1838 (image->columns != cache_info->columns) ||
1839 (image->rows != cache_info->rows) ||
1840 (cache_info->nexus_info == (
NexusInfo **) NULL))
1841 return(MagickFalse);
1845 static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1849 *magick_restrict cache_info;
1855 static MagickSizeType
1856 cache_timelimit = MagickResourceInfinity,
1857 cpu_throttle = MagickResourceInfinity,
1861 if (cpu_throttle == MagickResourceInfinity)
1862 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1863 if ((cpu_throttle != 0) && ((cycles++ % 32) == 0))
1864 MagickDelay(cpu_throttle);
1865 if (cache_epoch == 0)
1870 cache_epoch=GetMagickTime();
1871 cache_timelimit=GetMagickResourceLimit(TimeResource);
1873 if ((cache_timelimit != MagickResourceInfinity) &&
1874 ((MagickSizeType) (GetMagickTime()-cache_epoch) >= cache_timelimit))
1876 #if defined(ECANCELED)
1880 if (cache_info->file != -1)
1881 (void) ClosePixelCacheOnDisk(cache_info);
1882 ThrowFatalException(ResourceLimitFatalError,
"TimeLimitExceeded");
1884 LockSemaphoreInfo(image->semaphore);
1885 assert(image->cache != (Cache) NULL);
1887 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1888 CopyOpenCLBuffer(cache_info);
1890 destroy=MagickFalse;
1891 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1893 LockSemaphoreInfo(cache_info->semaphore);
1894 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1905 clone_image=(*image);
1906 clone_image.semaphore=AllocateSemaphoreInfo();
1907 clone_image.reference_count=1;
1908 clone_image.cache=ClonePixelCache(cache_info);
1909 clone_info=(
CacheInfo *) clone_image.cache;
1910 status=OpenPixelCache(&clone_image,IOMode,exception);
1911 if (status == MagickFalse)
1912 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1915 if (clone != MagickFalse)
1916 status=ClonePixelCacheRepository(clone_info,cache_info,
1918 if (status == MagickFalse)
1919 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1923 image->cache=clone_info;
1926 DestroySemaphoreInfo(&clone_image.semaphore);
1928 UnlockSemaphoreInfo(cache_info->semaphore);
1930 if (destroy != MagickFalse)
1931 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1932 if (status != MagickFalse)
1937 if (image->type != UndefinedType)
1938 image->type=UndefinedType;
1939 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1941 status=OpenPixelCache(image,IOMode,exception);
1943 if (cache_info->file != -1)
1944 (void) ClosePixelCacheOnDisk(cache_info);
1947 UnlockSemaphoreInfo(image->semaphore);
1948 if (status == MagickFalse)
1949 return((Cache) NULL);
1950 return(image->cache);
1977 MagickExport CacheType GetPixelCacheType(
const Image *image)
1979 return(GetImagePixelCacheType(image));
1982 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1985 *magick_restrict cache_info;
1987 assert(image != (
Image *) NULL);
1988 assert(image->signature == MagickCoreSignature);
1989 assert(image->cache != (Cache) NULL);
1991 assert(cache_info->signature == MagickCoreSignature);
1992 return(cache_info->type);
2025 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2029 *magick_restrict cache_info;
2032 *magick_restrict pixels;
2034 assert(image != (
Image *) NULL);
2035 assert(image->signature == MagickCoreSignature);
2036 assert(image->cache != (Cache) NULL);
2038 assert(cache_info->signature == MagickCoreSignature);
2039 *pixel=image->background_color;
2040 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2041 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2042 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2044 return(MagickFalse);
2080 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2084 *magick_restrict cache_info;
2087 id = GetOpenMPThreadId();
2090 *magick_restrict pixels;
2092 assert(image != (
const Image *) NULL);
2093 assert(image->signature == MagickCoreSignature);
2094 assert(image->cache != (Cache) NULL);
2096 assert(cache_info->signature == MagickCoreSignature);
2097 *pixel=image->background_color;
2098 assert(
id < (
int) cache_info->number_threads);
2099 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2100 cache_info->nexus_info[
id],exception);
2102 return(MagickFalse);
2139 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2144 *magick_restrict cache_info;
2147 id = GetOpenMPThreadId();
2150 *magick_restrict indexes;
2153 *magick_restrict pixels;
2155 assert(image != (
const Image *) NULL);
2156 assert(image->signature == MagickCoreSignature);
2157 assert(image->cache != (Cache) NULL);
2159 assert(cache_info->signature == MagickCoreSignature);
2160 assert(
id < (
int) cache_info->number_threads);
2161 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2162 1UL,1UL,cache_info->nexus_info[
id],exception);
2163 GetMagickPixelPacket(image,pixel);
2165 return(MagickFalse);
2166 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2167 SetMagickPixelPacket(image,pixels,indexes,pixel);
2206 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2207 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2211 *magick_restrict cache_info;
2214 id = GetOpenMPThreadId();
2217 *magick_restrict pixels;
2219 assert(image != (
const Image *) NULL);
2220 assert(image->signature == MagickCoreSignature);
2221 assert(image->cache != (Cache) NULL);
2223 assert(cache_info->signature == MagickCoreSignature);
2224 *pixel=image->background_color;
2225 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2226 (GetOneVirtualPixelFromHandler) NULL)
2227 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2228 virtual_pixel_method,x,y,pixel,exception));
2229 assert(
id < (
int) cache_info->number_threads);
2230 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2231 cache_info->nexus_info[
id],exception);
2233 return(MagickFalse);
2269 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2273 *magick_restrict cache_info;
2276 id = GetOpenMPThreadId();
2279 *magick_restrict pixels;
2281 assert(image != (
const Image *) NULL);
2282 assert(image->signature == MagickCoreSignature);
2283 assert(image->cache != (Cache) NULL);
2285 assert(cache_info->signature == MagickCoreSignature);
2286 *pixel=image->background_color;
2287 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2288 (GetOneVirtualPixelFromHandler) NULL)
2289 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2290 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2291 assert(
id < (
int) cache_info->number_threads);
2292 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2293 1UL,1UL,cache_info->nexus_info[
id],exception);
2295 return(MagickFalse);
2334 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2335 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2339 *magick_restrict cache_info;
2342 id = GetOpenMPThreadId();
2345 *magick_restrict pixels;
2347 assert(image != (
const Image *) NULL);
2348 assert(image->signature == MagickCoreSignature);
2349 assert(image->cache != (Cache) NULL);
2351 assert(cache_info->signature == MagickCoreSignature);
2352 assert(
id < (
int) cache_info->number_threads);
2353 *pixel=image->background_color;
2354 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2355 cache_info->nexus_info[
id],exception);
2357 return(MagickFalse);
2387 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2390 *magick_restrict cache_info;
2392 assert(cache != (Cache) NULL);
2394 assert(cache_info->signature == MagickCoreSignature);
2395 if (IsEventLogging() != MagickFalse)
2396 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2397 cache_info->filename);
2398 return(cache_info->channels);
2423 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2426 *magick_restrict cache_info;
2428 assert(cache != (Cache) NULL);
2430 assert(cache_info->signature == MagickCoreSignature);
2431 if (IsEventLogging() != MagickFalse)
2432 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2433 cache_info->filename);
2434 return(cache_info->colorspace);
2460 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2463 *magick_restrict cache_info;
2465 assert(image != (
const Image *) NULL);
2466 assert(image->signature == MagickCoreSignature);
2467 assert(image->cache != (Cache) NULL);
2469 assert(cache_info->signature == MagickCoreSignature);
2470 return(cache_info->cache_filename);
2495 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2498 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2499 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2500 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2501 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2502 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2503 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2504 cache_methods->get_authentic_indexes_from_handler=
2505 GetAuthenticIndexesFromCache;
2506 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2507 cache_methods->get_one_authentic_pixel_from_handler=
2508 GetOneAuthenticPixelFromCache;
2509 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2510 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2511 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2538 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2542 *magick_restrict cache_info;
2547 assert(cache != NULL);
2549 assert(cache_info->signature == MagickCoreSignature);
2550 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2552 return((MagickSizeType) cache_info->columns*cache_info->rows);
2583 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2587 *magick_restrict cache_info;
2589 assert(image != (
const Image *) NULL);
2590 assert(image->signature == MagickCoreSignature);
2591 assert(image->cache != (Cache) NULL);
2592 assert(length != (MagickSizeType *) NULL);
2594 assert(exception->signature == MagickCoreSignature);
2596 assert(cache_info->signature == MagickCoreSignature);
2598 *length=cache_info->length;
2599 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2600 return((
void *) NULL);
2601 return((
void *) cache_info->pixels);
2628 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2631 *magick_restrict cache_info;
2633 assert(cache != (Cache) NULL);
2635 assert(cache_info->signature == MagickCoreSignature);
2636 if (IsEventLogging() != MagickFalse)
2637 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2638 cache_info->filename);
2639 return(cache_info->storage_class);
2669 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2672 assert(image != (
Image *) NULL);
2673 assert(image->signature == MagickCoreSignature);
2674 if (IsEventLogging() != MagickFalse)
2675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2677 if (GetImagePixelCacheType(image) == DiskCache)
2706 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2709 *magick_restrict cache_info;
2711 assert(image != (
Image *) NULL);
2712 assert(image->signature == MagickCoreSignature);
2713 assert(image->cache != (Cache) NULL);
2715 assert(cache_info->signature == MagickCoreSignature);
2716 return(cache_info->virtual_pixel_method);
2742 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2745 *magick_restrict cache_info;
2748 id = GetOpenMPThreadId();
2750 assert(image != (
const Image *) NULL);
2751 assert(image->signature == MagickCoreSignature);
2752 assert(image->cache != (Cache) NULL);
2754 assert(cache_info->signature == MagickCoreSignature);
2755 assert(
id < (
int) cache_info->number_threads);
2756 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2785 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2789 *magick_restrict cache_info;
2791 assert(cache != (Cache) NULL);
2793 assert(cache_info->signature == MagickCoreSignature);
2794 if (cache_info->storage_class == UndefinedClass)
2795 return((IndexPacket *) NULL);
2796 return(nexus_info->indexes);
2824 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2827 *magick_restrict cache_info;
2830 id = GetOpenMPThreadId();
2832 assert(image != (
const Image *) NULL);
2833 assert(image->signature == MagickCoreSignature);
2834 assert(image->cache != (Cache) NULL);
2836 assert(cache_info->signature == MagickCoreSignature);
2837 if (cache_info->methods.get_virtual_indexes_from_handler !=
2838 (GetVirtualIndexesFromHandler) NULL)
2839 return(cache_info->methods.get_virtual_indexes_from_handler(image));
2840 assert(
id < (
int) cache_info->number_threads);
2841 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2884 0, 48, 12, 60, 3, 51, 15, 63,
2885 32, 16, 44, 28, 35, 19, 47, 31,
2886 8, 56, 4, 52, 11, 59, 7, 55,
2887 40, 24, 36, 20, 43, 27, 39, 23,
2888 2, 50, 14, 62, 1, 49, 13, 61,
2889 34, 18, 46, 30, 33, 17, 45, 29,
2890 10, 58, 6, 54, 9, 57, 5, 53,
2891 42, 26, 38, 22, 41, 25, 37, 21
2894 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2899 index=x+DitherMatrix[x & 0x07]-32L;
2902 if (index >= (ssize_t) columns)
2903 return((ssize_t) columns-1L);
2907 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2912 index=y+DitherMatrix[y & 0x07]-32L;
2915 if (index >= (ssize_t) rows)
2916 return((ssize_t) rows-1L);
2920 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2924 if (x >= (ssize_t) columns)
2925 return((ssize_t) (columns-1));
2929 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2933 if (y >= (ssize_t) rows)
2934 return((ssize_t) (rows-1));
2938 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2940 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2943 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2945 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2948 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2949 const size_t extent)
2954 modulo.quotient=offset;
2958 modulo.quotient=offset/((ssize_t) extent);
2959 modulo.remainder=offset % ((ssize_t) extent);
2961 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2964 modulo.remainder+=((ssize_t) extent);
2969 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2970 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2971 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2975 *magick_restrict cache_info;
2978 *magick_restrict virtual_indexes;
2985 *magick_restrict indexes;
2995 *magick_restrict virtual_nexus;
2998 *magick_restrict pixels,
3009 assert(image != (
const Image *) NULL);
3010 assert(image->signature == MagickCoreSignature);
3011 assert(image->cache != (Cache) NULL);
3013 assert(cache_info->signature == MagickCoreSignature);
3014 if (cache_info->type == UndefinedCache)
3016 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3017 CopyOpenCLBuffer(cache_info);
3019 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3020 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3021 MagickTrue : MagickFalse,nexus_info,exception);
3024 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3025 nexus_info->region.x;
3026 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3027 nexus_info->region.width-1L;
3028 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3029 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3030 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3031 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3039 if (nexus_info->authentic_pixel_cache != MagickFalse)
3041 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3042 if (status == MagickFalse)
3044 if ((cache_info->storage_class == PseudoClass) ||
3045 (cache_info->colorspace == CMYKColorspace))
3047 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3048 if (status == MagickFalse)
3056 virtual_nexus=nexus_info->virtual_nexus;
3058 indexes=nexus_info->indexes;
3059 switch (virtual_pixel_method)
3061 case BlackVirtualPixelMethod:
3063 SetPixelRed(&virtual_pixel,0);
3064 SetPixelGreen(&virtual_pixel,0);
3065 SetPixelBlue(&virtual_pixel,0);
3066 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3069 case GrayVirtualPixelMethod:
3071 SetPixelRed(&virtual_pixel,QuantumRange/2);
3072 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3073 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3074 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3077 case TransparentVirtualPixelMethod:
3079 SetPixelRed(&virtual_pixel,0);
3080 SetPixelGreen(&virtual_pixel,0);
3081 SetPixelBlue(&virtual_pixel,0);
3082 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3085 case MaskVirtualPixelMethod:
3086 case WhiteVirtualPixelMethod:
3088 SetPixelRed(&virtual_pixel,QuantumRange);
3089 SetPixelGreen(&virtual_pixel,QuantumRange);
3090 SetPixelBlue(&virtual_pixel,QuantumRange);
3091 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3096 virtual_pixel=image->background_color;
3100 virtual_index=(IndexPacket) 0;
3101 for (v=0; v < (ssize_t) rows; v++)
3107 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3108 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3109 y_offset=EdgeY(y_offset,cache_info->rows);
3110 for (u=0; u < (ssize_t) columns; u+=length)
3116 length=(MagickSizeType) MagickMin(cache_info->columns-x_offset,columns-u);
3117 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3118 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3128 length=(MagickSizeType) 1;
3129 switch (virtual_pixel_method)
3131 case BackgroundVirtualPixelMethod:
3132 case ConstantVirtualPixelMethod:
3133 case BlackVirtualPixelMethod:
3134 case GrayVirtualPixelMethod:
3135 case TransparentVirtualPixelMethod:
3136 case MaskVirtualPixelMethod:
3137 case WhiteVirtualPixelMethod:
3140 virtual_indexes=(&virtual_index);
3143 case EdgeVirtualPixelMethod:
3146 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3147 EdgeX(x_offset,cache_info->columns),
3148 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3150 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3154 case RandomVirtualPixelMethod:
3156 if (cache_info->random_info == (
RandomInfo *) NULL)
3157 cache_info->random_info=AcquireRandomInfo();
3158 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3159 RandomX(cache_info->random_info,cache_info->columns),
3160 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3161 virtual_nexus,exception);
3162 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3166 case DitherVirtualPixelMethod:
3168 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3169 DitherX(x_offset,cache_info->columns),
3170 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3172 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3176 case TileVirtualPixelMethod:
3178 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3179 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3180 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3181 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3183 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3187 case MirrorVirtualPixelMethod:
3189 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3190 if ((x_modulo.quotient & 0x01) == 1L)
3191 x_modulo.remainder=(ssize_t) cache_info->columns-
3192 x_modulo.remainder-1L;
3193 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3194 if ((y_modulo.quotient & 0x01) == 1L)
3195 y_modulo.remainder=(ssize_t) cache_info->rows-
3196 y_modulo.remainder-1L;
3197 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3198 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3200 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3204 case CheckerTileVirtualPixelMethod:
3206 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3207 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3208 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3211 virtual_indexes=(&virtual_index);
3214 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3215 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3217 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3221 case HorizontalTileVirtualPixelMethod:
3223 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3226 virtual_indexes=(&virtual_index);
3229 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3230 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3231 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3232 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3234 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3238 case VerticalTileVirtualPixelMethod:
3240 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3243 virtual_indexes=(&virtual_index);
3246 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3247 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3248 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3249 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3251 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3255 case HorizontalTileEdgeVirtualPixelMethod:
3257 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3258 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3259 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3260 virtual_nexus,exception);
3261 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3265 case VerticalTileEdgeVirtualPixelMethod:
3267 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3268 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3269 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3270 virtual_nexus,exception);
3271 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3279 if ((indexes != (IndexPacket *) NULL) &&
3280 (virtual_indexes != (
const IndexPacket *) NULL))
3281 *indexes++=(*virtual_indexes);
3287 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3288 (
size_t) length,1UL,virtual_nexus,exception);
3291 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3292 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3294 if ((indexes != (IndexPacket *) NULL) &&
3295 (virtual_indexes != (
const IndexPacket *) NULL))
3297 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3298 sizeof(*virtual_indexes));
3302 if (u < (ssize_t) columns)
3308 if (v < (ssize_t) rows)
3348 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3349 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3352 *magick_restrict cache_info;
3355 id = GetOpenMPThreadId();
3357 assert(image != (
const Image *) NULL);
3358 assert(image->signature == MagickCoreSignature);
3359 assert(image->cache != (Cache) NULL);
3361 assert(cache_info->signature == MagickCoreSignature);
3362 assert(
id < (
int) cache_info->number_threads);
3363 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3364 cache_info->nexus_info[
id],exception));
3393 *magick_restrict cache_info;
3396 id = GetOpenMPThreadId();
3398 assert(image != (
const Image *) NULL);
3399 assert(image->signature == MagickCoreSignature);
3400 assert(image->cache != (Cache) NULL);
3402 assert(cache_info->signature == MagickCoreSignature);
3403 if (cache_info->methods.get_virtual_pixels_handler !=
3404 (GetVirtualPixelsHandler) NULL)
3405 return(cache_info->methods.get_virtual_pixels_handler(image));
3406 assert(
id < (
int) cache_info->number_threads);
3407 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3459 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3463 *magick_restrict cache_info;
3466 id = GetOpenMPThreadId();
3468 assert(image != (
const Image *) NULL);
3469 assert(image->signature == MagickCoreSignature);
3470 assert(image->cache != (Cache) NULL);
3472 assert(cache_info->signature == MagickCoreSignature);
3473 if (cache_info->methods.get_virtual_pixel_handler !=
3474 (GetVirtualPixelHandler) NULL)
3475 return(cache_info->methods.get_virtual_pixel_handler(image,
3476 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3477 assert(
id < (
int) cache_info->number_threads);
3478 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3479 columns,rows,cache_info->nexus_info[
id],exception));
3508 *magick_restrict cache_info;
3511 id = GetOpenMPThreadId();
3513 assert(image != (
const Image *) NULL);
3514 assert(image->signature == MagickCoreSignature);
3515 assert(image->cache != (Cache) NULL);
3517 assert(cache_info->signature == MagickCoreSignature);
3518 assert(
id < (
int) cache_info->number_threads);
3519 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3548 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3552 *magick_restrict cache_info;
3554 assert(cache != (Cache) NULL);
3556 assert(cache_info->signature == MagickCoreSignature);
3557 if (cache_info->storage_class == UndefinedClass)
3599 if (fabs((
double) (alpha-TransparentOpacity)) < MagickEpsilon)
3604 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3605 gamma=PerceptibleReciprocal(gamma);
3606 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3607 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3608 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3609 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3610 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3613 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3617 *magick_restrict cache_info;
3623 *magick_restrict nexus_indexes,
3624 *magick_restrict indexes;
3634 **magick_restrict mask_nexus;
3646 if (IsEventLogging() != MagickFalse)
3647 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3648 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3650 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3653 if (cache_info == (Cache) NULL)
3654 return(MagickFalse);
3655 mask_nexus=AcquirePixelCacheNexus(1);
3656 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3657 nexus_info->virtual_nexus,exception);
3658 indexes=nexus_info->virtual_nexus->indexes;
3659 q=nexus_info->pixels;
3660 nexus_indexes=nexus_info->indexes;
3661 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3662 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3663 nexus_info->region.height,mask_nexus[0],&image->exception);
3666 return(MagickFalse);
3668 GetMagickPixelPacket(image,&alpha);
3669 GetMagickPixelPacket(image,&beta);
3670 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3675 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3677 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3678 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3679 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3680 alpha.opacity,&beta);
3681 SetPixelRed(q,ClampToQuantum(beta.red));
3682 SetPixelGreen(q,ClampToQuantum(beta.green));
3683 SetPixelBlue(q,ClampToQuantum(beta.blue));
3684 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3685 if (cache_info->active_index_channel != MagickFalse)
3686 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3693 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3728 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3737 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3739 if (*cache_info->cache_filename ==
'\0')
3740 file=AcquireUniqueFileResource(cache_info->cache_filename);
3746 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3751 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3752 O_BINARY | O_EXCL,S_MODE);
3754 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3760 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3763 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3768 return(MagickFalse);
3769 (void) AcquireMagickResource(FileResource,1);
3770 if (cache_info->file != -1)
3771 (void) ClosePixelCacheOnDisk(cache_info);
3772 cache_info->file=file;
3773 cache_info->disk_mode=mode;
3777 static inline MagickOffsetType WritePixelCacheRegion(
3778 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3779 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3787 #if !defined(MAGICKCORE_HAVE_PWRITE)
3788 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3789 return((MagickOffsetType) -1);
3791 for (i=0; i < (MagickOffsetType) length; i+=count)
3793 #if !defined(MAGICKCORE_HAVE_PWRITE)
3794 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
3797 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
3798 MAGICK_SSIZE_MAX),offset+i);
3810 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3813 *magick_restrict cache_info;
3819 if (cache_info->debug != MagickFalse)
3822 format[MaxTextExtent],
3823 message[MaxTextExtent];
3825 (void) FormatMagickSize(length,MagickFalse,format);
3826 (void) FormatLocaleString(message,MaxTextExtent,
3827 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3828 cache_info->cache_filename,cache_info->file,format);
3829 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3831 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3833 return(MagickFalse);
3834 if ((MagickSizeType) offset < length)
3840 extent=(MagickOffsetType) length-1;
3841 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3844 return(MagickFalse);
3845 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3846 if (cache_info->synchronize != MagickFalse)
3847 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3848 return(MagickFalse);
3851 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3853 return(MagickFalse);
3857 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3861 *magick_restrict cache_info,
3865 format[MaxTextExtent],
3866 message[MaxTextExtent];
3883 assert(image != (
const Image *) NULL);
3884 assert(image->signature == MagickCoreSignature);
3885 assert(image->cache != (Cache) NULL);
3886 if (IsEventLogging() != MagickFalse)
3887 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3888 if (cache_anonymous_memory < 0)
3896 cache_anonymous_memory=0;
3897 value=GetPolicyValue(
"pixel-cache-memory");
3898 if (value == (
char *) NULL)
3899 value=GetPolicyValue(
"cache:memory-map");
3900 if (LocaleCompare(value,
"anonymous") == 0)
3902 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3903 cache_anonymous_memory=1;
3905 (void) ThrowMagickException(exception,GetMagickModule(),
3906 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3907 "'%s' (policy requires anonymous memory mapping)",image->filename);
3910 value=DestroyString(value);
3912 if ((image->columns == 0) || (image->rows == 0))
3913 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3915 assert(cache_info->signature == MagickCoreSignature);
3916 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3917 ((MagickSizeType) image->rows > cache_info->height_limit))
3918 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3920 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3922 length=GetImageListLength(image);
3923 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3924 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3927 source_info=(*cache_info);
3928 source_info.file=(-1);
3929 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3930 image->filename,(
double) image->scene);
3931 cache_info->storage_class=image->storage_class;
3932 cache_info->colorspace=image->colorspace;
3933 cache_info->rows=image->rows;
3934 cache_info->columns=image->columns;
3935 cache_info->channels=image->channels;
3936 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3937 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3938 cache_info->mode=mode;
3939 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3941 if (cache_info->active_index_channel != MagickFalse)
3942 packet_size+=
sizeof(IndexPacket);
3943 length=number_pixels*packet_size;
3944 columns=(size_t) (length/cache_info->rows/packet_size);
3945 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3946 ((ssize_t) cache_info->rows < 0))
3947 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3949 cache_info->length=length;
3950 if (image->ping != MagickFalse)
3952 cache_info->type=PingCache;
3955 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3956 cache_info->columns*cache_info->rows);
3957 if (cache_info->mode == PersistMode)
3959 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3960 if ((status != MagickFalse) &&
3961 (length == (MagickSizeType) ((
size_t) length)) &&
3962 ((cache_info->type == UndefinedCache) ||
3963 (cache_info->type == MemoryCache)))
3965 status=AcquireMagickResource(MemoryResource,cache_info->length);
3966 if (status != MagickFalse)
3969 if (cache_anonymous_memory <= 0)
3971 cache_info->mapped=MagickFalse;
3972 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3973 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3977 cache_info->mapped=MagickTrue;
3978 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3979 cache_info->length);
3983 cache_info->mapped=source_info.mapped;
3984 cache_info->pixels=source_info.pixels;
3991 cache_info->colorspace=image->colorspace;
3992 cache_info->type=MemoryCache;
3993 cache_info->indexes=(IndexPacket *) NULL;
3994 if (cache_info->active_index_channel != MagickFalse)
3995 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
3997 if ((source_info.storage_class != UndefinedClass) &&
4000 status&=ClonePixelCacheRepository(cache_info,&source_info,
4002 RelinquishPixelCachePixels(&source_info);
4004 if (cache_info->debug != MagickFalse)
4006 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4007 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4009 (void) FormatLocaleString(message,MaxTextExtent,
4010 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4011 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4012 type,(
double) cache_info->columns,(double) cache_info->rows,
4014 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4017 cache_info->storage_class=image->storage_class;
4020 cache_info->type=UndefinedCache;
4021 return(MagickFalse);
4027 status=AcquireMagickResource(DiskResource,cache_info->length);
4028 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4030 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4038 server_info=AcquireDistributeCacheInfo(exception);
4041 status=OpenDistributePixelCache(server_info,image);
4042 if (status == MagickFalse)
4044 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4045 GetDistributeCacheHostname(server_info));
4046 server_info=DestroyDistributeCacheInfo(server_info);
4054 cache_info->type=DistributedCache;
4055 cache_info->storage_class=image->storage_class;
4056 cache_info->colorspace=image->colorspace;
4057 cache_info->server_info=server_info;
4058 (void) FormatLocaleString(cache_info->cache_filename,
4059 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4062 cache_info->server_info));
4063 if ((source_info.storage_class != UndefinedClass) &&
4066 status=ClonePixelCacheRepository(cache_info,&source_info,
4068 RelinquishPixelCachePixels(&source_info);
4070 if (cache_info->debug != MagickFalse)
4072 (void) FormatMagickSize(cache_info->length,MagickFalse,
4074 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4076 (void) FormatLocaleString(message,MaxTextExtent,
4077 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4078 cache_info->cache_filename,GetDistributeCacheFile(
4080 (double) cache_info->columns,(
double) cache_info->rows,
4082 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4087 cache_info->type=UndefinedCache;
4088 return(MagickFalse);
4093 cache_info->type=UndefinedCache;
4094 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4095 "CacheResourcesExhausted",
"`%s'",image->filename);
4096 return(MagickFalse);
4101 if (status == MagickFalse)
4103 cache_info->type=UndefinedCache;
4104 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4105 "CacheResourcesExhausted",
"`%s'",image->filename);
4106 return(MagickFalse);
4108 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4109 (cache_info->mode != PersistMode))
4111 (void) ClosePixelCacheOnDisk(cache_info);
4112 *cache_info->cache_filename=
'\0';
4114 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4116 cache_info->type=UndefinedCache;
4117 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4119 return(MagickFalse);
4121 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4122 cache_info->length);
4123 if (status == MagickFalse)
4125 cache_info->type=UndefinedCache;
4126 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4128 return(MagickFalse);
4130 cache_info->storage_class=image->storage_class;
4131 cache_info->colorspace=image->colorspace;
4132 cache_info->type=DiskCache;
4133 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4134 if (length == (MagickSizeType) ((size_t) length))
4136 status=AcquireMagickResource(MapResource,cache_info->length);
4137 if (status != MagickFalse)
4139 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4140 cache_info->offset,(
size_t) cache_info->length);
4143 cache_info->mapped=source_info.mapped;
4144 cache_info->pixels=source_info.pixels;
4145 RelinquishMagickResource(MapResource,cache_info->length);
4152 (void) ClosePixelCacheOnDisk(cache_info);
4153 cache_info->type=MapCache;
4154 cache_info->mapped=MagickTrue;
4155 cache_info->indexes=(IndexPacket *) NULL;
4156 if (cache_info->active_index_channel != MagickFalse)
4157 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4159 if ((source_info.storage_class != UndefinedClass) &&
4162 status=ClonePixelCacheRepository(cache_info,&source_info,
4164 RelinquishPixelCachePixels(&source_info);
4166 if (cache_info->debug != MagickFalse)
4168 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4169 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4171 (void) FormatLocaleString(message,MaxTextExtent,
4172 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4173 cache_info->filename,cache_info->cache_filename,
4174 cache_info->file,type,(
double) cache_info->columns,
4175 (double) cache_info->rows,format);
4176 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4181 cache_info->type=UndefinedCache;
4182 return(MagickFalse);
4189 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4191 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4192 RelinquishPixelCachePixels(&source_info);
4194 if (cache_info->debug != MagickFalse)
4196 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4197 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4199 (void) FormatLocaleString(message,MaxTextExtent,
4200 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4201 cache_info->cache_filename,cache_info->file,type,(
double)
4202 cache_info->columns,(double) cache_info->rows,format);
4203 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4207 cache_info->type=UndefinedCache;
4208 return(MagickFalse);
4250 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4251 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4255 *magick_restrict cache_info,
4256 *magick_restrict clone_info;
4264 assert(image != (
Image *) NULL);
4265 assert(image->signature == MagickCoreSignature);
4266 if (IsEventLogging() != MagickFalse)
4267 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4268 assert(image->cache != (
void *) NULL);
4269 assert(filename != (
const char *) NULL);
4270 assert(offset != (MagickOffsetType *) NULL);
4271 page_size=GetMagickPageSize();
4273 assert(cache_info->signature == MagickCoreSignature);
4274 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4275 CopyOpenCLBuffer(cache_info);
4277 if (attach != MagickFalse)
4282 if (cache_info->debug != MagickFalse)
4283 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4284 "attach persistent cache");
4285 (void) CopyMagickString(cache_info->cache_filename,filename,
4287 cache_info->type=MapCache;
4288 cache_info->offset=(*offset);
4289 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4290 return(MagickFalse);
4291 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4297 status=AcquireMagickResource(DiskResource,cache_info->length);
4298 if (status == MagickFalse)
4300 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4301 "CacheResourcesExhausted",
"`%s'",image->filename);
4302 return(MagickFalse);
4304 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4305 clone_info->type=DiskCache;
4306 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4307 clone_info->file=(-1);
4308 clone_info->storage_class=cache_info->storage_class;
4309 clone_info->colorspace=cache_info->colorspace;
4310 clone_info->columns=cache_info->columns;
4311 clone_info->rows=cache_info->rows;
4312 clone_info->active_index_channel=cache_info->active_index_channel;
4313 clone_info->mode=PersistMode;
4314 clone_info->length=cache_info->length;
4315 clone_info->channels=cache_info->channels;
4316 clone_info->offset=(*offset);
4317 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4318 if (status != MagickFalse)
4319 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4320 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4321 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4363 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4364 const ssize_t y,
const size_t columns,
const size_t rows,
4365 const MagickBooleanType clone,
NexusInfo *nexus_info,
4368 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4373 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4377 *magick_restrict cache_info;
4386 *magick_restrict pixels;
4391 assert(image != (
const Image *) NULL);
4392 assert(image->signature == MagickCoreSignature);
4393 assert(image->cache != (Cache) NULL);
4394 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4395 if (cache_info == (Cache) NULL)
4397 assert(cache_info->signature == MagickCoreSignature);
4398 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4399 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4400 (y >= (ssize_t) cache_info->rows))
4402 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4403 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4406 offset=(MagickOffsetType) y*cache_info->columns+x;
4409 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4410 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4411 if ((MagickSizeType) offset >= number_pixels)
4416 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4417 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4418 MagickTrue : MagickFalse,nexus_info,exception);
4455 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4456 const ssize_t y,
const size_t columns,
const size_t rows,
4460 *magick_restrict cache_info;
4463 id = GetOpenMPThreadId();
4465 assert(image != (
const Image *) NULL);
4466 assert(image->signature == MagickCoreSignature);
4467 assert(image->cache != (Cache) NULL);
4469 assert(cache_info->signature == MagickCoreSignature);
4470 assert(
id < (
int) cache_info->number_threads);
4471 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4472 cache_info->nexus_info[
id],exception));
4531 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4532 const ssize_t y,
const size_t columns,
const size_t rows,
4536 *magick_restrict cache_info;
4539 id = GetOpenMPThreadId();
4541 assert(image != (
Image *) NULL);
4542 assert(image->signature == MagickCoreSignature);
4543 assert(image->cache != (Cache) NULL);
4545 assert(cache_info->signature == MagickCoreSignature);
4546 if (cache_info->methods.queue_authentic_pixels_handler !=
4547 (QueueAuthenticPixelsHandler) NULL)
4548 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4550 assert(
id < (
int) cache_info->number_threads);
4551 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4552 cache_info->nexus_info[
id],exception));
4584 static inline MagickOffsetType ReadPixelCacheRegion(
4585 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4586 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4594 #if !defined(MAGICKCORE_HAVE_PREAD)
4595 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4596 return((MagickOffsetType) -1);
4598 for (i=0; i < (MagickOffsetType) length; i+=count)
4600 #if !defined(MAGICKCORE_HAVE_PREAD)
4601 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
4604 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
4605 MAGICK_SSIZE_MAX),offset+i);
4617 static MagickBooleanType ReadPixelCacheIndexes(
4638 if (cache_info->active_index_channel == MagickFalse)
4639 return(MagickFalse);
4640 if (nexus_info->authentic_pixel_cache != MagickFalse)
4642 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4643 nexus_info->region.x;
4644 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4645 rows=nexus_info->region.height;
4647 q=nexus_info->indexes;
4649 switch (cache_info->type)
4660 if ((cache_info->columns == nexus_info->region.width) &&
4661 (extent == (MagickSizeType) ((
size_t) extent)))
4666 p=cache_info->indexes+offset;
4667 for (y=0; y < (ssize_t) rows; y++)
4669 (void) memcpy(q,p,(
size_t) length);
4670 p+=cache_info->columns;
4671 q+=nexus_info->region.width;
4680 LockSemaphoreInfo(cache_info->file_semaphore);
4681 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4683 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4684 cache_info->cache_filename);
4685 UnlockSemaphoreInfo(cache_info->file_semaphore);
4686 return(MagickFalse);
4688 if ((cache_info->columns == nexus_info->region.width) &&
4689 (extent <= MagickMaxBufferExtent))
4694 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4695 for (y=0; y < (ssize_t) rows; y++)
4697 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4698 sizeof(
PixelPacket)+offset*
sizeof(*q),length,(
unsigned char *) q);
4699 if (count < (MagickOffsetType) length)
4701 offset+=cache_info->columns;
4702 q+=nexus_info->region.width;
4704 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4705 (void) ClosePixelCacheOnDisk(cache_info);
4706 UnlockSemaphoreInfo(cache_info->file_semaphore);
4709 case DistributedCache:
4717 LockSemaphoreInfo(cache_info->file_semaphore);
4718 region=nexus_info->region;
4719 if ((cache_info->columns != nexus_info->region.width) ||
4720 (extent > MagickMaxBufferExtent))
4727 for (y=0; y < (ssize_t) rows; y++)
4730 cache_info->server_info,®ion,length,(
unsigned char *) q);
4731 if (count != (MagickOffsetType) length)
4733 q+=nexus_info->region.width;
4736 UnlockSemaphoreInfo(cache_info->file_semaphore);
4742 if (y < (ssize_t) rows)
4744 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4745 cache_info->cache_filename);
4746 return(MagickFalse);
4748 if ((cache_info->debug != MagickFalse) &&
4749 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4750 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4751 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4752 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4753 nexus_info->region.x,(
double) nexus_info->region.y);
4785 static MagickBooleanType ReadPixelCachePixels(
4806 if (nexus_info->authentic_pixel_cache != MagickFalse)
4808 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns;
4809 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4810 return(MagickFalse);
4811 offset+=nexus_info->region.x;
4812 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4813 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4814 return(MagickFalse);
4815 rows=nexus_info->region.height;
4817 if ((extent == 0) || ((extent/length) != rows))
4818 return(MagickFalse);
4819 q=nexus_info->pixels;
4821 switch (cache_info->type)
4832 if ((cache_info->columns == nexus_info->region.width) &&
4833 (extent == (MagickSizeType) ((
size_t) extent)))
4838 p=cache_info->pixels+offset;
4839 for (y=0; y < (ssize_t) rows; y++)
4841 (void) memcpy(q,p,(
size_t) length);
4842 p+=cache_info->columns;
4843 q+=nexus_info->region.width;
4852 LockSemaphoreInfo(cache_info->file_semaphore);
4853 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4855 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4856 cache_info->cache_filename);
4857 UnlockSemaphoreInfo(cache_info->file_semaphore);
4858 return(MagickFalse);
4860 if ((cache_info->columns == nexus_info->region.width) &&
4861 (extent <= MagickMaxBufferExtent))
4866 for (y=0; y < (ssize_t) rows; y++)
4868 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4869 sizeof(*q),length,(
unsigned char *) q);
4870 if (count < (MagickOffsetType) length)
4872 offset+=cache_info->columns;
4873 q+=nexus_info->region.width;
4875 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4876 (void) ClosePixelCacheOnDisk(cache_info);
4877 UnlockSemaphoreInfo(cache_info->file_semaphore);
4880 case DistributedCache:
4888 LockSemaphoreInfo(cache_info->file_semaphore);
4889 region=nexus_info->region;
4890 if ((cache_info->columns != nexus_info->region.width) ||
4891 (extent > MagickMaxBufferExtent))
4898 for (y=0; y < (ssize_t) rows; y++)
4901 cache_info->server_info,®ion,length,(
unsigned char *) q);
4902 if (count != (MagickOffsetType) length)
4904 q+=nexus_info->region.width;
4907 UnlockSemaphoreInfo(cache_info->file_semaphore);
4913 if (y < (ssize_t) rows)
4915 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4916 cache_info->cache_filename);
4917 return(MagickFalse);
4919 if ((cache_info->debug != MagickFalse) &&
4920 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4921 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4922 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4923 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4924 nexus_info->region.x,(
double) nexus_info->region.y);
4951 MagickExport Cache ReferencePixelCache(Cache cache)
4954 *magick_restrict cache_info;
4956 assert(cache != (Cache *) NULL);
4958 assert(cache_info->signature == MagickCoreSignature);
4959 LockSemaphoreInfo(cache_info->semaphore);
4960 cache_info->reference_count++;
4961 UnlockSemaphoreInfo(cache_info->semaphore);
4983 MagickPrivate
void ResetPixelCacheEpoch(
void)
5012 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5015 *magick_restrict cache_info;
5017 GetOneAuthenticPixelFromHandler
5018 get_one_authentic_pixel_from_handler;
5020 GetOneVirtualPixelFromHandler
5021 get_one_virtual_pixel_from_handler;
5026 assert(cache != (Cache) NULL);
5029 assert(cache_info->signature == MagickCoreSignature);
5030 if (IsEventLogging() != MagickFalse)
5031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5032 cache_info->filename);
5033 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5034 cache_info->methods.get_virtual_pixel_handler=
5035 cache_methods->get_virtual_pixel_handler;
5036 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5037 cache_info->methods.destroy_pixel_handler=
5038 cache_methods->destroy_pixel_handler;
5039 if (cache_methods->get_virtual_indexes_from_handler !=
5040 (GetVirtualIndexesFromHandler) NULL)
5041 cache_info->methods.get_virtual_indexes_from_handler=
5042 cache_methods->get_virtual_indexes_from_handler;
5043 if (cache_methods->get_authentic_pixels_handler !=
5044 (GetAuthenticPixelsHandler) NULL)
5045 cache_info->methods.get_authentic_pixels_handler=
5046 cache_methods->get_authentic_pixels_handler;
5047 if (cache_methods->queue_authentic_pixels_handler !=
5048 (QueueAuthenticPixelsHandler) NULL)
5049 cache_info->methods.queue_authentic_pixels_handler=
5050 cache_methods->queue_authentic_pixels_handler;
5051 if (cache_methods->sync_authentic_pixels_handler !=
5052 (SyncAuthenticPixelsHandler) NULL)
5053 cache_info->methods.sync_authentic_pixels_handler=
5054 cache_methods->sync_authentic_pixels_handler;
5055 if (cache_methods->get_authentic_pixels_from_handler !=
5056 (GetAuthenticPixelsFromHandler) NULL)
5057 cache_info->methods.get_authentic_pixels_from_handler=
5058 cache_methods->get_authentic_pixels_from_handler;
5059 if (cache_methods->get_authentic_indexes_from_handler !=
5060 (GetAuthenticIndexesFromHandler) NULL)
5061 cache_info->methods.get_authentic_indexes_from_handler=
5062 cache_methods->get_authentic_indexes_from_handler;
5063 get_one_virtual_pixel_from_handler=
5064 cache_info->methods.get_one_virtual_pixel_from_handler;
5065 if (get_one_virtual_pixel_from_handler !=
5066 (GetOneVirtualPixelFromHandler) NULL)
5067 cache_info->methods.get_one_virtual_pixel_from_handler=
5068 cache_methods->get_one_virtual_pixel_from_handler;
5069 get_one_authentic_pixel_from_handler=
5070 cache_methods->get_one_authentic_pixel_from_handler;
5071 if (get_one_authentic_pixel_from_handler !=
5072 (GetOneAuthenticPixelFromHandler) NULL)
5073 cache_info->methods.get_one_authentic_pixel_from_handler=
5074 cache_methods->get_one_authentic_pixel_from_handler;
5115 static inline MagickBooleanType AcquireCacheNexusPixels(
5116 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5119 if (length != (MagickSizeType) ((
size_t) length))
5121 (void) ThrowMagickException(exception,GetMagickModule(),
5122 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5123 cache_info->filename);
5124 return(MagickFalse);
5126 nexus_info->length=0;
5127 nexus_info->mapped=MagickFalse;
5128 if (cache_anonymous_memory <= 0)
5130 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5131 AcquireAlignedMemory(1,(
size_t) length));
5133 (
void) memset(nexus_info->cache,0,(
size_t) length);
5137 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5139 nexus_info->mapped=MagickTrue;
5143 (void) ThrowMagickException(exception,GetMagickModule(),
5144 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5145 cache_info->filename);
5146 return(MagickFalse);
5148 nexus_info->length=length;
5152 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5155 if (nexus_info->length < CACHE_LINE_SIZE)
5157 if (mode == ReadMode)
5159 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5163 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5166 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5169 if ((x >= 0) && (x >= ((ssize_t) MAGICK_SSIZE_MAX-(ssize_t) a)))
5170 return(MagickFalse);
5171 if (x <= ((ssize_t) MAGICK_SSIZE_MIN+(ssize_t) a))
5172 return(MagickFalse);
5177 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5178 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5179 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5189 assert(cache_info != (
const CacheInfo *) NULL);
5190 assert(cache_info->signature == MagickCoreSignature);
5191 if (cache_info->type == UndefinedCache)
5193 assert(nexus_info->signature == MagickCoreSignature);
5194 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5195 if ((width == 0) || (height == 0))
5197 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5198 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5201 if (((MagickSizeType) width > cache_info->width_limit) ||
5202 ((MagickSizeType) height > cache_info->height_limit) ||
5203 (ValidatePixelOffset(x,width) == MagickFalse) ||
5204 (ValidatePixelOffset(y,height) == MagickFalse))
5206 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5207 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5210 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5211 (buffered == MagickFalse))
5213 if (((x >= 0) && (y >= 0) &&
5214 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5215 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5216 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5224 offset=(MagickOffsetType) y*cache_info->columns+x;
5225 nexus_info->pixels=cache_info->pixels+offset;
5226 nexus_info->indexes=(IndexPacket *) NULL;
5227 if (cache_info->active_index_channel != MagickFalse)
5228 nexus_info->indexes=cache_info->indexes+offset;
5229 nexus_info->region.width=width;
5230 nexus_info->region.height=height;
5231 nexus_info->region.x=x;
5232 nexus_info->region.y=y;
5233 nexus_info->authentic_pixel_cache=MagickTrue;
5234 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5235 return(nexus_info->pixels);
5241 number_pixels=(MagickSizeType) width*height;
5242 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5244 if (cache_info->active_index_channel != MagickFalse)
5245 length+=number_pixels*
sizeof(IndexPacket);
5248 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5250 if (nexus_info->length < length)
5252 RelinquishCacheNexusPixels(nexus_info);
5253 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5255 if (status == MagickFalse)
5257 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5260 nexus_info->pixels=nexus_info->cache;
5261 nexus_info->indexes=(IndexPacket *) NULL;
5262 if (cache_info->active_index_channel != MagickFalse)
5263 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5264 nexus_info->region.width=width;
5265 nexus_info->region.height=height;
5266 nexus_info->region.x=x;
5267 nexus_info->region.y=y;
5268 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5269 MagickTrue : MagickFalse;
5270 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5271 return(nexus_info->pixels);
5302 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5303 const Quantum opacity)
5306 *magick_restrict image_view;
5314 assert(image != (
Image *) NULL);
5315 assert(image->signature == MagickCoreSignature);
5316 if (IsEventLogging() != MagickFalse)
5317 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5318 assert(image->cache != (Cache) NULL);
5319 image->matte=MagickTrue;
5321 image_view=AcquireVirtualCacheView(image,&image->exception);
5322 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5323 #pragma omp parallel for schedule(static) shared(status) \
5324 magick_number_threads(image,image,image->rows,1)
5326 for (y=0; y < (ssize_t) image->rows; y++)
5334 if (status == MagickFalse)
5336 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5343 for (x=0; x < (ssize_t) image->columns; x++)
5348 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5350 image_view=DestroyCacheView(image_view);
5354 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5355 const VirtualPixelMethod virtual_pixel_method)
5358 *magick_restrict cache_info;
5363 assert(image != (
Image *) NULL);
5364 assert(image->signature == MagickCoreSignature);
5365 if (IsEventLogging() != MagickFalse)
5366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5367 assert(image->cache != (Cache) NULL);
5369 assert(cache_info->signature == MagickCoreSignature);
5370 method=cache_info->virtual_pixel_method;
5371 cache_info->virtual_pixel_method=virtual_pixel_method;
5372 if ((image->columns != 0) && (image->rows != 0))
5373 switch (virtual_pixel_method)
5375 case BackgroundVirtualPixelMethod:
5377 if ((image->background_color.opacity != OpaqueOpacity) &&
5378 (image->matte == MagickFalse))
5379 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5380 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5381 (IsGrayColorspace(image->colorspace) != MagickFalse))
5382 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5385 case TransparentVirtualPixelMethod:
5387 if (image->matte == MagickFalse)
5388 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5397 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5421 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5426 assert(cache_info != (
CacheInfo *)NULL);
5427 if ((cache_info->type != MemoryCache) ||
5433 LockSemaphoreInfo(cache_info->semaphore);
5442 clEnv=GetDefaultOpenCLEnv();
5443 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5444 if (events != (cl_event *) NULL)
5458 context=GetOpenCLContext(clEnv);
5459 queue=AcquireOpenCLCommandQueue(clEnv);
5460 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5461 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5462 cache_info->length,event_count,events,NULL,&status);
5463 assert(pixels == cache_info->pixels);
5464 events=(cl_event *) RelinquishMagickMemory(events);
5465 RelinquishOpenCLCommandQueue(clEnv,queue);
5467 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5469 UnlockSemaphoreInfo(cache_info->semaphore);
5472 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5475 *magick_restrict cache_info;
5477 assert(image != (
Image *)NULL);
5479 CopyOpenCLBuffer(cache_info);
5512 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5516 *magick_restrict cache_info;
5524 assert(image != (
Image *) NULL);
5525 assert(image->signature == MagickCoreSignature);
5526 if (image->cache == (Cache) NULL)
5527 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5529 assert(cache_info->signature == MagickCoreSignature);
5530 if (cache_info->type == UndefinedCache)
5531 return(MagickFalse);
5532 if ((image->storage_class == DirectClass) &&
5533 (image->clip_mask != (
Image *) NULL) &&
5534 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5535 return(MagickFalse);
5536 if ((image->storage_class == DirectClass) &&
5537 (image->mask != (
Image *) NULL) &&
5538 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5539 return(MagickFalse);
5540 if (nexus_info->authentic_pixel_cache != MagickFalse)
5542 if (image->taint == MagickFalse)
5543 image->taint=MagickTrue;
5546 assert(cache_info->signature == MagickCoreSignature);
5547 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5548 if ((cache_info->active_index_channel != MagickFalse) &&
5549 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5550 return(MagickFalse);
5551 if ((status != MagickFalse) && (image->taint == MagickFalse))
5552 image->taint=MagickTrue;
5583 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5587 *magick_restrict cache_info;
5590 id = GetOpenMPThreadId();
5595 assert(image != (
Image *) NULL);
5596 assert(image->signature == MagickCoreSignature);
5597 assert(image->cache != (Cache) NULL);
5599 assert(cache_info->signature == MagickCoreSignature);
5600 assert(
id < (
int) cache_info->number_threads);
5601 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5633 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5637 *magick_restrict cache_info;
5640 id = GetOpenMPThreadId();
5645 assert(image != (
Image *) NULL);
5646 assert(image->signature == MagickCoreSignature);
5647 assert(image->cache != (Cache) NULL);
5649 assert(cache_info->signature == MagickCoreSignature);
5650 if (cache_info->methods.sync_authentic_pixels_handler !=
5651 (SyncAuthenticPixelsHandler) NULL)
5652 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5653 assert(
id < (
int) cache_info->number_threads);
5654 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5686 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5690 *magick_restrict cache_info;
5692 assert(image != (
Image *) NULL);
5694 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5695 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5726 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5746 if (cache_info->active_index_channel == MagickFalse)
5747 return(MagickFalse);
5748 if (nexus_info->authentic_pixel_cache != MagickFalse)
5750 if (nexus_info->indexes == (IndexPacket *) NULL)
5751 return(MagickFalse);
5752 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5753 nexus_info->region.x;
5754 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5755 rows=nexus_info->region.height;
5756 extent=(MagickSizeType) length*rows;
5757 p=nexus_info->indexes;
5759 switch (cache_info->type)
5770 if ((cache_info->columns == nexus_info->region.width) &&
5771 (extent == (MagickSizeType) ((
size_t) extent)))
5776 q=cache_info->indexes+offset;
5777 for (y=0; y < (ssize_t) rows; y++)
5779 (void) memcpy(q,p,(
size_t) length);
5780 p+=nexus_info->region.width;
5781 q+=cache_info->columns;
5790 LockSemaphoreInfo(cache_info->file_semaphore);
5791 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5793 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5794 cache_info->cache_filename);
5795 UnlockSemaphoreInfo(cache_info->file_semaphore);
5796 return(MagickFalse);
5798 if ((cache_info->columns == nexus_info->region.width) &&
5799 (extent <= MagickMaxBufferExtent))
5804 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5805 for (y=0; y < (ssize_t) rows; y++)
5807 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5808 sizeof(
PixelPacket)+offset*
sizeof(*p),length,(
const unsigned char *)
5810 if (count < (MagickOffsetType) length)
5812 p+=nexus_info->region.width;
5813 offset+=cache_info->columns;
5815 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5816 (void) ClosePixelCacheOnDisk(cache_info);
5817 UnlockSemaphoreInfo(cache_info->file_semaphore);
5820 case DistributedCache:
5828 LockSemaphoreInfo(cache_info->file_semaphore);
5829 region=nexus_info->region;
5830 if ((cache_info->columns != nexus_info->region.width) ||
5831 (extent > MagickMaxBufferExtent))
5838 for (y=0; y < (ssize_t) rows; y++)
5841 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5842 if (count != (MagickOffsetType) length)
5844 p+=nexus_info->region.width;
5847 UnlockSemaphoreInfo(cache_info->file_semaphore);
5853 if (y < (ssize_t) rows)
5855 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5856 cache_info->cache_filename);
5857 return(MagickFalse);
5859 if ((cache_info->debug != MagickFalse) &&
5860 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5861 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5862 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5863 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5864 nexus_info->region.x,(
double) nexus_info->region.y);
5896 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5916 if (nexus_info->authentic_pixel_cache != MagickFalse)
5918 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5919 nexus_info->region.x;
5920 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5921 rows=nexus_info->region.height;
5923 p=nexus_info->pixels;
5925 switch (cache_info->type)
5936 if ((cache_info->columns == nexus_info->region.width) &&
5937 (extent == (MagickSizeType) ((
size_t) extent)))
5942 q=cache_info->pixels+offset;
5943 for (y=0; y < (ssize_t) rows; y++)
5945 (void) memcpy(q,p,(
size_t) length);
5946 p+=nexus_info->region.width;
5947 q+=cache_info->columns;
5956 LockSemaphoreInfo(cache_info->file_semaphore);
5957 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5959 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5960 cache_info->cache_filename);
5961 UnlockSemaphoreInfo(cache_info->file_semaphore);
5962 return(MagickFalse);
5964 if ((cache_info->columns == nexus_info->region.width) &&
5965 (extent <= MagickMaxBufferExtent))
5970 for (y=0; y < (ssize_t) rows; y++)
5972 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5973 sizeof(*p),length,(
const unsigned char *) p);
5974 if (count < (MagickOffsetType) length)
5976 p+=nexus_info->region.width;
5977 offset+=cache_info->columns;
5979 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5980 (void) ClosePixelCacheOnDisk(cache_info);
5981 UnlockSemaphoreInfo(cache_info->file_semaphore);
5984 case DistributedCache:
5992 LockSemaphoreInfo(cache_info->file_semaphore);
5993 region=nexus_info->region;
5994 if ((cache_info->columns != nexus_info->region.width) ||
5995 (extent > MagickMaxBufferExtent))
6002 for (y=0; y < (ssize_t) rows; y++)
6005 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6006 if (count != (MagickOffsetType) length)
6008 p+=nexus_info->region.width;
6011 UnlockSemaphoreInfo(cache_info->file_semaphore);
6017 if (y < (ssize_t) rows)
6019 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6020 cache_info->cache_filename);
6021 return(MagickFalse);
6023 if ((cache_info->debug != MagickFalse) &&
6024 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6025 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6026 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6027 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6028 nexus_info->region.x,(
double) nexus_info->region.y);