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 (void) ThrowMagickException(exception,GetMagickModule(),
1883 ResourceLimitFatalError,
"TimeLimitExceeded",
"`%s'",image->filename);
1884 return((Cache) NULL);
1886 LockSemaphoreInfo(image->semaphore);
1887 assert(image->cache != (Cache) NULL);
1889 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1890 CopyOpenCLBuffer(cache_info);
1892 destroy=MagickFalse;
1893 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1895 LockSemaphoreInfo(cache_info->semaphore);
1896 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1907 clone_image=(*image);
1908 clone_image.semaphore=AllocateSemaphoreInfo();
1909 clone_image.reference_count=1;
1910 clone_image.cache=ClonePixelCache(cache_info);
1911 clone_info=(
CacheInfo *) clone_image.cache;
1912 status=OpenPixelCache(&clone_image,IOMode,exception);
1913 if (status == MagickFalse)
1914 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1917 if (clone != MagickFalse)
1918 status=ClonePixelCacheRepository(clone_info,cache_info,
1920 if (status == MagickFalse)
1921 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1925 image->cache=clone_info;
1928 DestroySemaphoreInfo(&clone_image.semaphore);
1930 UnlockSemaphoreInfo(cache_info->semaphore);
1932 if (destroy != MagickFalse)
1933 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1934 if (status != MagickFalse)
1939 if (image->type != UndefinedType)
1940 image->type=UndefinedType;
1941 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1943 status=OpenPixelCache(image,IOMode,exception);
1945 if (cache_info->file != -1)
1946 (void) ClosePixelCacheOnDisk(cache_info);
1949 UnlockSemaphoreInfo(image->semaphore);
1950 if (status == MagickFalse)
1951 return((Cache) NULL);
1952 return(image->cache);
1979 MagickExport CacheType GetPixelCacheType(
const Image *image)
1981 return(GetImagePixelCacheType(image));
1984 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1987 *magick_restrict cache_info;
1989 assert(image != (
Image *) NULL);
1990 assert(image->signature == MagickCoreSignature);
1991 assert(image->cache != (Cache) NULL);
1993 assert(cache_info->signature == MagickCoreSignature);
1994 return(cache_info->type);
2027 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2031 *magick_restrict cache_info;
2034 *magick_restrict pixels;
2036 assert(image != (
Image *) NULL);
2037 assert(image->signature == MagickCoreSignature);
2038 assert(image->cache != (Cache) NULL);
2040 assert(cache_info->signature == MagickCoreSignature);
2041 *pixel=image->background_color;
2042 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2043 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2044 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2046 return(MagickFalse);
2082 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2086 *magick_restrict cache_info;
2089 id = GetOpenMPThreadId();
2092 *magick_restrict pixels;
2094 assert(image != (
const Image *) NULL);
2095 assert(image->signature == MagickCoreSignature);
2096 assert(image->cache != (Cache) NULL);
2098 assert(cache_info->signature == MagickCoreSignature);
2099 *pixel=image->background_color;
2100 assert(
id < (
int) cache_info->number_threads);
2101 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2102 cache_info->nexus_info[
id],exception);
2104 return(MagickFalse);
2141 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2146 *magick_restrict cache_info;
2149 id = GetOpenMPThreadId();
2152 *magick_restrict indexes;
2155 *magick_restrict pixels;
2157 assert(image != (
const Image *) NULL);
2158 assert(image->signature == MagickCoreSignature);
2159 assert(image->cache != (Cache) NULL);
2161 assert(cache_info->signature == MagickCoreSignature);
2162 assert(
id < (
int) cache_info->number_threads);
2163 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2164 1UL,1UL,cache_info->nexus_info[
id],exception);
2165 GetMagickPixelPacket(image,pixel);
2167 return(MagickFalse);
2168 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2169 SetMagickPixelPacket(image,pixels,indexes,pixel);
2208 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2209 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2213 *magick_restrict cache_info;
2216 id = GetOpenMPThreadId();
2219 *magick_restrict pixels;
2221 assert(image != (
const Image *) NULL);
2222 assert(image->signature == MagickCoreSignature);
2223 assert(image->cache != (Cache) NULL);
2225 assert(cache_info->signature == MagickCoreSignature);
2226 *pixel=image->background_color;
2227 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2228 (GetOneVirtualPixelFromHandler) NULL)
2229 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2230 virtual_pixel_method,x,y,pixel,exception));
2231 assert(
id < (
int) cache_info->number_threads);
2232 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2233 cache_info->nexus_info[
id],exception);
2235 return(MagickFalse);
2271 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2275 *magick_restrict cache_info;
2278 id = GetOpenMPThreadId();
2281 *magick_restrict pixels;
2283 assert(image != (
const Image *) NULL);
2284 assert(image->signature == MagickCoreSignature);
2285 assert(image->cache != (Cache) NULL);
2287 assert(cache_info->signature == MagickCoreSignature);
2288 *pixel=image->background_color;
2289 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2290 (GetOneVirtualPixelFromHandler) NULL)
2291 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2292 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2293 assert(
id < (
int) cache_info->number_threads);
2294 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2295 1UL,1UL,cache_info->nexus_info[
id],exception);
2297 return(MagickFalse);
2336 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2337 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2341 *magick_restrict cache_info;
2344 id = GetOpenMPThreadId();
2347 *magick_restrict pixels;
2349 assert(image != (
const Image *) NULL);
2350 assert(image->signature == MagickCoreSignature);
2351 assert(image->cache != (Cache) NULL);
2353 assert(cache_info->signature == MagickCoreSignature);
2354 assert(
id < (
int) cache_info->number_threads);
2355 *pixel=image->background_color;
2356 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2357 cache_info->nexus_info[
id],exception);
2359 return(MagickFalse);
2389 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2392 *magick_restrict cache_info;
2394 assert(cache != (Cache) NULL);
2396 assert(cache_info->signature == MagickCoreSignature);
2397 if (IsEventLogging() != MagickFalse)
2398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2399 cache_info->filename);
2400 return(cache_info->channels);
2425 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2428 *magick_restrict cache_info;
2430 assert(cache != (Cache) NULL);
2432 assert(cache_info->signature == MagickCoreSignature);
2433 if (IsEventLogging() != MagickFalse)
2434 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2435 cache_info->filename);
2436 return(cache_info->colorspace);
2462 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2465 *magick_restrict cache_info;
2467 assert(image != (
const Image *) NULL);
2468 assert(image->signature == MagickCoreSignature);
2469 assert(image->cache != (Cache) NULL);
2471 assert(cache_info->signature == MagickCoreSignature);
2472 return(cache_info->cache_filename);
2497 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2500 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2501 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2502 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2503 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2504 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2505 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2506 cache_methods->get_authentic_indexes_from_handler=
2507 GetAuthenticIndexesFromCache;
2508 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2509 cache_methods->get_one_authentic_pixel_from_handler=
2510 GetOneAuthenticPixelFromCache;
2511 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2512 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2513 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2540 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2544 *magick_restrict cache_info;
2549 assert(cache != NULL);
2551 assert(cache_info->signature == MagickCoreSignature);
2552 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2554 return((MagickSizeType) cache_info->columns*cache_info->rows);
2585 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2589 *magick_restrict cache_info;
2591 assert(image != (
const Image *) NULL);
2592 assert(image->signature == MagickCoreSignature);
2593 assert(image->cache != (Cache) NULL);
2594 assert(length != (MagickSizeType *) NULL);
2596 assert(exception->signature == MagickCoreSignature);
2598 assert(cache_info->signature == MagickCoreSignature);
2600 *length=cache_info->length;
2601 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2602 return((
void *) NULL);
2603 return((
void *) cache_info->pixels);
2630 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2633 *magick_restrict cache_info;
2635 assert(cache != (Cache) NULL);
2637 assert(cache_info->signature == MagickCoreSignature);
2638 if (IsEventLogging() != MagickFalse)
2639 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2640 cache_info->filename);
2641 return(cache_info->storage_class);
2671 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2674 assert(image != (
Image *) NULL);
2675 assert(image->signature == MagickCoreSignature);
2676 if (IsEventLogging() != MagickFalse)
2677 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2679 if (GetImagePixelCacheType(image) == DiskCache)
2708 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2711 *magick_restrict cache_info;
2713 assert(image != (
Image *) NULL);
2714 assert(image->signature == MagickCoreSignature);
2715 assert(image->cache != (Cache) NULL);
2717 assert(cache_info->signature == MagickCoreSignature);
2718 return(cache_info->virtual_pixel_method);
2744 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2747 *magick_restrict cache_info;
2750 id = GetOpenMPThreadId();
2752 assert(image != (
const Image *) NULL);
2753 assert(image->signature == MagickCoreSignature);
2754 assert(image->cache != (Cache) NULL);
2756 assert(cache_info->signature == MagickCoreSignature);
2757 assert(
id < (
int) cache_info->number_threads);
2758 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2787 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2791 *magick_restrict cache_info;
2793 assert(cache != (Cache) NULL);
2795 assert(cache_info->signature == MagickCoreSignature);
2796 if (cache_info->storage_class == UndefinedClass)
2797 return((IndexPacket *) NULL);
2798 return(nexus_info->indexes);
2826 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2829 *magick_restrict cache_info;
2832 id = GetOpenMPThreadId();
2834 assert(image != (
const Image *) NULL);
2835 assert(image->signature == MagickCoreSignature);
2836 assert(image->cache != (Cache) NULL);
2838 assert(cache_info->signature == MagickCoreSignature);
2839 if (cache_info->methods.get_virtual_indexes_from_handler !=
2840 (GetVirtualIndexesFromHandler) NULL)
2841 return(cache_info->methods.get_virtual_indexes_from_handler(image));
2842 assert(
id < (
int) cache_info->number_threads);
2843 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2886 0, 48, 12, 60, 3, 51, 15, 63,
2887 32, 16, 44, 28, 35, 19, 47, 31,
2888 8, 56, 4, 52, 11, 59, 7, 55,
2889 40, 24, 36, 20, 43, 27, 39, 23,
2890 2, 50, 14, 62, 1, 49, 13, 61,
2891 34, 18, 46, 30, 33, 17, 45, 29,
2892 10, 58, 6, 54, 9, 57, 5, 53,
2893 42, 26, 38, 22, 41, 25, 37, 21
2896 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2901 index=x+DitherMatrix[x & 0x07]-32L;
2904 if (index >= (ssize_t) columns)
2905 return((ssize_t) columns-1L);
2909 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2914 index=y+DitherMatrix[y & 0x07]-32L;
2917 if (index >= (ssize_t) rows)
2918 return((ssize_t) rows-1L);
2922 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2926 if (x >= (ssize_t) columns)
2927 return((ssize_t) (columns-1));
2931 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2935 if (y >= (ssize_t) rows)
2936 return((ssize_t) (rows-1));
2940 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2942 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2945 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2947 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2950 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2951 const size_t extent)
2956 modulo.quotient=offset;
2960 modulo.quotient=offset/((ssize_t) extent);
2961 modulo.remainder=offset % ((ssize_t) extent);
2963 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2966 modulo.remainder+=((ssize_t) extent);
2971 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2972 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2973 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2977 *magick_restrict cache_info;
2980 *magick_restrict virtual_indexes;
2987 *magick_restrict indexes;
2997 *magick_restrict virtual_nexus;
3000 *magick_restrict pixels,
3011 assert(image != (
const Image *) NULL);
3012 assert(image->signature == MagickCoreSignature);
3013 assert(image->cache != (Cache) NULL);
3015 assert(cache_info->signature == MagickCoreSignature);
3016 if (cache_info->type == UndefinedCache)
3018 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3019 CopyOpenCLBuffer(cache_info);
3021 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3022 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3023 MagickTrue : MagickFalse,nexus_info,exception);
3026 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
3027 nexus_info->region.x;
3028 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3029 nexus_info->region.width-1L;
3030 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3031 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3032 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
3033 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
3041 if (nexus_info->authentic_pixel_cache != MagickFalse)
3043 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3044 if (status == MagickFalse)
3046 if ((cache_info->storage_class == PseudoClass) ||
3047 (cache_info->colorspace == CMYKColorspace))
3049 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3050 if (status == MagickFalse)
3058 virtual_nexus=nexus_info->virtual_nexus;
3060 indexes=nexus_info->indexes;
3061 switch (virtual_pixel_method)
3063 case BlackVirtualPixelMethod:
3065 SetPixelRed(&virtual_pixel,0);
3066 SetPixelGreen(&virtual_pixel,0);
3067 SetPixelBlue(&virtual_pixel,0);
3068 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3071 case GrayVirtualPixelMethod:
3073 SetPixelRed(&virtual_pixel,QuantumRange/2);
3074 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3075 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3076 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3079 case TransparentVirtualPixelMethod:
3081 SetPixelRed(&virtual_pixel,0);
3082 SetPixelGreen(&virtual_pixel,0);
3083 SetPixelBlue(&virtual_pixel,0);
3084 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3087 case MaskVirtualPixelMethod:
3088 case WhiteVirtualPixelMethod:
3090 SetPixelRed(&virtual_pixel,QuantumRange);
3091 SetPixelGreen(&virtual_pixel,QuantumRange);
3092 SetPixelBlue(&virtual_pixel,QuantumRange);
3093 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3098 virtual_pixel=image->background_color;
3102 virtual_index=(IndexPacket) 0;
3103 for (v=0; v < (ssize_t) rows; v++)
3109 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3110 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3111 y_offset=EdgeY(y_offset,cache_info->rows);
3112 for (u=0; u < (ssize_t) columns; u+=length)
3118 length=(MagickSizeType) MagickMin(cache_info->columns-x_offset,columns-u);
3119 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3120 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3130 length=(MagickSizeType) 1;
3131 switch (virtual_pixel_method)
3133 case BackgroundVirtualPixelMethod:
3134 case ConstantVirtualPixelMethod:
3135 case BlackVirtualPixelMethod:
3136 case GrayVirtualPixelMethod:
3137 case TransparentVirtualPixelMethod:
3138 case MaskVirtualPixelMethod:
3139 case WhiteVirtualPixelMethod:
3142 virtual_indexes=(&virtual_index);
3145 case EdgeVirtualPixelMethod:
3148 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3149 EdgeX(x_offset,cache_info->columns),
3150 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3152 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3156 case RandomVirtualPixelMethod:
3158 if (cache_info->random_info == (
RandomInfo *) NULL)
3159 cache_info->random_info=AcquireRandomInfo();
3160 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3161 RandomX(cache_info->random_info,cache_info->columns),
3162 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3163 virtual_nexus,exception);
3164 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3168 case DitherVirtualPixelMethod:
3170 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3171 DitherX(x_offset,cache_info->columns),
3172 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3174 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3178 case TileVirtualPixelMethod:
3180 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3181 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3182 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3183 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3185 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3189 case MirrorVirtualPixelMethod:
3191 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3192 if ((x_modulo.quotient & 0x01) == 1L)
3193 x_modulo.remainder=(ssize_t) cache_info->columns-
3194 x_modulo.remainder-1L;
3195 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3196 if ((y_modulo.quotient & 0x01) == 1L)
3197 y_modulo.remainder=(ssize_t) cache_info->rows-
3198 y_modulo.remainder-1L;
3199 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3200 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3202 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3206 case CheckerTileVirtualPixelMethod:
3208 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3209 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3210 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3213 virtual_indexes=(&virtual_index);
3216 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3217 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3219 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3223 case HorizontalTileVirtualPixelMethod:
3225 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3228 virtual_indexes=(&virtual_index);
3231 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3232 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3233 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3234 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3236 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3240 case VerticalTileVirtualPixelMethod:
3242 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3245 virtual_indexes=(&virtual_index);
3248 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3249 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3250 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3251 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3253 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3257 case HorizontalTileEdgeVirtualPixelMethod:
3259 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3260 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3261 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3262 virtual_nexus,exception);
3263 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3267 case VerticalTileEdgeVirtualPixelMethod:
3269 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3270 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3271 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3272 virtual_nexus,exception);
3273 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3281 if ((indexes != (IndexPacket *) NULL) &&
3282 (virtual_indexes != (
const IndexPacket *) NULL))
3283 *indexes++=(*virtual_indexes);
3289 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3290 (
size_t) length,1UL,virtual_nexus,exception);
3293 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3294 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3296 if ((indexes != (IndexPacket *) NULL) &&
3297 (virtual_indexes != (
const IndexPacket *) NULL))
3299 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3300 sizeof(*virtual_indexes));
3304 if (u < (ssize_t) columns)
3310 if (v < (ssize_t) rows)
3350 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3351 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3354 *magick_restrict cache_info;
3357 id = GetOpenMPThreadId();
3359 assert(image != (
const Image *) NULL);
3360 assert(image->signature == MagickCoreSignature);
3361 assert(image->cache != (Cache) NULL);
3363 assert(cache_info->signature == MagickCoreSignature);
3364 assert(
id < (
int) cache_info->number_threads);
3365 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3366 cache_info->nexus_info[
id],exception));
3395 *magick_restrict cache_info;
3398 id = GetOpenMPThreadId();
3400 assert(image != (
const Image *) NULL);
3401 assert(image->signature == MagickCoreSignature);
3402 assert(image->cache != (Cache) NULL);
3404 assert(cache_info->signature == MagickCoreSignature);
3405 if (cache_info->methods.get_virtual_pixels_handler !=
3406 (GetVirtualPixelsHandler) NULL)
3407 return(cache_info->methods.get_virtual_pixels_handler(image));
3408 assert(
id < (
int) cache_info->number_threads);
3409 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3461 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3465 *magick_restrict cache_info;
3468 id = GetOpenMPThreadId();
3470 assert(image != (
const Image *) NULL);
3471 assert(image->signature == MagickCoreSignature);
3472 assert(image->cache != (Cache) NULL);
3474 assert(cache_info->signature == MagickCoreSignature);
3475 if (cache_info->methods.get_virtual_pixel_handler !=
3476 (GetVirtualPixelHandler) NULL)
3477 return(cache_info->methods.get_virtual_pixel_handler(image,
3478 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3479 assert(
id < (
int) cache_info->number_threads);
3480 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3481 columns,rows,cache_info->nexus_info[
id],exception));
3510 *magick_restrict cache_info;
3513 id = GetOpenMPThreadId();
3515 assert(image != (
const Image *) NULL);
3516 assert(image->signature == MagickCoreSignature);
3517 assert(image->cache != (Cache) NULL);
3519 assert(cache_info->signature == MagickCoreSignature);
3520 assert(
id < (
int) cache_info->number_threads);
3521 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3550 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3554 *magick_restrict cache_info;
3556 assert(cache != (Cache) NULL);
3558 assert(cache_info->signature == MagickCoreSignature);
3559 if (cache_info->storage_class == UndefinedClass)
3601 if (fabs((
double) (alpha-TransparentOpacity)) < MagickEpsilon)
3606 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3607 gamma=PerceptibleReciprocal(gamma);
3608 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3609 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3610 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3611 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3612 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3615 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3619 *magick_restrict cache_info;
3625 *magick_restrict nexus_indexes,
3626 *magick_restrict indexes;
3636 **magick_restrict mask_nexus;
3648 if (IsEventLogging() != MagickFalse)
3649 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3650 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3652 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3655 if (cache_info == (Cache) NULL)
3656 return(MagickFalse);
3657 mask_nexus=AcquirePixelCacheNexus(1);
3658 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3659 nexus_info->virtual_nexus,exception);
3660 indexes=nexus_info->virtual_nexus->indexes;
3661 q=nexus_info->pixels;
3662 nexus_indexes=nexus_info->indexes;
3663 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3664 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3665 nexus_info->region.height,mask_nexus[0],&image->exception);
3668 return(MagickFalse);
3670 GetMagickPixelPacket(image,&alpha);
3671 GetMagickPixelPacket(image,&beta);
3672 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3677 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3679 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3680 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3681 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3682 alpha.opacity,&beta);
3683 SetPixelRed(q,ClampToQuantum(beta.red));
3684 SetPixelGreen(q,ClampToQuantum(beta.green));
3685 SetPixelBlue(q,ClampToQuantum(beta.blue));
3686 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3687 if (cache_info->active_index_channel != MagickFalse)
3688 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3695 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3730 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3739 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3741 if (*cache_info->cache_filename ==
'\0')
3742 file=AcquireUniqueFileResource(cache_info->cache_filename);
3748 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3753 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3754 O_BINARY | O_EXCL,S_MODE);
3756 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3762 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3765 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3770 return(MagickFalse);
3771 (void) AcquireMagickResource(FileResource,1);
3772 if (cache_info->file != -1)
3773 (void) ClosePixelCacheOnDisk(cache_info);
3774 cache_info->file=file;
3775 cache_info->disk_mode=mode;
3779 static inline MagickOffsetType WritePixelCacheRegion(
3780 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3781 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3789 #if !defined(MAGICKCORE_HAVE_PWRITE)
3790 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3791 return((MagickOffsetType) -1);
3793 for (i=0; i < (MagickOffsetType) length; i+=count)
3795 #if !defined(MAGICKCORE_HAVE_PWRITE)
3796 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
3799 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
3800 MAGICK_SSIZE_MAX),offset+i);
3812 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3815 *magick_restrict cache_info;
3821 if (cache_info->debug != MagickFalse)
3824 format[MaxTextExtent],
3825 message[MaxTextExtent];
3827 (void) FormatMagickSize(length,MagickFalse,format);
3828 (void) FormatLocaleString(message,MaxTextExtent,
3829 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3830 cache_info->cache_filename,cache_info->file,format);
3831 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3833 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3835 return(MagickFalse);
3836 if ((MagickSizeType) offset < length)
3842 extent=(MagickOffsetType) length-1;
3843 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3846 return(MagickFalse);
3847 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3848 if (cache_info->synchronize != MagickFalse)
3849 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3850 return(MagickFalse);
3853 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3855 return(MagickFalse);
3859 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3863 *magick_restrict cache_info,
3867 format[MaxTextExtent],
3868 message[MaxTextExtent];
3885 assert(image != (
const Image *) NULL);
3886 assert(image->signature == MagickCoreSignature);
3887 assert(image->cache != (Cache) NULL);
3888 if (IsEventLogging() != MagickFalse)
3889 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3890 if (cache_anonymous_memory < 0)
3898 cache_anonymous_memory=0;
3899 value=GetPolicyValue(
"pixel-cache-memory");
3900 if (value == (
char *) NULL)
3901 value=GetPolicyValue(
"cache:memory-map");
3902 if (LocaleCompare(value,
"anonymous") == 0)
3904 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3905 cache_anonymous_memory=1;
3907 (void) ThrowMagickException(exception,GetMagickModule(),
3908 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3909 "'%s' (policy requires anonymous memory mapping)",image->filename);
3912 value=DestroyString(value);
3914 if ((image->columns == 0) || (image->rows == 0))
3915 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3917 assert(cache_info->signature == MagickCoreSignature);
3918 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3919 ((MagickSizeType) image->rows > cache_info->height_limit))
3920 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3922 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3924 length=GetImageListLength(image);
3925 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3926 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3929 source_info=(*cache_info);
3930 source_info.file=(-1);
3931 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3932 image->filename,(
double) image->scene);
3933 cache_info->storage_class=image->storage_class;
3934 cache_info->colorspace=image->colorspace;
3935 cache_info->rows=image->rows;
3936 cache_info->columns=image->columns;
3937 cache_info->channels=image->channels;
3938 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3939 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3940 cache_info->mode=mode;
3941 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3943 if (cache_info->active_index_channel != MagickFalse)
3944 packet_size+=
sizeof(IndexPacket);
3945 length=number_pixels*packet_size;
3946 columns=(size_t) (length/cache_info->rows/packet_size);
3947 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3948 ((ssize_t) cache_info->rows < 0))
3949 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3951 cache_info->length=length;
3952 if (image->ping != MagickFalse)
3954 cache_info->type=PingCache;
3957 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3958 cache_info->columns*cache_info->rows);
3959 if (cache_info->mode == PersistMode)
3961 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3962 if ((status != MagickFalse) &&
3963 (length == (MagickSizeType) ((
size_t) length)) &&
3964 ((cache_info->type == UndefinedCache) ||
3965 (cache_info->type == MemoryCache)))
3967 status=AcquireMagickResource(MemoryResource,cache_info->length);
3968 if (status != MagickFalse)
3971 if (cache_anonymous_memory <= 0)
3973 cache_info->mapped=MagickFalse;
3974 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3975 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3979 cache_info->mapped=MagickTrue;
3980 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3981 cache_info->length);
3985 cache_info->mapped=source_info.mapped;
3986 cache_info->pixels=source_info.pixels;
3993 cache_info->colorspace=image->colorspace;
3994 cache_info->type=MemoryCache;
3995 cache_info->indexes=(IndexPacket *) NULL;
3996 if (cache_info->active_index_channel != MagickFalse)
3997 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
3999 if ((source_info.storage_class != UndefinedClass) &&
4002 status&=ClonePixelCacheRepository(cache_info,&source_info,
4004 RelinquishPixelCachePixels(&source_info);
4006 if (cache_info->debug != MagickFalse)
4008 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4009 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4011 (void) FormatLocaleString(message,MaxTextExtent,
4012 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4013 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4014 type,(
double) cache_info->columns,(double) cache_info->rows,
4016 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4019 cache_info->storage_class=image->storage_class;
4022 cache_info->type=UndefinedCache;
4023 return(MagickFalse);
4029 status=AcquireMagickResource(DiskResource,cache_info->length);
4030 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4032 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4040 server_info=AcquireDistributeCacheInfo(exception);
4043 status=OpenDistributePixelCache(server_info,image);
4044 if (status == MagickFalse)
4046 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4047 GetDistributeCacheHostname(server_info));
4048 server_info=DestroyDistributeCacheInfo(server_info);
4056 cache_info->type=DistributedCache;
4057 cache_info->storage_class=image->storage_class;
4058 cache_info->colorspace=image->colorspace;
4059 cache_info->server_info=server_info;
4060 (void) FormatLocaleString(cache_info->cache_filename,
4061 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4064 cache_info->server_info));
4065 if ((source_info.storage_class != UndefinedClass) &&
4068 status=ClonePixelCacheRepository(cache_info,&source_info,
4070 RelinquishPixelCachePixels(&source_info);
4072 if (cache_info->debug != MagickFalse)
4074 (void) FormatMagickSize(cache_info->length,MagickFalse,
4076 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4078 (void) FormatLocaleString(message,MaxTextExtent,
4079 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4080 cache_info->cache_filename,GetDistributeCacheFile(
4082 (double) cache_info->columns,(
double) cache_info->rows,
4084 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4089 cache_info->type=UndefinedCache;
4090 return(MagickFalse);
4095 cache_info->type=UndefinedCache;
4096 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4097 "CacheResourcesExhausted",
"`%s'",image->filename);
4098 return(MagickFalse);
4103 if (status == MagickFalse)
4105 cache_info->type=UndefinedCache;
4106 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4107 "CacheResourcesExhausted",
"`%s'",image->filename);
4108 return(MagickFalse);
4110 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4111 (cache_info->mode != PersistMode))
4113 (void) ClosePixelCacheOnDisk(cache_info);
4114 *cache_info->cache_filename=
'\0';
4116 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4118 cache_info->type=UndefinedCache;
4119 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4121 return(MagickFalse);
4123 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4124 cache_info->length);
4125 if (status == MagickFalse)
4127 cache_info->type=UndefinedCache;
4128 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4130 return(MagickFalse);
4132 cache_info->storage_class=image->storage_class;
4133 cache_info->colorspace=image->colorspace;
4134 cache_info->type=DiskCache;
4135 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4136 if (length == (MagickSizeType) ((size_t) length))
4138 status=AcquireMagickResource(MapResource,cache_info->length);
4139 if (status != MagickFalse)
4141 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4142 cache_info->offset,(
size_t) cache_info->length);
4145 cache_info->mapped=source_info.mapped;
4146 cache_info->pixels=source_info.pixels;
4147 RelinquishMagickResource(MapResource,cache_info->length);
4154 (void) ClosePixelCacheOnDisk(cache_info);
4155 cache_info->type=MapCache;
4156 cache_info->mapped=MagickTrue;
4157 cache_info->indexes=(IndexPacket *) NULL;
4158 if (cache_info->active_index_channel != MagickFalse)
4159 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4161 if ((source_info.storage_class != UndefinedClass) &&
4164 status=ClonePixelCacheRepository(cache_info,&source_info,
4166 RelinquishPixelCachePixels(&source_info);
4168 if (cache_info->debug != MagickFalse)
4170 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4171 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4173 (void) FormatLocaleString(message,MaxTextExtent,
4174 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4175 cache_info->filename,cache_info->cache_filename,
4176 cache_info->file,type,(
double) cache_info->columns,
4177 (double) cache_info->rows,format);
4178 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4183 cache_info->type=UndefinedCache;
4184 return(MagickFalse);
4191 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4193 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4194 RelinquishPixelCachePixels(&source_info);
4196 if (cache_info->debug != MagickFalse)
4198 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4199 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4201 (void) FormatLocaleString(message,MaxTextExtent,
4202 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4203 cache_info->cache_filename,cache_info->file,type,(
double)
4204 cache_info->columns,(double) cache_info->rows,format);
4205 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4209 cache_info->type=UndefinedCache;
4210 return(MagickFalse);
4252 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4253 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4257 *magick_restrict cache_info,
4258 *magick_restrict clone_info;
4266 assert(image != (
Image *) NULL);
4267 assert(image->signature == MagickCoreSignature);
4268 if (IsEventLogging() != MagickFalse)
4269 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4270 assert(image->cache != (
void *) NULL);
4271 assert(filename != (
const char *) NULL);
4272 assert(offset != (MagickOffsetType *) NULL);
4273 page_size=GetMagickPageSize();
4275 assert(cache_info->signature == MagickCoreSignature);
4276 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4277 CopyOpenCLBuffer(cache_info);
4279 if (attach != MagickFalse)
4284 if (cache_info->debug != MagickFalse)
4285 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4286 "attach persistent cache");
4287 (void) CopyMagickString(cache_info->cache_filename,filename,
4289 cache_info->type=MapCache;
4290 cache_info->offset=(*offset);
4291 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4292 return(MagickFalse);
4293 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4299 status=AcquireMagickResource(DiskResource,cache_info->length);
4300 if (status == MagickFalse)
4302 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4303 "CacheResourcesExhausted",
"`%s'",image->filename);
4304 return(MagickFalse);
4306 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4307 clone_info->type=DiskCache;
4308 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4309 clone_info->file=(-1);
4310 clone_info->storage_class=cache_info->storage_class;
4311 clone_info->colorspace=cache_info->colorspace;
4312 clone_info->columns=cache_info->columns;
4313 clone_info->rows=cache_info->rows;
4314 clone_info->active_index_channel=cache_info->active_index_channel;
4315 clone_info->mode=PersistMode;
4316 clone_info->length=cache_info->length;
4317 clone_info->channels=cache_info->channels;
4318 clone_info->offset=(*offset);
4319 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4320 if (status != MagickFalse)
4321 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4322 *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4323 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4365 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4366 const ssize_t y,
const size_t columns,
const size_t rows,
4367 const MagickBooleanType clone,
NexusInfo *nexus_info,
4370 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4375 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4379 *magick_restrict cache_info;
4388 *magick_restrict pixels;
4393 assert(image != (
const Image *) NULL);
4394 assert(image->signature == MagickCoreSignature);
4395 assert(image->cache != (Cache) NULL);
4396 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4397 if (cache_info == (Cache) NULL)
4399 assert(cache_info->signature == MagickCoreSignature);
4400 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4401 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4402 (y >= (ssize_t) cache_info->rows))
4404 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4405 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4408 offset=(MagickOffsetType) y*cache_info->columns+x;
4411 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4412 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4413 if ((MagickSizeType) offset >= number_pixels)
4418 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4419 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4420 MagickTrue : MagickFalse,nexus_info,exception);
4457 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4458 const ssize_t y,
const size_t columns,
const size_t rows,
4462 *magick_restrict cache_info;
4465 id = GetOpenMPThreadId();
4467 assert(image != (
const Image *) NULL);
4468 assert(image->signature == MagickCoreSignature);
4469 assert(image->cache != (Cache) NULL);
4471 assert(cache_info->signature == MagickCoreSignature);
4472 assert(
id < (
int) cache_info->number_threads);
4473 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4474 cache_info->nexus_info[
id],exception));
4533 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4534 const ssize_t y,
const size_t columns,
const size_t rows,
4538 *magick_restrict cache_info;
4541 id = GetOpenMPThreadId();
4543 assert(image != (
Image *) NULL);
4544 assert(image->signature == MagickCoreSignature);
4545 assert(image->cache != (Cache) NULL);
4547 assert(cache_info->signature == MagickCoreSignature);
4548 if (cache_info->methods.queue_authentic_pixels_handler !=
4549 (QueueAuthenticPixelsHandler) NULL)
4550 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4552 assert(
id < (
int) cache_info->number_threads);
4553 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4554 cache_info->nexus_info[
id],exception));
4586 static inline MagickOffsetType ReadPixelCacheRegion(
4587 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4588 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4596 #if !defined(MAGICKCORE_HAVE_PREAD)
4597 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4598 return((MagickOffsetType) -1);
4600 for (i=0; i < (MagickOffsetType) length; i+=count)
4602 #if !defined(MAGICKCORE_HAVE_PREAD)
4603 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
4606 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-i,(
size_t)
4607 MAGICK_SSIZE_MAX),offset+i);
4619 static MagickBooleanType ReadPixelCacheIndexes(
4640 if (cache_info->active_index_channel == MagickFalse)
4641 return(MagickFalse);
4642 if (nexus_info->authentic_pixel_cache != MagickFalse)
4644 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4645 nexus_info->region.x;
4646 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4647 rows=nexus_info->region.height;
4649 q=nexus_info->indexes;
4651 switch (cache_info->type)
4662 if ((cache_info->columns == nexus_info->region.width) &&
4663 (extent == (MagickSizeType) ((
size_t) extent)))
4668 p=cache_info->indexes+offset;
4669 for (y=0; y < (ssize_t) rows; y++)
4671 (void) memcpy(q,p,(
size_t) length);
4672 p+=cache_info->columns;
4673 q+=nexus_info->region.width;
4682 LockSemaphoreInfo(cache_info->file_semaphore);
4683 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4685 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4686 cache_info->cache_filename);
4687 UnlockSemaphoreInfo(cache_info->file_semaphore);
4688 return(MagickFalse);
4690 if ((cache_info->columns == nexus_info->region.width) &&
4691 (extent <= MagickMaxBufferExtent))
4696 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4697 for (y=0; y < (ssize_t) rows; y++)
4699 count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4700 sizeof(
PixelPacket)+offset*
sizeof(*q),length,(
unsigned char *) q);
4701 if (count < (MagickOffsetType) length)
4703 offset+=cache_info->columns;
4704 q+=nexus_info->region.width;
4706 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4707 (void) ClosePixelCacheOnDisk(cache_info);
4708 UnlockSemaphoreInfo(cache_info->file_semaphore);
4711 case DistributedCache:
4719 LockSemaphoreInfo(cache_info->file_semaphore);
4720 region=nexus_info->region;
4721 if ((cache_info->columns != nexus_info->region.width) ||
4722 (extent > MagickMaxBufferExtent))
4729 for (y=0; y < (ssize_t) rows; y++)
4732 cache_info->server_info,®ion,length,(
unsigned char *) q);
4733 if (count != (MagickOffsetType) length)
4735 q+=nexus_info->region.width;
4738 UnlockSemaphoreInfo(cache_info->file_semaphore);
4744 if (y < (ssize_t) rows)
4746 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4747 cache_info->cache_filename);
4748 return(MagickFalse);
4750 if ((cache_info->debug != MagickFalse) &&
4751 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4752 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4753 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4754 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4755 nexus_info->region.x,(
double) nexus_info->region.y);
4787 static MagickBooleanType ReadPixelCachePixels(
4808 if (nexus_info->authentic_pixel_cache != MagickFalse)
4810 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns;
4811 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4812 return(MagickFalse);
4813 offset+=nexus_info->region.x;
4814 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4815 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4816 return(MagickFalse);
4817 rows=nexus_info->region.height;
4819 if ((extent == 0) || ((extent/length) != rows))
4820 return(MagickFalse);
4821 q=nexus_info->pixels;
4823 switch (cache_info->type)
4834 if ((cache_info->columns == nexus_info->region.width) &&
4835 (extent == (MagickSizeType) ((
size_t) extent)))
4840 p=cache_info->pixels+offset;
4841 for (y=0; y < (ssize_t) rows; y++)
4843 (void) memcpy(q,p,(
size_t) length);
4844 p+=cache_info->columns;
4845 q+=nexus_info->region.width;
4854 LockSemaphoreInfo(cache_info->file_semaphore);
4855 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4857 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4858 cache_info->cache_filename);
4859 UnlockSemaphoreInfo(cache_info->file_semaphore);
4860 return(MagickFalse);
4862 if ((cache_info->columns == nexus_info->region.width) &&
4863 (extent <= MagickMaxBufferExtent))
4868 for (y=0; y < (ssize_t) rows; y++)
4870 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4871 sizeof(*q),length,(
unsigned char *) q);
4872 if (count < (MagickOffsetType) length)
4874 offset+=cache_info->columns;
4875 q+=nexus_info->region.width;
4877 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4878 (void) ClosePixelCacheOnDisk(cache_info);
4879 UnlockSemaphoreInfo(cache_info->file_semaphore);
4882 case DistributedCache:
4890 LockSemaphoreInfo(cache_info->file_semaphore);
4891 region=nexus_info->region;
4892 if ((cache_info->columns != nexus_info->region.width) ||
4893 (extent > MagickMaxBufferExtent))
4900 for (y=0; y < (ssize_t) rows; y++)
4903 cache_info->server_info,®ion,length,(
unsigned char *) q);
4904 if (count != (MagickOffsetType) length)
4906 q+=nexus_info->region.width;
4909 UnlockSemaphoreInfo(cache_info->file_semaphore);
4915 if (y < (ssize_t) rows)
4917 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4918 cache_info->cache_filename);
4919 return(MagickFalse);
4921 if ((cache_info->debug != MagickFalse) &&
4922 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4923 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4924 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4925 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4926 nexus_info->region.x,(
double) nexus_info->region.y);
4953 MagickExport Cache ReferencePixelCache(Cache cache)
4956 *magick_restrict cache_info;
4958 assert(cache != (Cache *) NULL);
4960 assert(cache_info->signature == MagickCoreSignature);
4961 LockSemaphoreInfo(cache_info->semaphore);
4962 cache_info->reference_count++;
4963 UnlockSemaphoreInfo(cache_info->semaphore);
4985 MagickPrivate
void ResetPixelCacheEpoch(
void)
5014 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5017 *magick_restrict cache_info;
5019 GetOneAuthenticPixelFromHandler
5020 get_one_authentic_pixel_from_handler;
5022 GetOneVirtualPixelFromHandler
5023 get_one_virtual_pixel_from_handler;
5028 assert(cache != (Cache) NULL);
5031 assert(cache_info->signature == MagickCoreSignature);
5032 if (IsEventLogging() != MagickFalse)
5033 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5034 cache_info->filename);
5035 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5036 cache_info->methods.get_virtual_pixel_handler=
5037 cache_methods->get_virtual_pixel_handler;
5038 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5039 cache_info->methods.destroy_pixel_handler=
5040 cache_methods->destroy_pixel_handler;
5041 if (cache_methods->get_virtual_indexes_from_handler !=
5042 (GetVirtualIndexesFromHandler) NULL)
5043 cache_info->methods.get_virtual_indexes_from_handler=
5044 cache_methods->get_virtual_indexes_from_handler;
5045 if (cache_methods->get_authentic_pixels_handler !=
5046 (GetAuthenticPixelsHandler) NULL)
5047 cache_info->methods.get_authentic_pixels_handler=
5048 cache_methods->get_authentic_pixels_handler;
5049 if (cache_methods->queue_authentic_pixels_handler !=
5050 (QueueAuthenticPixelsHandler) NULL)
5051 cache_info->methods.queue_authentic_pixels_handler=
5052 cache_methods->queue_authentic_pixels_handler;
5053 if (cache_methods->sync_authentic_pixels_handler !=
5054 (SyncAuthenticPixelsHandler) NULL)
5055 cache_info->methods.sync_authentic_pixels_handler=
5056 cache_methods->sync_authentic_pixels_handler;
5057 if (cache_methods->get_authentic_pixels_from_handler !=
5058 (GetAuthenticPixelsFromHandler) NULL)
5059 cache_info->methods.get_authentic_pixels_from_handler=
5060 cache_methods->get_authentic_pixels_from_handler;
5061 if (cache_methods->get_authentic_indexes_from_handler !=
5062 (GetAuthenticIndexesFromHandler) NULL)
5063 cache_info->methods.get_authentic_indexes_from_handler=
5064 cache_methods->get_authentic_indexes_from_handler;
5065 get_one_virtual_pixel_from_handler=
5066 cache_info->methods.get_one_virtual_pixel_from_handler;
5067 if (get_one_virtual_pixel_from_handler !=
5068 (GetOneVirtualPixelFromHandler) NULL)
5069 cache_info->methods.get_one_virtual_pixel_from_handler=
5070 cache_methods->get_one_virtual_pixel_from_handler;
5071 get_one_authentic_pixel_from_handler=
5072 cache_methods->get_one_authentic_pixel_from_handler;
5073 if (get_one_authentic_pixel_from_handler !=
5074 (GetOneAuthenticPixelFromHandler) NULL)
5075 cache_info->methods.get_one_authentic_pixel_from_handler=
5076 cache_methods->get_one_authentic_pixel_from_handler;
5117 static inline MagickBooleanType AcquireCacheNexusPixels(
5118 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5121 if (length != (MagickSizeType) ((
size_t) length))
5123 (void) ThrowMagickException(exception,GetMagickModule(),
5124 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5125 cache_info->filename);
5126 return(MagickFalse);
5128 nexus_info->length=0;
5129 nexus_info->mapped=MagickFalse;
5130 if (cache_anonymous_memory <= 0)
5132 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5133 AcquireAlignedMemory(1,(
size_t) length));
5135 (
void) memset(nexus_info->cache,0,(
size_t) length);
5139 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5141 nexus_info->mapped=MagickTrue;
5145 (void) ThrowMagickException(exception,GetMagickModule(),
5146 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5147 cache_info->filename);
5148 return(MagickFalse);
5150 nexus_info->length=length;
5154 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5157 if (nexus_info->length < CACHE_LINE_SIZE)
5159 if (mode == ReadMode)
5161 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5165 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5168 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5171 if ((x >= 0) && (x >= ((ssize_t) MAGICK_SSIZE_MAX-(ssize_t) a)))
5172 return(MagickFalse);
5173 if (x <= ((ssize_t) MAGICK_SSIZE_MIN+(ssize_t) a))
5174 return(MagickFalse);
5179 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5180 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5181 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5191 assert(cache_info != (
const CacheInfo *) NULL);
5192 assert(cache_info->signature == MagickCoreSignature);
5193 if (cache_info->type == UndefinedCache)
5195 assert(nexus_info->signature == MagickCoreSignature);
5196 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5197 if ((width == 0) || (height == 0))
5199 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5200 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5203 if (((MagickSizeType) width > cache_info->width_limit) ||
5204 ((MagickSizeType) height > cache_info->height_limit) ||
5205 (ValidatePixelOffset(x,width) == MagickFalse) ||
5206 (ValidatePixelOffset(y,height) == MagickFalse))
5208 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5209 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5212 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5213 (buffered == MagickFalse))
5215 if (((x >= 0) && (y >= 0) &&
5216 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5217 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5218 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5226 offset=(MagickOffsetType) y*cache_info->columns+x;
5227 nexus_info->pixels=cache_info->pixels+offset;
5228 nexus_info->indexes=(IndexPacket *) NULL;
5229 if (cache_info->active_index_channel != MagickFalse)
5230 nexus_info->indexes=cache_info->indexes+offset;
5231 nexus_info->region.width=width;
5232 nexus_info->region.height=height;
5233 nexus_info->region.x=x;
5234 nexus_info->region.y=y;
5235 nexus_info->authentic_pixel_cache=MagickTrue;
5236 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5237 return(nexus_info->pixels);
5243 number_pixels=(MagickSizeType) width*height;
5244 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5246 if (cache_info->active_index_channel != MagickFalse)
5247 length+=number_pixels*
sizeof(IndexPacket);
5250 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5252 if (nexus_info->length < length)
5254 RelinquishCacheNexusPixels(nexus_info);
5255 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5257 if (status == MagickFalse)
5259 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5262 nexus_info->pixels=nexus_info->cache;
5263 nexus_info->indexes=(IndexPacket *) NULL;
5264 if (cache_info->active_index_channel != MagickFalse)
5265 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5266 nexus_info->region.width=width;
5267 nexus_info->region.height=height;
5268 nexus_info->region.x=x;
5269 nexus_info->region.y=y;
5270 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5271 MagickTrue : MagickFalse;
5272 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5273 return(nexus_info->pixels);
5304 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5305 const Quantum opacity)
5308 *magick_restrict image_view;
5316 assert(image != (
Image *) NULL);
5317 assert(image->signature == MagickCoreSignature);
5318 if (IsEventLogging() != MagickFalse)
5319 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5320 assert(image->cache != (Cache) NULL);
5321 image->matte=MagickTrue;
5323 image_view=AcquireVirtualCacheView(image,&image->exception);
5324 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5325 #pragma omp parallel for schedule(static) shared(status) \
5326 magick_number_threads(image,image,image->rows,1)
5328 for (y=0; y < (ssize_t) image->rows; y++)
5336 if (status == MagickFalse)
5338 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5345 for (x=0; x < (ssize_t) image->columns; x++)
5350 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5352 image_view=DestroyCacheView(image_view);
5356 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5357 const VirtualPixelMethod virtual_pixel_method)
5360 *magick_restrict cache_info;
5365 assert(image != (
Image *) NULL);
5366 assert(image->signature == MagickCoreSignature);
5367 if (IsEventLogging() != MagickFalse)
5368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5369 assert(image->cache != (Cache) NULL);
5371 assert(cache_info->signature == MagickCoreSignature);
5372 method=cache_info->virtual_pixel_method;
5373 cache_info->virtual_pixel_method=virtual_pixel_method;
5374 if ((image->columns != 0) && (image->rows != 0))
5375 switch (virtual_pixel_method)
5377 case BackgroundVirtualPixelMethod:
5379 if ((image->background_color.opacity != OpaqueOpacity) &&
5380 (image->matte == MagickFalse))
5381 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5382 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5383 (IsGrayColorspace(image->colorspace) != MagickFalse))
5384 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5387 case TransparentVirtualPixelMethod:
5389 if (image->matte == MagickFalse)
5390 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5399 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5423 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5428 assert(cache_info != (
CacheInfo *)NULL);
5429 if ((cache_info->type != MemoryCache) ||
5435 LockSemaphoreInfo(cache_info->semaphore);
5444 clEnv=GetDefaultOpenCLEnv();
5445 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5446 if (events != (cl_event *) NULL)
5460 context=GetOpenCLContext(clEnv);
5461 queue=AcquireOpenCLCommandQueue(clEnv);
5462 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5463 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5464 cache_info->length,event_count,events,NULL,&status);
5465 assert(pixels == cache_info->pixels);
5466 events=(cl_event *) RelinquishMagickMemory(events);
5467 RelinquishOpenCLCommandQueue(clEnv,queue);
5469 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5471 UnlockSemaphoreInfo(cache_info->semaphore);
5474 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5477 *magick_restrict cache_info;
5479 assert(image != (
Image *)NULL);
5481 CopyOpenCLBuffer(cache_info);
5514 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5518 *magick_restrict cache_info;
5526 assert(image != (
Image *) NULL);
5527 assert(image->signature == MagickCoreSignature);
5528 if (image->cache == (Cache) NULL)
5529 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5531 assert(cache_info->signature == MagickCoreSignature);
5532 if (cache_info->type == UndefinedCache)
5533 return(MagickFalse);
5534 if ((image->storage_class == DirectClass) &&
5535 (image->clip_mask != (
Image *) NULL) &&
5536 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5537 return(MagickFalse);
5538 if ((image->storage_class == DirectClass) &&
5539 (image->mask != (
Image *) NULL) &&
5540 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5541 return(MagickFalse);
5542 if (nexus_info->authentic_pixel_cache != MagickFalse)
5544 if (image->taint == MagickFalse)
5545 image->taint=MagickTrue;
5548 assert(cache_info->signature == MagickCoreSignature);
5549 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5550 if ((cache_info->active_index_channel != MagickFalse) &&
5551 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5552 return(MagickFalse);
5553 if ((status != MagickFalse) && (image->taint == MagickFalse))
5554 image->taint=MagickTrue;
5585 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5589 *magick_restrict cache_info;
5592 id = GetOpenMPThreadId();
5597 assert(image != (
Image *) NULL);
5598 assert(image->signature == MagickCoreSignature);
5599 assert(image->cache != (Cache) NULL);
5601 assert(cache_info->signature == MagickCoreSignature);
5602 assert(
id < (
int) cache_info->number_threads);
5603 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5635 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5639 *magick_restrict cache_info;
5642 id = GetOpenMPThreadId();
5647 assert(image != (
Image *) NULL);
5648 assert(image->signature == MagickCoreSignature);
5649 assert(image->cache != (Cache) NULL);
5651 assert(cache_info->signature == MagickCoreSignature);
5652 if (cache_info->methods.sync_authentic_pixels_handler !=
5653 (SyncAuthenticPixelsHandler) NULL)
5654 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5655 assert(
id < (
int) cache_info->number_threads);
5656 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5688 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5692 *magick_restrict cache_info;
5694 assert(image != (
Image *) NULL);
5696 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5697 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5728 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5748 if (cache_info->active_index_channel == MagickFalse)
5749 return(MagickFalse);
5750 if (nexus_info->authentic_pixel_cache != MagickFalse)
5752 if (nexus_info->indexes == (IndexPacket *) NULL)
5753 return(MagickFalse);
5754 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5755 nexus_info->region.x;
5756 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5757 rows=nexus_info->region.height;
5758 extent=(MagickSizeType) length*rows;
5759 p=nexus_info->indexes;
5761 switch (cache_info->type)
5772 if ((cache_info->columns == nexus_info->region.width) &&
5773 (extent == (MagickSizeType) ((
size_t) extent)))
5778 q=cache_info->indexes+offset;
5779 for (y=0; y < (ssize_t) rows; y++)
5781 (void) memcpy(q,p,(
size_t) length);
5782 p+=nexus_info->region.width;
5783 q+=cache_info->columns;
5792 LockSemaphoreInfo(cache_info->file_semaphore);
5793 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5795 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5796 cache_info->cache_filename);
5797 UnlockSemaphoreInfo(cache_info->file_semaphore);
5798 return(MagickFalse);
5800 if ((cache_info->columns == nexus_info->region.width) &&
5801 (extent <= MagickMaxBufferExtent))
5806 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5807 for (y=0; y < (ssize_t) rows; y++)
5809 count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5810 sizeof(
PixelPacket)+offset*
sizeof(*p),length,(
const unsigned char *)
5812 if (count < (MagickOffsetType) length)
5814 p+=nexus_info->region.width;
5815 offset+=cache_info->columns;
5817 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5818 (void) ClosePixelCacheOnDisk(cache_info);
5819 UnlockSemaphoreInfo(cache_info->file_semaphore);
5822 case DistributedCache:
5830 LockSemaphoreInfo(cache_info->file_semaphore);
5831 region=nexus_info->region;
5832 if ((cache_info->columns != nexus_info->region.width) ||
5833 (extent > MagickMaxBufferExtent))
5840 for (y=0; y < (ssize_t) rows; y++)
5843 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5844 if (count != (MagickOffsetType) length)
5846 p+=nexus_info->region.width;
5849 UnlockSemaphoreInfo(cache_info->file_semaphore);
5855 if (y < (ssize_t) rows)
5857 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5858 cache_info->cache_filename);
5859 return(MagickFalse);
5861 if ((cache_info->debug != MagickFalse) &&
5862 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5863 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5864 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5865 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5866 nexus_info->region.x,(
double) nexus_info->region.y);
5898 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5918 if (nexus_info->authentic_pixel_cache != MagickFalse)
5920 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5921 nexus_info->region.x;
5922 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5923 rows=nexus_info->region.height;
5925 p=nexus_info->pixels;
5927 switch (cache_info->type)
5938 if ((cache_info->columns == nexus_info->region.width) &&
5939 (extent == (MagickSizeType) ((
size_t) extent)))
5944 q=cache_info->pixels+offset;
5945 for (y=0; y < (ssize_t) rows; y++)
5947 (void) memcpy(q,p,(
size_t) length);
5948 p+=nexus_info->region.width;
5949 q+=cache_info->columns;
5958 LockSemaphoreInfo(cache_info->file_semaphore);
5959 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5961 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5962 cache_info->cache_filename);
5963 UnlockSemaphoreInfo(cache_info->file_semaphore);
5964 return(MagickFalse);
5966 if ((cache_info->columns == nexus_info->region.width) &&
5967 (extent <= MagickMaxBufferExtent))
5972 for (y=0; y < (ssize_t) rows; y++)
5974 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5975 sizeof(*p),length,(
const unsigned char *) p);
5976 if (count < (MagickOffsetType) length)
5978 p+=nexus_info->region.width;
5979 offset+=cache_info->columns;
5981 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5982 (void) ClosePixelCacheOnDisk(cache_info);
5983 UnlockSemaphoreInfo(cache_info->file_semaphore);
5986 case DistributedCache:
5994 LockSemaphoreInfo(cache_info->file_semaphore);
5995 region=nexus_info->region;
5996 if ((cache_info->columns != nexus_info->region.width) ||
5997 (extent > MagickMaxBufferExtent))
6004 for (y=0; y < (ssize_t) rows; y++)
6007 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6008 if (count != (MagickOffsetType) length)
6010 p+=nexus_info->region.width;
6013 UnlockSemaphoreInfo(cache_info->file_semaphore);
6019 if (y < (ssize_t) rows)
6021 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6022 cache_info->cache_filename);
6023 return(MagickFalse);
6025 if ((cache_info->debug != MagickFalse) &&
6026 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6027 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6028 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6029 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6030 nexus_info->region.x,(
double) nexus_info->region.y);