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,
125 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
137 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
139 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
141 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
142 const ssize_t,
const ssize_t,
const size_t,
const size_t,
146 #if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
151 #if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
164 #if defined(MAGICKCORE_OPENCL_SUPPORT)
171 for (i=0; i < (ssize_t) info->event_count; i++)
172 clEnv->library->clReleaseEvent(info->events[i]);
173 info->events=(cl_event *) RelinquishMagickMemory(info->events);
174 DestroySemaphoreInfo(&info->events_semaphore);
175 if (info->buffer != (cl_mem) NULL)
177 clEnv->library->clReleaseMemObject(info->buffer);
178 info->buffer=(cl_mem) NULL;
183 static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
184 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
199 magick_unreferenced(event);
200 magick_unreferenced(event_command_exec_status);
202 clEnv=GetDefaultOpenCLEnv();
203 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
211 status=clEnv->library->clGetEventInfo(info->events[i],
212 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
213 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
215 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
216 &RelinquishPixelCachePixelsDelayed,info);
221 RelinquishMagickResource(MemoryResource,info->length);
222 (void) RelinquishOpenCLCacheInfo(clEnv,info);
223 (void) RelinquishAlignedMemory(pixels);
226 static MagickBooleanType RelinquishOpenCLBuffer(
232 assert(cache_info != (
CacheInfo *) NULL);
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
240 cl_uint *event_count)
249 events=(cl_event *) NULL;
250 LockSemaphoreInfo(opencl_info->events_semaphore);
251 *event_count=opencl_info->event_count;
252 if (*event_count > 0)
254 events=AcquireQuantumMemory(*event_count,
sizeof(*events));
255 if (events == (cl_event *) NULL)
259 for (i=0; i < opencl_info->event_count; i++)
260 events[i]=opencl_info->events[i];
263 UnlockSemaphoreInfo(opencl_info->events_semaphore);
268 #if defined(MAGICKCORE_OPENCL_SUPPORT)
294 extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
297 *magick_restrict cache_info;
302 assert(image != (
const Image *) NULL);
303 assert(event != (cl_event) NULL);
306 clEnv=GetDefaultOpenCLEnv();
307 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
309 clEnv->library->clWaitForEvents(1,&event);
312 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
313 if (cache_info->opencl->events == (cl_event *) NULL)
315 cache_info->opencl->events=AcquireMagickMemory(
sizeof(
316 *cache_info->opencl->events));
317 cache_info->opencl->event_count=1;
320 cache_info->opencl->events=ResizeQuantumMemory(cache_info->opencl->events,
321 ++cache_info->opencl->event_count,
sizeof(*cache_info->opencl->events));
322 if (cache_info->opencl->events == (cl_event *) NULL)
323 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
324 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
325 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
351 MagickExport Cache AcquirePixelCache(
const size_t number_threads)
354 *magick_restrict cache_info;
359 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
361 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
362 (void) memset(cache_info,0,
sizeof(*cache_info));
363 cache_info->type=UndefinedCache;
364 cache_info->mode=IOMode;
365 cache_info->disk_mode=IOMode;
366 cache_info->colorspace=sRGBColorspace;
367 cache_info->channels=4;
368 cache_info->file=(-1);
369 cache_info->id=GetMagickThreadId();
370 cache_info->number_threads=number_threads;
371 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
372 cache_info->number_threads=GetOpenMPMaximumThreads();
373 if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
374 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
375 if (cache_info->number_threads == 0)
376 cache_info->number_threads=1;
377 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
378 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
379 if (value != (
const char *) NULL)
381 cache_info->synchronize=IsStringTrue(value);
382 value=DestroyString(value);
384 value=GetPolicyValue(
"cache:synchronize");
385 if (value != (
const char *) NULL)
387 cache_info->synchronize=IsStringTrue(value);
388 value=DestroyString(value);
390 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
391 (MagickSizeType) MAGICK_SSIZE_MAX);
392 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
393 (MagickSizeType) MAGICK_SSIZE_MAX);
394 cache_info->semaphore=AllocateSemaphoreInfo();
395 cache_info->reference_count=1;
396 cache_info->file_semaphore=AllocateSemaphoreInfo();
397 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
398 cache_info->signature=MagickCoreSignature;
399 return((Cache ) cache_info);
424 MagickExport
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
427 **magick_restrict nexus_info;
432 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
433 number_threads,
sizeof(*nexus_info)));
435 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
436 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
437 2*
sizeof(**nexus_info));
439 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
440 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
441 for (i=0; i < (ssize_t) (2*number_threads); i++)
443 nexus_info[i]=(*nexus_info+i);
444 if (i < (ssize_t) number_threads)
445 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
446 nexus_info[i]->signature=MagickCoreSignature;
479 MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
483 *magick_restrict cache_info;
485 assert(image != (
const Image *) NULL);
486 assert(image->signature == MagickCoreSignature);
488 assert(exception->signature == MagickCoreSignature);
489 assert(image->cache != (Cache) NULL);
491 assert(cache_info->signature == MagickCoreSignature);
494 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
495 return((
const void *) NULL);
496 *length=cache_info->length;
497 return((
const void *) cache_info->pixels);
518 MagickExport MagickBooleanType CacheComponentGenesis(
void)
521 cache_semaphore=AllocateSemaphoreInfo();
543 MagickExport
void CacheComponentTerminus(
void)
546 ActivateSemaphoreInfo(&cache_semaphore);
548 DestroySemaphoreInfo(&cache_semaphore);
580 static MagickBooleanType ClipPixelCacheNexus(
Image *image,
584 *magick_restrict cache_info;
590 *magick_restrict nexus_indexes,
591 *magick_restrict indexes;
597 **magick_restrict clip_nexus;
609 if (IsEventLogging() != MagickFalse)
610 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
611 if ((image->clip_mask == (
Image *) NULL) ||
612 (image->storage_class == PseudoClass))
614 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
617 if (cache_info == (Cache) NULL)
619 clip_nexus=AcquirePixelCacheNexus(1);
620 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
621 nexus_info->region.width,nexus_info->region.height,
622 nexus_info->virtual_nexus,exception);
623 indexes=nexus_info->virtual_nexus->indexes;
624 q=nexus_info->pixels;
625 nexus_indexes=nexus_info->indexes;
626 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
627 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
628 nexus_info->region.height,clip_nexus[0],exception);
633 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
638 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
643 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
644 if (fabs(mask_alpha) >= MagickEpsilon)
646 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
647 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
648 GetPixelOpacity(q)));
649 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
650 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
651 GetPixelOpacity(q)));
652 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
653 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
654 GetPixelOpacity(q)));
655 SetPixelOpacity(q,GetPixelOpacity(p));
656 if (cache_info->active_index_channel != MagickFalse)
657 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
665 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
691 MagickExport Cache ClonePixelCache(
const Cache cache)
694 *magick_restrict clone_info;
697 *magick_restrict cache_info;
699 assert(cache != NULL);
701 assert(cache_info->signature == MagickCoreSignature);
702 if (IsEventLogging() != MagickFalse)
703 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
704 cache_info->filename);
705 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
706 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
707 return((Cache ) clone_info);
735 MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
738 *magick_restrict cache_info,
739 *magick_restrict source_info;
741 assert(clone != (Cache) NULL);
743 assert(source_info->signature == MagickCoreSignature);
744 if (IsEventLogging() != MagickFalse)
745 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
746 source_info->filename);
747 assert(cache != (Cache) NULL);
749 assert(cache_info->signature == MagickCoreSignature);
750 source_info->methods=cache_info->methods;
782 static MagickBooleanType ClonePixelCacheOnDisk(
803 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
804 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
806 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
807 (lseek(clone_info->file,0,SEEK_SET) < 0))
809 quantum=(size_t) MagickMaxBufferExtent;
810 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
812 #if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
813 if (cache_info->length < 0x7ffff000)
815 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
816 (
size_t) cache_info->length);
817 if (count == (ssize_t) cache_info->length)
819 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
820 (lseek(clone_info->file,0,SEEK_SET) < 0))
824 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
826 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
827 if (buffer == (
unsigned char *) NULL)
828 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
830 while ((count=read(cache_info->file,buffer,quantum)) > 0)
835 number_bytes=write(clone_info->file,buffer,(
size_t) count);
836 if (number_bytes != count)
838 extent+=(size_t) number_bytes;
840 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
841 if (extent != cache_info->length)
846 static MagickBooleanType ClonePixelCacheRepository(
850 #define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
851 #define cache_number_threads(source,destination,chunk,multithreaded) \
852 num_threads((multithreaded) == 0 ? 1 : \
853 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
854 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
855 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
856 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
862 **magick_restrict cache_nexus,
863 **magick_restrict clone_nexus;
871 assert(cache_info != (
CacheInfo *) NULL);
872 assert(clone_info != (
CacheInfo *) NULL);
874 if (cache_info->type == PingCache)
876 if ((cache_info->storage_class == clone_info->storage_class) &&
877 (cache_info->colorspace == clone_info->colorspace) &&
878 (cache_info->channels == clone_info->channels) &&
879 (cache_info->columns == clone_info->columns) &&
880 (cache_info->rows == clone_info->rows) &&
881 (cache_info->active_index_channel == clone_info->active_index_channel))
886 if (((cache_info->type == MemoryCache) ||
887 (cache_info->type == MapCache)) &&
888 ((clone_info->type == MemoryCache) ||
889 (clone_info->type == MapCache)))
891 (void) memcpy(clone_info->pixels,cache_info->pixels,
892 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
893 if ((cache_info->active_index_channel != MagickFalse) &&
894 (clone_info->active_index_channel != MagickFalse))
895 (void) memcpy(clone_info->indexes,cache_info->indexes,
896 cache_info->columns*cache_info->rows*
897 sizeof(*cache_info->indexes));
900 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
901 return(ClonePixelCacheOnDisk(cache_info,clone_info));
906 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
907 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
908 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
909 sizeof(*cache_info->pixels);
911 #if defined(MAGICKCORE_OPENMP_SUPPORT)
912 #pragma omp parallel for schedule(static) shared(status) \
913 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
915 for (y=0; y < (ssize_t) cache_info->rows; y++)
918 id = GetOpenMPThreadId();
923 if (status == MagickFalse)
925 if (y >= (ssize_t) clone_info->rows)
927 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
928 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
931 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
932 if (status == MagickFalse)
934 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
935 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
938 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
939 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
940 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
942 if ((cache_info->active_index_channel != MagickFalse) &&
943 (clone_info->active_index_channel != MagickFalse))
948 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
949 sizeof(*cache_info->indexes);
950 #if defined(MAGICKCORE_OPENMP_SUPPORT)
951 #pragma omp parallel for schedule(static) shared(status) \
952 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
954 for (y=0; y < (ssize_t) cache_info->rows; y++)
957 id = GetOpenMPThreadId();
962 if (status == MagickFalse)
964 if (y >= (ssize_t) clone_info->rows)
966 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
967 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
970 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
971 if (status == MagickFalse)
973 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
974 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
977 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
978 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
981 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
982 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
983 if (cache_info->debug != MagickFalse)
986 message[MaxTextExtent];
988 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
989 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
990 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
991 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1018 static void DestroyImagePixelCache(
Image *image)
1020 assert(image != (
Image *) NULL);
1021 assert(image->signature == MagickCoreSignature);
1022 if (IsEventLogging() != MagickFalse)
1023 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1024 if (image->cache != (
void *) NULL)
1025 image->cache=DestroyPixelCache(image->cache);
1050 MagickExport
void DestroyImagePixels(
Image *image)
1053 *magick_restrict cache_info;
1055 assert(image != (
const Image *) NULL);
1056 assert(image->signature == MagickCoreSignature);
1057 if (IsEventLogging() != MagickFalse)
1058 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1059 assert(image->cache != (Cache) NULL);
1061 assert(cache_info->signature == MagickCoreSignature);
1062 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1064 cache_info->methods.destroy_pixel_handler(image);
1067 image->cache=DestroyPixelCache(image->cache);
1093 static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1099 if (cache_info->file != -1)
1101 status=close(cache_info->file);
1102 cache_info->file=(-1);
1103 RelinquishMagickResource(FileResource,1);
1105 return(status == -1 ? MagickFalse : MagickTrue);
1108 static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1110 switch (cache_info->type)
1114 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1115 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1116 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1122 if (cache_info->mapped == MagickFalse)
1123 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1124 cache_info->pixels);
1127 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1130 RelinquishMagickResource(MemoryResource,cache_info->length);
1135 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1137 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1138 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1139 *cache_info->cache_filename=
'\0';
1140 RelinquishMagickResource(MapResource,cache_info->length);
1145 if (cache_info->file != -1)
1146 (void) ClosePixelCacheOnDisk(cache_info);
1147 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1148 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1149 *cache_info->cache_filename=
'\0';
1150 RelinquishMagickResource(DiskResource,cache_info->length);
1153 case DistributedCache:
1155 *cache_info->cache_filename=
'\0';
1157 cache_info->server_info);
1163 cache_info->type=UndefinedCache;
1164 cache_info->mapped=MagickFalse;
1165 cache_info->indexes=(IndexPacket *) NULL;
1168 MagickExport Cache DestroyPixelCache(Cache cache)
1171 *magick_restrict cache_info;
1173 assert(cache != (Cache) NULL);
1175 assert(cache_info->signature == MagickCoreSignature);
1176 if (IsEventLogging() != MagickFalse)
1177 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1178 cache_info->filename);
1179 LockSemaphoreInfo(cache_info->semaphore);
1180 cache_info->reference_count--;
1181 if (cache_info->reference_count != 0)
1183 UnlockSemaphoreInfo(cache_info->semaphore);
1184 return((Cache) NULL);
1186 UnlockSemaphoreInfo(cache_info->semaphore);
1187 if (cache_info->debug != MagickFalse)
1190 message[MaxTextExtent];
1192 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1193 cache_info->filename);
1194 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1196 RelinquishPixelCachePixels(cache_info);
1199 cache_info->server_info);
1200 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1201 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1202 cache_info->number_threads);
1203 if (cache_info->random_info != (
RandomInfo *) NULL)
1204 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1206 DestroySemaphoreInfo(&cache_info->file_semaphore);
1208 DestroySemaphoreInfo(&cache_info->semaphore);
1209 cache_info->signature=(~MagickCoreSignature);
1210 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1241 static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1243 if (nexus_info->mapped == MagickFalse)
1244 (void) RelinquishAlignedMemory(nexus_info->cache);
1246 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1249 nexus_info->indexes=(IndexPacket *) NULL;
1250 nexus_info->length=0;
1251 nexus_info->mapped=MagickFalse;
1255 const size_t number_threads)
1260 assert(nexus_info != (
NexusInfo **) NULL);
1261 for (i=0; i < (ssize_t) (2*number_threads); i++)
1264 RelinquishCacheNexusPixels(nexus_info[i]);
1265 nexus_info[i]->signature=(~MagickCoreSignature);
1267 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1268 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1295 static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1298 *magick_restrict cache_info;
1301 id = GetOpenMPThreadId();
1303 assert(image != (
const Image *) NULL);
1304 assert(image->signature == MagickCoreSignature);
1305 assert(image->cache != (Cache) NULL);
1307 assert(cache_info->signature == MagickCoreSignature);
1308 assert(
id < (
int) cache_info->number_threads);
1309 return(cache_info->nexus_info[
id]->indexes);
1337 MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1340 *magick_restrict cache_info;
1343 id = GetOpenMPThreadId();
1345 assert(image != (
const Image *) NULL);
1346 assert(image->signature == MagickCoreSignature);
1347 assert(image->cache != (Cache) NULL);
1349 assert(cache_info->signature == MagickCoreSignature);
1350 if (cache_info->methods.get_authentic_indexes_from_handler !=
1351 (GetAuthenticIndexesFromHandler) NULL)
1352 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1353 assert(
id < (
int) cache_info->number_threads);
1354 return(cache_info->nexus_info[
id]->indexes);
1357 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1381 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1385 *magick_restrict cache_info;
1396 assert(image != (
const Image *) NULL);
1398 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1400 SyncImagePixelCache((
Image *) image,exception);
1403 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1404 return((cl_mem) NULL);
1405 LockSemaphoreInfo(cache_info->semaphore);
1406 clEnv=GetDefaultOpenCLEnv();
1409 assert(cache_info->pixels != NULL);
1410 context=GetOpenCLContext(clEnv);
1412 sizeof(*cache_info->opencl));
1413 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1414 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1415 cache_info->opencl->length=cache_info->length;
1416 cache_info->opencl->pixels=cache_info->pixels;
1417 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1418 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1419 if (status != CL_SUCCESS)
1420 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1423 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1424 UnlockSemaphoreInfo(cache_info->semaphore);
1426 return((cl_mem) NULL);
1427 return(cache_info->opencl->buffer);
1467 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1471 *magick_restrict cache_info;
1474 *magick_restrict pixels;
1479 assert(image != (
Image *) NULL);
1480 assert(image->signature == MagickCoreSignature);
1481 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1482 nexus_info,exception);
1486 assert(cache_info->signature == MagickCoreSignature);
1487 if (nexus_info->authentic_pixel_cache != MagickFalse)
1489 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1491 if (cache_info->active_index_channel != MagickFalse)
1492 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1523 *magick_restrict cache_info;
1526 id = GetOpenMPThreadId();
1528 assert(image != (
const Image *) NULL);
1529 assert(image->signature == MagickCoreSignature);
1530 assert(image->cache != (Cache) NULL);
1532 assert(cache_info->signature == MagickCoreSignature);
1533 assert(
id < (
int) cache_info->number_threads);
1534 return(cache_info->nexus_info[
id]->pixels);
1563 *magick_restrict cache_info;
1566 id = GetOpenMPThreadId();
1568 assert(image != (
const Image *) NULL);
1569 assert(image->signature == MagickCoreSignature);
1570 assert(image->cache != (Cache) NULL);
1572 assert(cache_info->signature == MagickCoreSignature);
1573 if (cache_info->methods.get_authentic_pixels_from_handler !=
1574 (GetAuthenticPixelsFromHandler) NULL)
1575 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1576 assert(
id < (
int) cache_info->number_threads);
1577 return(cache_info->nexus_info[
id]->pixels);
1627 const ssize_t y,
const size_t columns,
const size_t rows,
1631 *magick_restrict cache_info;
1634 id = GetOpenMPThreadId();
1636 assert(image != (
Image *) NULL);
1637 assert(image->signature == MagickCoreSignature);
1638 assert(image->cache != (Cache) NULL);
1640 assert(cache_info->signature == MagickCoreSignature);
1641 if (cache_info->methods.get_authentic_pixels_handler !=
1642 (GetAuthenticPixelsHandler) NULL)
1643 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1645 assert(
id < (
int) cache_info->number_threads);
1646 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1647 cache_info->nexus_info[
id],exception));
1682 const ssize_t y,
const size_t columns,
const size_t rows,
1686 *magick_restrict cache_info;
1689 id = GetOpenMPThreadId();
1691 assert(image != (
const Image *) NULL);
1692 assert(image->signature == MagickCoreSignature);
1693 assert(image->cache != (Cache) NULL);
1695 if (cache_info == (Cache) NULL)
1697 assert(cache_info->signature == MagickCoreSignature);
1698 assert(
id < (
int) cache_info->number_threads);
1699 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1700 cache_info->nexus_info[
id],exception));
1726 MagickExport MagickSizeType GetImageExtent(
const Image *image)
1729 *magick_restrict cache_info;
1732 id = GetOpenMPThreadId();
1734 assert(image != (
Image *) NULL);
1735 assert(image->signature == MagickCoreSignature);
1736 if (IsEventLogging() != MagickFalse)
1737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1738 assert(image->cache != (Cache) NULL);
1740 assert(cache_info->signature == MagickCoreSignature);
1741 assert(
id < (
int) cache_info->number_threads);
1742 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1745 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1773 extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1774 cl_uint *event_count)
1777 *magick_restrict cache_info;
1782 assert(image != (
const Image *) NULL);
1783 assert(event_count != (cl_uint *) NULL);
1786 events=(cl_event *) NULL;
1788 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1823 static inline MagickBooleanType ValidatePixelCacheMorphology(
1824 const Image *magick_restrict image)
1827 *magick_restrict cache_info;
1833 if ((image->storage_class != cache_info->storage_class) ||
1834 (image->colorspace != cache_info->colorspace) ||
1835 (image->channels != cache_info->channels) ||
1836 (image->columns != cache_info->columns) ||
1837 (image->rows != cache_info->rows) ||
1838 (cache_info->nexus_info == (
NexusInfo **) NULL))
1839 return(MagickFalse);
1843 static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1847 *magick_restrict cache_info;
1853 static MagickSizeType
1854 cpu_throttle = MagickResourceInfinity,
1858 if (cpu_throttle == MagickResourceInfinity)
1859 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1860 if ((cycles++ % 4096) == 0)
1862 if (GetMagickTTL() < 0)
1865 if (cache_info->file != -1)
1866 (void) ClosePixelCacheOnDisk(cache_info);
1867 (void) ThrowMagickException(exception,GetMagickModule(),
1868 ResourceLimitFatalError,
"TimeLimitExceeded",
"`%s'",image->filename);
1869 return((Cache) NULL);
1871 if (cpu_throttle != 0)
1872 MagickDelay(cpu_throttle);
1874 LockSemaphoreInfo(image->semaphore);
1875 assert(image->cache != (Cache) NULL);
1877 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1878 CopyOpenCLBuffer(cache_info);
1880 destroy=MagickFalse;
1881 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1883 LockSemaphoreInfo(cache_info->semaphore);
1884 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1895 clone_image=(*image);
1896 clone_image.semaphore=AllocateSemaphoreInfo();
1897 clone_image.reference_count=1;
1898 clone_image.cache=ClonePixelCache(cache_info);
1899 clone_info=(
CacheInfo *) clone_image.cache;
1900 status=OpenPixelCache(&clone_image,IOMode,exception);
1901 if (status == MagickFalse)
1902 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1905 if (clone != MagickFalse)
1906 status=ClonePixelCacheRepository(clone_info,cache_info,
1908 if (status == MagickFalse)
1909 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1913 image->cache=clone_info;
1916 DestroySemaphoreInfo(&clone_image.semaphore);
1918 UnlockSemaphoreInfo(cache_info->semaphore);
1920 if (destroy != MagickFalse)
1921 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1922 if (status != MagickFalse)
1927 if (image->type != UndefinedType)
1928 image->type=UndefinedType;
1929 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1931 status=OpenPixelCache(image,IOMode,exception);
1933 if (cache_info->file != -1)
1934 (void) ClosePixelCacheOnDisk(cache_info);
1937 UnlockSemaphoreInfo(image->semaphore);
1938 if (status == MagickFalse)
1939 return((Cache) NULL);
1940 return(image->cache);
1967 MagickExport CacheType GetPixelCacheType(
const Image *image)
1969 return(GetImagePixelCacheType(image));
1972 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1975 *magick_restrict cache_info;
1977 assert(image != (
Image *) NULL);
1978 assert(image->signature == MagickCoreSignature);
1979 assert(image->cache != (Cache) NULL);
1981 assert(cache_info->signature == MagickCoreSignature);
1982 return(cache_info->type);
2015 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2019 *magick_restrict cache_info;
2022 *magick_restrict pixels;
2024 assert(image != (
Image *) NULL);
2025 assert(image->signature == MagickCoreSignature);
2026 assert(image->cache != (Cache) NULL);
2028 assert(cache_info->signature == MagickCoreSignature);
2029 *pixel=image->background_color;
2030 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2031 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2032 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2034 return(MagickFalse);
2070 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2074 *magick_restrict cache_info;
2077 id = GetOpenMPThreadId();
2080 *magick_restrict pixels;
2082 assert(image != (
const Image *) NULL);
2083 assert(image->signature == MagickCoreSignature);
2084 assert(image->cache != (Cache) NULL);
2086 assert(cache_info->signature == MagickCoreSignature);
2087 *pixel=image->background_color;
2088 assert(
id < (
int) cache_info->number_threads);
2089 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2090 cache_info->nexus_info[
id],exception);
2092 return(MagickFalse);
2129 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2134 *magick_restrict cache_info;
2137 id = GetOpenMPThreadId();
2140 *magick_restrict indexes;
2143 *magick_restrict pixels;
2145 assert(image != (
const Image *) NULL);
2146 assert(image->signature == MagickCoreSignature);
2147 assert(image->cache != (Cache) NULL);
2149 assert(cache_info->signature == MagickCoreSignature);
2150 assert(
id < (
int) cache_info->number_threads);
2151 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2152 1UL,1UL,cache_info->nexus_info[
id],exception);
2153 GetMagickPixelPacket(image,pixel);
2155 return(MagickFalse);
2156 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2157 SetMagickPixelPacket(image,pixels,indexes,pixel);
2196 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2197 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2201 *magick_restrict cache_info;
2204 id = GetOpenMPThreadId();
2207 *magick_restrict pixels;
2209 assert(image != (
const Image *) NULL);
2210 assert(image->signature == MagickCoreSignature);
2211 assert(image->cache != (Cache) NULL);
2213 assert(cache_info->signature == MagickCoreSignature);
2214 *pixel=image->background_color;
2215 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2216 (GetOneVirtualPixelFromHandler) NULL)
2217 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2218 virtual_pixel_method,x,y,pixel,exception));
2219 assert(
id < (
int) cache_info->number_threads);
2220 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2221 cache_info->nexus_info[
id],exception);
2223 return(MagickFalse);
2259 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2263 *magick_restrict cache_info;
2266 id = GetOpenMPThreadId();
2269 *magick_restrict pixels;
2271 assert(image != (
const Image *) NULL);
2272 assert(image->signature == MagickCoreSignature);
2273 assert(image->cache != (Cache) NULL);
2275 assert(cache_info->signature == MagickCoreSignature);
2276 *pixel=image->background_color;
2277 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2278 (GetOneVirtualPixelFromHandler) NULL)
2279 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2280 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2281 assert(
id < (
int) cache_info->number_threads);
2282 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2283 1UL,1UL,cache_info->nexus_info[
id],exception);
2285 return(MagickFalse);
2324 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2325 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2329 *magick_restrict cache_info;
2332 id = GetOpenMPThreadId();
2335 *magick_restrict pixels;
2337 assert(image != (
const Image *) NULL);
2338 assert(image->signature == MagickCoreSignature);
2339 assert(image->cache != (Cache) NULL);
2341 assert(cache_info->signature == MagickCoreSignature);
2342 assert(
id < (
int) cache_info->number_threads);
2343 *pixel=image->background_color;
2344 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2345 cache_info->nexus_info[
id],exception);
2347 return(MagickFalse);
2377 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2380 *magick_restrict cache_info;
2382 assert(cache != (Cache) NULL);
2384 assert(cache_info->signature == MagickCoreSignature);
2385 if (IsEventLogging() != MagickFalse)
2386 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2387 cache_info->filename);
2388 return(cache_info->channels);
2413 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2416 *magick_restrict cache_info;
2418 assert(cache != (Cache) NULL);
2420 assert(cache_info->signature == MagickCoreSignature);
2421 if (IsEventLogging() != MagickFalse)
2422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2423 cache_info->filename);
2424 return(cache_info->colorspace);
2450 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2453 *magick_restrict cache_info;
2455 assert(image != (
const Image *) NULL);
2456 assert(image->signature == MagickCoreSignature);
2457 assert(image->cache != (Cache) NULL);
2459 assert(cache_info->signature == MagickCoreSignature);
2460 return(cache_info->cache_filename);
2485 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2488 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2489 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2490 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2491 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2492 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2493 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2494 cache_methods->get_authentic_indexes_from_handler=
2495 GetAuthenticIndexesFromCache;
2496 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2497 cache_methods->get_one_authentic_pixel_from_handler=
2498 GetOneAuthenticPixelFromCache;
2499 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2500 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2501 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2528 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2532 *magick_restrict cache_info;
2537 assert(cache != NULL);
2539 assert(cache_info->signature == MagickCoreSignature);
2540 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2542 return((MagickSizeType) cache_info->columns*cache_info->rows);
2573 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2577 *magick_restrict cache_info;
2579 assert(image != (
const Image *) NULL);
2580 assert(image->signature == MagickCoreSignature);
2581 assert(image->cache != (Cache) NULL);
2582 assert(length != (MagickSizeType *) NULL);
2584 assert(exception->signature == MagickCoreSignature);
2586 assert(cache_info->signature == MagickCoreSignature);
2588 *length=cache_info->length;
2589 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2590 return((
void *) NULL);
2591 return((
void *) cache_info->pixels);
2618 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2621 *magick_restrict cache_info;
2623 assert(cache != (Cache) NULL);
2625 assert(cache_info->signature == MagickCoreSignature);
2626 if (IsEventLogging() != MagickFalse)
2627 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2628 cache_info->filename);
2629 return(cache_info->storage_class);
2659 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2662 assert(image != (
Image *) NULL);
2663 assert(image->signature == MagickCoreSignature);
2664 if (IsEventLogging() != MagickFalse)
2665 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2667 if (GetImagePixelCacheType(image) == DiskCache)
2696 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2699 *magick_restrict cache_info;
2701 assert(image != (
Image *) NULL);
2702 assert(image->signature == MagickCoreSignature);
2703 assert(image->cache != (Cache) NULL);
2705 assert(cache_info->signature == MagickCoreSignature);
2706 return(cache_info->virtual_pixel_method);
2732 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2735 *magick_restrict cache_info;
2738 id = GetOpenMPThreadId();
2740 assert(image != (
const Image *) NULL);
2741 assert(image->signature == MagickCoreSignature);
2742 assert(image->cache != (Cache) NULL);
2744 assert(cache_info->signature == MagickCoreSignature);
2745 assert(
id < (
int) cache_info->number_threads);
2746 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2775 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2779 *magick_restrict cache_info;
2781 assert(cache != (Cache) NULL);
2783 assert(cache_info->signature == MagickCoreSignature);
2784 if (cache_info->storage_class == UndefinedClass)
2785 return((IndexPacket *) NULL);
2786 return(nexus_info->indexes);
2814 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2817 *magick_restrict cache_info;
2820 id = GetOpenMPThreadId();
2822 assert(image != (
const Image *) NULL);
2823 assert(image->signature == MagickCoreSignature);
2824 assert(image->cache != (Cache) NULL);
2826 assert(cache_info->signature == MagickCoreSignature);
2827 if (cache_info->methods.get_virtual_indexes_from_handler !=
2828 (GetVirtualIndexesFromHandler) NULL)
2829 return(cache_info->methods.get_virtual_indexes_from_handler(image));
2830 assert(
id < (
int) cache_info->number_threads);
2831 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2874 0, 48, 12, 60, 3, 51, 15, 63,
2875 32, 16, 44, 28, 35, 19, 47, 31,
2876 8, 56, 4, 52, 11, 59, 7, 55,
2877 40, 24, 36, 20, 43, 27, 39, 23,
2878 2, 50, 14, 62, 1, 49, 13, 61,
2879 34, 18, 46, 30, 33, 17, 45, 29,
2880 10, 58, 6, 54, 9, 57, 5, 53,
2881 42, 26, 38, 22, 41, 25, 37, 21
2884 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2889 index=x+DitherMatrix[x & 0x07]-32L;
2892 if (index >= (ssize_t) columns)
2893 return((ssize_t) columns-1L);
2897 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2902 index=y+DitherMatrix[y & 0x07]-32L;
2905 if (index >= (ssize_t) rows)
2906 return((ssize_t) rows-1L);
2910 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2914 if (x >= (ssize_t) columns)
2915 return((ssize_t) (columns-1));
2919 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2923 if (y >= (ssize_t) rows)
2924 return((ssize_t) (rows-1));
2928 static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2931 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2932 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2933 return(MagickFalse);
2937 static inline MagickBooleanType IsValidOffset(
const ssize_t y,
2938 const size_t columns)
2942 if ((y >= (MAGICK_SSIZE_MAX/(ssize_t) columns)) ||
2943 (y <= (MAGICK_SSIZE_MIN/(ssize_t) columns)))
2944 return(MagickFalse);
2948 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2950 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2953 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2955 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2958 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2959 const size_t extent)
2964 modulo.quotient=offset;
2968 modulo.quotient=offset/((ssize_t) extent);
2969 modulo.remainder=offset % ((ssize_t) extent);
2971 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2974 modulo.remainder+=((ssize_t) extent);
2979 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2980 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2981 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2985 *magick_restrict cache_info;
2988 *magick_restrict virtual_indexes;
2995 *magick_restrict indexes;
3005 *magick_restrict virtual_nexus;
3008 *magick_restrict pixels,
3019 assert(image != (
const Image *) NULL);
3020 assert(image->signature == MagickCoreSignature);
3021 assert(image->cache != (Cache) NULL);
3023 assert(cache_info->signature == MagickCoreSignature);
3024 if (cache_info->type == UndefinedCache)
3026 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3027 CopyOpenCLBuffer(cache_info);
3029 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3030 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3031 MagickTrue : MagickFalse,nexus_info,exception);
3034 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3036 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3037 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3039 offset+=nexus_info->region.x;
3040 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3041 nexus_info->region.width-1L;
3042 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3043 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3044 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3045 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3053 if (nexus_info->authentic_pixel_cache != MagickFalse)
3055 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3056 if (status == MagickFalse)
3058 if ((cache_info->storage_class == PseudoClass) ||
3059 (cache_info->colorspace == CMYKColorspace))
3061 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3062 if (status == MagickFalse)
3070 virtual_nexus=nexus_info->virtual_nexus;
3072 indexes=nexus_info->indexes;
3073 switch (virtual_pixel_method)
3075 case BlackVirtualPixelMethod:
3077 SetPixelRed(&virtual_pixel,0);
3078 SetPixelGreen(&virtual_pixel,0);
3079 SetPixelBlue(&virtual_pixel,0);
3080 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3083 case GrayVirtualPixelMethod:
3085 SetPixelRed(&virtual_pixel,QuantumRange/2);
3086 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3087 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3088 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3091 case TransparentVirtualPixelMethod:
3093 SetPixelRed(&virtual_pixel,0);
3094 SetPixelGreen(&virtual_pixel,0);
3095 SetPixelBlue(&virtual_pixel,0);
3096 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3099 case MaskVirtualPixelMethod:
3100 case WhiteVirtualPixelMethod:
3102 SetPixelRed(&virtual_pixel,QuantumRange);
3103 SetPixelGreen(&virtual_pixel,QuantumRange);
3104 SetPixelBlue(&virtual_pixel,QuantumRange);
3105 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3110 virtual_pixel=image->background_color;
3114 virtual_index=(IndexPacket) 0;
3115 for (v=0; v < (ssize_t) rows; v++)
3121 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3122 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3123 y_offset=EdgeY(y_offset,cache_info->rows);
3124 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3130 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3131 (ssize_t) columns-u);
3132 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3133 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3143 length=(MagickSizeType) 1;
3144 switch (virtual_pixel_method)
3146 case BackgroundVirtualPixelMethod:
3147 case ConstantVirtualPixelMethod:
3148 case BlackVirtualPixelMethod:
3149 case GrayVirtualPixelMethod:
3150 case TransparentVirtualPixelMethod:
3151 case MaskVirtualPixelMethod:
3152 case WhiteVirtualPixelMethod:
3155 virtual_indexes=(&virtual_index);
3158 case EdgeVirtualPixelMethod:
3161 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3162 EdgeX(x_offset,cache_info->columns),
3163 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3165 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3169 case RandomVirtualPixelMethod:
3171 if (cache_info->random_info == (
RandomInfo *) NULL)
3172 cache_info->random_info=AcquireRandomInfo();
3173 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3174 RandomX(cache_info->random_info,cache_info->columns),
3175 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3176 virtual_nexus,exception);
3177 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3181 case DitherVirtualPixelMethod:
3183 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3184 DitherX(x_offset,cache_info->columns),
3185 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3187 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3191 case TileVirtualPixelMethod:
3193 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3194 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3195 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3196 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3198 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3202 case MirrorVirtualPixelMethod:
3204 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3205 if ((x_modulo.quotient & 0x01) == 1L)
3206 x_modulo.remainder=(ssize_t) cache_info->columns-
3207 x_modulo.remainder-1L;
3208 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3209 if ((y_modulo.quotient & 0x01) == 1L)
3210 y_modulo.remainder=(ssize_t) cache_info->rows-
3211 y_modulo.remainder-1L;
3212 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3213 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3215 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3219 case CheckerTileVirtualPixelMethod:
3221 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3222 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3223 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3226 virtual_indexes=(&virtual_index);
3229 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3230 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3232 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3236 case HorizontalTileVirtualPixelMethod:
3238 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3241 virtual_indexes=(&virtual_index);
3244 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3245 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3246 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3247 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3249 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3253 case VerticalTileVirtualPixelMethod:
3255 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3258 virtual_indexes=(&virtual_index);
3261 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3262 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3263 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3264 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3266 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3270 case HorizontalTileEdgeVirtualPixelMethod:
3272 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3273 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3274 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3275 virtual_nexus,exception);
3276 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3280 case VerticalTileEdgeVirtualPixelMethod:
3282 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3283 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3284 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3285 virtual_nexus,exception);
3286 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3294 if ((indexes != (IndexPacket *) NULL) &&
3295 (virtual_indexes != (
const IndexPacket *) NULL))
3296 *indexes++=(*virtual_indexes);
3302 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3303 (
size_t) length,1UL,virtual_nexus,exception);
3306 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3307 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3309 if ((indexes != (IndexPacket *) NULL) &&
3310 (virtual_indexes != (
const IndexPacket *) NULL))
3312 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3313 sizeof(*virtual_indexes));
3317 if (u < (ssize_t) columns)
3323 if (v < (ssize_t) rows)
3363 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3364 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3367 *magick_restrict cache_info;
3370 id = GetOpenMPThreadId();
3372 assert(image != (
const Image *) NULL);
3373 assert(image->signature == MagickCoreSignature);
3374 assert(image->cache != (Cache) NULL);
3376 assert(cache_info->signature == MagickCoreSignature);
3377 assert(
id < (
int) cache_info->number_threads);
3378 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3379 cache_info->nexus_info[
id],exception));
3408 *magick_restrict cache_info;
3411 id = GetOpenMPThreadId();
3413 assert(image != (
const Image *) NULL);
3414 assert(image->signature == MagickCoreSignature);
3415 assert(image->cache != (Cache) NULL);
3417 assert(cache_info->signature == MagickCoreSignature);
3418 if (cache_info->methods.get_virtual_pixels_handler !=
3419 (GetVirtualPixelsHandler) NULL)
3420 return(cache_info->methods.get_virtual_pixels_handler(image));
3421 assert(
id < (
int) cache_info->number_threads);
3422 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3474 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3478 *magick_restrict cache_info;
3481 id = GetOpenMPThreadId();
3483 assert(image != (
const Image *) NULL);
3484 assert(image->signature == MagickCoreSignature);
3485 assert(image->cache != (Cache) NULL);
3487 assert(cache_info->signature == MagickCoreSignature);
3488 if (cache_info->methods.get_virtual_pixel_handler !=
3489 (GetVirtualPixelHandler) NULL)
3490 return(cache_info->methods.get_virtual_pixel_handler(image,
3491 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3492 assert(
id < (
int) cache_info->number_threads);
3493 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3494 columns,rows,cache_info->nexus_info[
id],exception));
3523 *magick_restrict cache_info;
3526 id = GetOpenMPThreadId();
3528 assert(image != (
const Image *) NULL);
3529 assert(image->signature == MagickCoreSignature);
3530 assert(image->cache != (Cache) NULL);
3532 assert(cache_info->signature == MagickCoreSignature);
3533 assert(
id < (
int) cache_info->number_threads);
3534 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3563 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3567 *magick_restrict cache_info;
3569 assert(cache != (Cache) NULL);
3571 assert(cache_info->signature == MagickCoreSignature);
3572 if (cache_info->storage_class == UndefinedClass)
3614 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3619 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3620 gamma=PerceptibleReciprocal(gamma);
3621 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3622 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3623 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3624 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3625 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3628 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3632 *magick_restrict cache_info;
3638 *magick_restrict nexus_indexes,
3639 *magick_restrict indexes;
3649 **magick_restrict mask_nexus;
3661 if (IsEventLogging() != MagickFalse)
3662 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3663 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3665 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3668 if (cache_info == (Cache) NULL)
3669 return(MagickFalse);
3670 mask_nexus=AcquirePixelCacheNexus(1);
3671 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3672 nexus_info->virtual_nexus,exception);
3673 indexes=nexus_info->virtual_nexus->indexes;
3674 q=nexus_info->pixels;
3675 nexus_indexes=nexus_info->indexes;
3676 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3677 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3678 nexus_info->region.height,mask_nexus[0],&image->exception);
3681 return(MagickFalse);
3683 GetMagickPixelPacket(image,&alpha);
3684 GetMagickPixelPacket(image,&beta);
3685 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3690 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3692 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3693 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3694 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3695 alpha.opacity,&beta);
3696 SetPixelRed(q,ClampToQuantum(beta.red));
3697 SetPixelGreen(q,ClampToQuantum(beta.green));
3698 SetPixelBlue(q,ClampToQuantum(beta.blue));
3699 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3700 if (cache_info->active_index_channel != MagickFalse)
3701 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3708 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3743 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3752 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3754 if (*cache_info->cache_filename ==
'\0')
3755 file=AcquireUniqueFileResource(cache_info->cache_filename);
3761 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3766 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3767 O_BINARY | O_EXCL,S_MODE);
3769 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3775 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3778 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3783 return(MagickFalse);
3784 (void) AcquireMagickResource(FileResource,1);
3785 if (cache_info->file != -1)
3786 (void) ClosePixelCacheOnDisk(cache_info);
3787 cache_info->file=file;
3788 cache_info->disk_mode=mode;
3792 static inline MagickOffsetType WritePixelCacheRegion(
3793 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3794 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3802 #if !defined(MAGICKCORE_HAVE_PWRITE)
3803 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3804 return((MagickOffsetType) -1);
3806 for (i=0; i < (MagickOffsetType) length; i+=count)
3808 #if !defined(MAGICKCORE_HAVE_PWRITE)
3809 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3810 (MagickSizeType) i,MAGICK_SSIZE_MAX));
3812 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3813 (MagickSizeType) i,MAGICK_SSIZE_MAX),offset+i);
3825 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3828 *magick_restrict cache_info;
3834 if (cache_info->debug != MagickFalse)
3837 format[MaxTextExtent],
3838 message[MaxTextExtent];
3840 (void) FormatMagickSize(length,MagickFalse,format);
3841 (void) FormatLocaleString(message,MaxTextExtent,
3842 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3843 cache_info->cache_filename,cache_info->file,format);
3844 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3846 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3848 return(MagickFalse);
3849 if ((MagickSizeType) offset < length)
3855 extent=(MagickOffsetType) length-1;
3856 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3859 return(MagickFalse);
3860 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3861 if (cache_info->synchronize != MagickFalse)
3862 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3863 return(MagickFalse);
3866 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3868 return(MagickFalse);
3872 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3876 *magick_restrict cache_info,
3880 format[MaxTextExtent],
3881 message[MaxTextExtent];
3898 assert(image != (
const Image *) NULL);
3899 assert(image->signature == MagickCoreSignature);
3900 assert(image->cache != (Cache) NULL);
3901 if (IsEventLogging() != MagickFalse)
3902 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3903 if (cache_anonymous_memory < 0)
3911 cache_anonymous_memory=0;
3912 value=GetPolicyValue(
"pixel-cache-memory");
3913 if (value == (
char *) NULL)
3914 value=GetPolicyValue(
"cache:memory-map");
3915 if (LocaleCompare(value,
"anonymous") == 0)
3917 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3918 cache_anonymous_memory=1;
3920 (void) ThrowMagickException(exception,GetMagickModule(),
3921 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3922 "'%s' (policy requires anonymous memory mapping)",image->filename);
3925 value=DestroyString(value);
3927 if ((image->columns == 0) || (image->rows == 0))
3928 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3930 assert(cache_info->signature == MagickCoreSignature);
3931 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3932 ((MagickSizeType) image->rows > cache_info->height_limit))
3933 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3935 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3937 length=GetImageListLength(image);
3938 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3939 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3942 source_info=(*cache_info);
3943 source_info.file=(-1);
3944 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3945 image->filename,(
double) image->scene);
3946 cache_info->storage_class=image->storage_class;
3947 cache_info->colorspace=image->colorspace;
3948 cache_info->rows=image->rows;
3949 cache_info->columns=image->columns;
3950 cache_info->channels=image->channels;
3951 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3952 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3953 cache_info->mode=mode;
3954 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3956 if (cache_info->active_index_channel != MagickFalse)
3957 packet_size+=
sizeof(IndexPacket);
3958 length=number_pixels*packet_size;
3959 columns=(size_t) (length/cache_info->rows/packet_size);
3960 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3961 ((ssize_t) cache_info->rows < 0))
3962 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3964 cache_info->length=length;
3965 if (image->ping != MagickFalse)
3967 cache_info->type=PingCache;
3970 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3971 cache_info->columns*cache_info->rows);
3972 if (cache_info->mode == PersistMode)
3974 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3975 if ((status != MagickFalse) &&
3976 (length == (MagickSizeType) ((
size_t) length)) &&
3977 ((cache_info->type == UndefinedCache) ||
3978 (cache_info->type == MemoryCache)))
3980 status=AcquireMagickResource(MemoryResource,cache_info->length);
3981 if (status != MagickFalse)
3984 if (cache_anonymous_memory <= 0)
3986 cache_info->mapped=MagickFalse;
3987 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3988 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3992 cache_info->mapped=MagickTrue;
3993 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3994 cache_info->length);
3998 cache_info->mapped=source_info.mapped;
3999 cache_info->pixels=source_info.pixels;
4006 cache_info->colorspace=image->colorspace;
4007 cache_info->type=MemoryCache;
4008 cache_info->indexes=(IndexPacket *) NULL;
4009 if (cache_info->active_index_channel != MagickFalse)
4010 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4012 if ((source_info.storage_class != UndefinedClass) &&
4015 status&=ClonePixelCacheRepository(cache_info,&source_info,
4017 RelinquishPixelCachePixels(&source_info);
4019 if (cache_info->debug != MagickFalse)
4021 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4022 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4024 (void) FormatLocaleString(message,MaxTextExtent,
4025 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4026 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4027 type,(
double) cache_info->columns,(double) cache_info->rows,
4029 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4032 cache_info->storage_class=image->storage_class;
4035 cache_info->type=UndefinedCache;
4036 return(MagickFalse);
4042 status=AcquireMagickResource(DiskResource,cache_info->length);
4043 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4045 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4053 server_info=AcquireDistributeCacheInfo(exception);
4056 status=OpenDistributePixelCache(server_info,image);
4057 if (status == MagickFalse)
4059 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4060 GetDistributeCacheHostname(server_info));
4061 server_info=DestroyDistributeCacheInfo(server_info);
4069 cache_info->type=DistributedCache;
4070 cache_info->storage_class=image->storage_class;
4071 cache_info->colorspace=image->colorspace;
4072 cache_info->server_info=server_info;
4073 (void) FormatLocaleString(cache_info->cache_filename,
4074 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4077 cache_info->server_info));
4078 if ((source_info.storage_class != UndefinedClass) &&
4081 status=ClonePixelCacheRepository(cache_info,&source_info,
4083 RelinquishPixelCachePixels(&source_info);
4085 if (cache_info->debug != MagickFalse)
4087 (void) FormatMagickSize(cache_info->length,MagickFalse,
4089 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4091 (void) FormatLocaleString(message,MaxTextExtent,
4092 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4093 cache_info->cache_filename,GetDistributeCacheFile(
4095 (double) cache_info->columns,(
double) cache_info->rows,
4097 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4102 cache_info->type=UndefinedCache;
4103 return(MagickFalse);
4108 cache_info->type=UndefinedCache;
4109 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4110 "CacheResourcesExhausted",
"`%s'",image->filename);
4111 return(MagickFalse);
4116 if (status == MagickFalse)
4118 cache_info->type=UndefinedCache;
4119 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4120 "CacheResourcesExhausted",
"`%s'",image->filename);
4121 return(MagickFalse);
4123 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4124 (cache_info->mode != PersistMode))
4126 (void) ClosePixelCacheOnDisk(cache_info);
4127 *cache_info->cache_filename=
'\0';
4129 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4131 cache_info->type=UndefinedCache;
4132 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4134 return(MagickFalse);
4136 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4137 cache_info->length);
4138 if (status == MagickFalse)
4140 cache_info->type=UndefinedCache;
4141 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4143 return(MagickFalse);
4145 cache_info->storage_class=image->storage_class;
4146 cache_info->colorspace=image->colorspace;
4147 cache_info->type=DiskCache;
4148 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4149 if (length == (MagickSizeType) ((size_t) length))
4151 status=AcquireMagickResource(MapResource,cache_info->length);
4152 if (status != MagickFalse)
4154 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4155 cache_info->offset,(
size_t) cache_info->length);
4158 cache_info->mapped=source_info.mapped;
4159 cache_info->pixels=source_info.pixels;
4160 RelinquishMagickResource(MapResource,cache_info->length);
4167 (void) ClosePixelCacheOnDisk(cache_info);
4168 cache_info->type=MapCache;
4169 cache_info->mapped=MagickTrue;
4170 cache_info->indexes=(IndexPacket *) NULL;
4171 if (cache_info->active_index_channel != MagickFalse)
4172 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4174 if ((source_info.storage_class != UndefinedClass) &&
4177 status=ClonePixelCacheRepository(cache_info,&source_info,
4179 RelinquishPixelCachePixels(&source_info);
4181 if (cache_info->debug != MagickFalse)
4183 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4184 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4186 (void) FormatLocaleString(message,MaxTextExtent,
4187 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4188 cache_info->filename,cache_info->cache_filename,
4189 cache_info->file,type,(
double) cache_info->columns,
4190 (double) cache_info->rows,format);
4191 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4196 cache_info->type=UndefinedCache;
4197 return(MagickFalse);
4204 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4206 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4207 RelinquishPixelCachePixels(&source_info);
4209 if (cache_info->debug != MagickFalse)
4211 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4212 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4214 (void) FormatLocaleString(message,MaxTextExtent,
4215 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4216 cache_info->cache_filename,cache_info->file,type,(
double)
4217 cache_info->columns,(double) cache_info->rows,format);
4218 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4222 cache_info->type=UndefinedCache;
4223 return(MagickFalse);
4265 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4266 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4270 *magick_restrict cache_info,
4271 *magick_restrict clone_info;
4279 assert(image != (
Image *) NULL);
4280 assert(image->signature == MagickCoreSignature);
4281 if (IsEventLogging() != MagickFalse)
4282 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4283 assert(image->cache != (
void *) NULL);
4284 assert(filename != (
const char *) NULL);
4285 assert(offset != (MagickOffsetType *) NULL);
4286 page_size=GetMagickPageSize();
4288 assert(cache_info->signature == MagickCoreSignature);
4289 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4290 CopyOpenCLBuffer(cache_info);
4292 if (attach != MagickFalse)
4297 if (cache_info->debug != MagickFalse)
4298 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4299 "attach persistent cache");
4300 (void) CopyMagickString(cache_info->cache_filename,filename,
4302 cache_info->type=MapCache;
4303 cache_info->offset=(*offset);
4304 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4305 return(MagickFalse);
4306 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4307 ((MagickOffsetType) cache_info->length % page_size));
4313 status=AcquireMagickResource(DiskResource,cache_info->length);
4314 if (status == MagickFalse)
4316 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4317 "CacheResourcesExhausted",
"`%s'",image->filename);
4318 return(MagickFalse);
4320 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4321 clone_info->type=DiskCache;
4322 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4323 clone_info->file=(-1);
4324 clone_info->storage_class=cache_info->storage_class;
4325 clone_info->colorspace=cache_info->colorspace;
4326 clone_info->columns=cache_info->columns;
4327 clone_info->rows=cache_info->rows;
4328 clone_info->active_index_channel=cache_info->active_index_channel;
4329 clone_info->mode=PersistMode;
4330 clone_info->length=cache_info->length;
4331 clone_info->channels=cache_info->channels;
4332 clone_info->offset=(*offset);
4333 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4334 if (status != MagickFalse)
4335 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4336 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4337 ((MagickOffsetType) cache_info->length % page_size));
4338 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4380 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4381 const ssize_t y,
const size_t columns,
const size_t rows,
4382 const MagickBooleanType clone,
NexusInfo *nexus_info,
4385 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4390 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4394 *magick_restrict cache_info;
4403 *magick_restrict pixels;
4408 assert(image != (
const Image *) NULL);
4409 assert(image->signature == MagickCoreSignature);
4410 assert(image->cache != (Cache) NULL);
4411 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4412 if (cache_info == (Cache) NULL)
4414 assert(cache_info->signature == MagickCoreSignature);
4415 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4416 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4417 (y >= (ssize_t) cache_info->rows))
4419 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4420 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4423 if (IsValidOffset(y,cache_info->columns) == MagickFalse)
4425 offset=y*(MagickOffsetType) cache_info->columns+x;
4428 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4429 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4430 (MagickOffsetType) columns-1;
4431 if ((MagickSizeType) offset >= number_pixels)
4436 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4437 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4438 MagickTrue : MagickFalse,nexus_info,exception);
4475 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4476 const ssize_t y,
const size_t columns,
const size_t rows,
4480 *magick_restrict cache_info;
4483 id = GetOpenMPThreadId();
4485 assert(image != (
const Image *) NULL);
4486 assert(image->signature == MagickCoreSignature);
4487 assert(image->cache != (Cache) NULL);
4489 assert(cache_info->signature == MagickCoreSignature);
4490 assert(
id < (
int) cache_info->number_threads);
4491 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4492 cache_info->nexus_info[
id],exception));
4551 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4552 const ssize_t y,
const size_t columns,
const size_t rows,
4556 *magick_restrict cache_info;
4559 id = GetOpenMPThreadId();
4561 assert(image != (
Image *) NULL);
4562 assert(image->signature == MagickCoreSignature);
4563 assert(image->cache != (Cache) NULL);
4565 assert(cache_info->signature == MagickCoreSignature);
4566 if (cache_info->methods.queue_authentic_pixels_handler !=
4567 (QueueAuthenticPixelsHandler) NULL)
4568 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4570 assert(
id < (
int) cache_info->number_threads);
4571 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4572 cache_info->nexus_info[
id],exception));
4604 static inline MagickOffsetType ReadPixelCacheRegion(
4605 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4606 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4614 #if !defined(MAGICKCORE_HAVE_PREAD)
4615 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4616 return((MagickOffsetType) -1);
4618 for (i=0; i < (MagickOffsetType) length; i+=count)
4620 #if !defined(MAGICKCORE_HAVE_PREAD)
4621 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4622 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX));
4624 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4625 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX),offset+i);
4637 static MagickBooleanType ReadPixelCacheIndexes(
4658 if (cache_info->active_index_channel == MagickFalse)
4659 return(MagickFalse);
4660 if (nexus_info->authentic_pixel_cache != MagickFalse)
4662 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4663 return(MagickFalse);
4664 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4665 nexus_info->region.x;
4666 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4667 rows=nexus_info->region.height;
4669 q=nexus_info->indexes;
4671 switch (cache_info->type)
4682 if ((cache_info->columns == nexus_info->region.width) &&
4683 (extent == (MagickSizeType) ((
size_t) extent)))
4688 p=cache_info->indexes+offset;
4689 for (y=0; y < (ssize_t) rows; y++)
4691 (void) memcpy(q,p,(
size_t) length);
4692 p+=cache_info->columns;
4693 q+=nexus_info->region.width;
4702 LockSemaphoreInfo(cache_info->file_semaphore);
4703 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4705 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4706 cache_info->cache_filename);
4707 UnlockSemaphoreInfo(cache_info->file_semaphore);
4708 return(MagickFalse);
4710 if ((cache_info->columns == nexus_info->region.width) &&
4711 (extent <= MagickMaxBufferExtent))
4716 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4717 for (y=0; y < (ssize_t) rows; y++)
4719 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4720 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4721 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4722 if (count < (MagickOffsetType) length)
4724 offset+=(MagickOffsetType) cache_info->columns;
4725 q+=nexus_info->region.width;
4727 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4728 (
void) ClosePixelCacheOnDisk(cache_info);
4729 UnlockSemaphoreInfo(cache_info->file_semaphore);
4732 case DistributedCache:
4740 LockSemaphoreInfo(cache_info->file_semaphore);
4741 region=nexus_info->region;
4742 if ((cache_info->columns != nexus_info->region.width) ||
4743 (extent > MagickMaxBufferExtent))
4750 for (y=0; y < (ssize_t) rows; y++)
4753 cache_info->server_info,®ion,length,(
unsigned char *) q);
4754 if (count != (MagickOffsetType) length)
4756 q+=nexus_info->region.width;
4759 UnlockSemaphoreInfo(cache_info->file_semaphore);
4765 if (y < (ssize_t) rows)
4767 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4768 cache_info->cache_filename);
4769 return(MagickFalse);
4771 if ((cache_info->debug != MagickFalse) &&
4772 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4773 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4774 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4775 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4776 nexus_info->region.x,(
double) nexus_info->region.y);
4808 static MagickBooleanType ReadPixelCachePixels(
4829 if (nexus_info->authentic_pixel_cache != MagickFalse)
4831 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4832 return(MagickFalse);
4833 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4834 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4835 return(MagickFalse);
4836 offset+=nexus_info->region.x;
4837 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4838 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4839 return(MagickFalse);
4840 rows=nexus_info->region.height;
4842 if ((extent == 0) || ((extent/length) != rows))
4843 return(MagickFalse);
4844 q=nexus_info->pixels;
4846 switch (cache_info->type)
4857 if ((cache_info->columns == nexus_info->region.width) &&
4858 (extent == (MagickSizeType) ((
size_t) extent)))
4863 p=cache_info->pixels+offset;
4864 for (y=0; y < (ssize_t) rows; y++)
4866 (void) memcpy(q,p,(
size_t) length);
4867 p+=cache_info->columns;
4868 q+=nexus_info->region.width;
4877 LockSemaphoreInfo(cache_info->file_semaphore);
4878 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4880 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4881 cache_info->cache_filename);
4882 UnlockSemaphoreInfo(cache_info->file_semaphore);
4883 return(MagickFalse);
4885 if ((cache_info->columns == nexus_info->region.width) &&
4886 (extent <= MagickMaxBufferExtent))
4891 for (y=0; y < (ssize_t) rows; y++)
4893 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4894 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4895 if (count < (MagickOffsetType) length)
4897 offset+=(MagickOffsetType) cache_info->columns;
4898 q+=nexus_info->region.width;
4900 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4901 (
void) ClosePixelCacheOnDisk(cache_info);
4902 UnlockSemaphoreInfo(cache_info->file_semaphore);
4905 case DistributedCache:
4913 LockSemaphoreInfo(cache_info->file_semaphore);
4914 region=nexus_info->region;
4915 if ((cache_info->columns != nexus_info->region.width) ||
4916 (extent > MagickMaxBufferExtent))
4923 for (y=0; y < (ssize_t) rows; y++)
4926 cache_info->server_info,®ion,length,(
unsigned char *) q);
4927 if (count != (MagickOffsetType) length)
4929 q+=nexus_info->region.width;
4932 UnlockSemaphoreInfo(cache_info->file_semaphore);
4938 if (y < (ssize_t) rows)
4940 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4941 cache_info->cache_filename);
4942 return(MagickFalse);
4944 if ((cache_info->debug != MagickFalse) &&
4945 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4946 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4947 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4948 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4949 nexus_info->region.x,(
double) nexus_info->region.y);
4976 MagickExport Cache ReferencePixelCache(Cache cache)
4979 *magick_restrict cache_info;
4981 assert(cache != (Cache *) NULL);
4983 assert(cache_info->signature == MagickCoreSignature);
4984 LockSemaphoreInfo(cache_info->semaphore);
4985 cache_info->reference_count++;
4986 UnlockSemaphoreInfo(cache_info->semaphore);
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-5*a))))
5172 return(MagickFalse);
5173 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) 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 if (IsValidOffset(y,cache_info->columns) == MagickFalse)
5228 offset=y*(MagickOffsetType) cache_info->columns+x;
5229 nexus_info->pixels=cache_info->pixels+offset;
5230 nexus_info->indexes=(IndexPacket *) NULL;
5231 if (cache_info->active_index_channel != MagickFalse)
5232 nexus_info->indexes=cache_info->indexes+offset;
5233 nexus_info->region.width=width;
5234 nexus_info->region.height=height;
5235 nexus_info->region.x=x;
5236 nexus_info->region.y=y;
5237 nexus_info->authentic_pixel_cache=MagickTrue;
5238 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5239 return(nexus_info->pixels);
5245 number_pixels=(MagickSizeType) width*height;
5246 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5248 if (cache_info->active_index_channel != MagickFalse)
5249 length+=number_pixels*
sizeof(IndexPacket);
5252 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5254 if (nexus_info->length < length)
5256 RelinquishCacheNexusPixels(nexus_info);
5257 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5259 if (status == MagickFalse)
5261 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5264 nexus_info->pixels=nexus_info->cache;
5265 nexus_info->indexes=(IndexPacket *) NULL;
5266 if (cache_info->active_index_channel != MagickFalse)
5267 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5268 nexus_info->region.width=width;
5269 nexus_info->region.height=height;
5270 nexus_info->region.x=x;
5271 nexus_info->region.y=y;
5272 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5273 MagickTrue : MagickFalse;
5274 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5275 return(nexus_info->pixels);
5306 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5307 const Quantum opacity)
5310 *magick_restrict image_view;
5318 assert(image != (
Image *) NULL);
5319 assert(image->signature == MagickCoreSignature);
5320 if (IsEventLogging() != MagickFalse)
5321 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5322 assert(image->cache != (Cache) NULL);
5323 image->matte=MagickTrue;
5325 image_view=AcquireVirtualCacheView(image,&image->exception);
5326 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5327 #pragma omp parallel for schedule(static) shared(status) \
5328 magick_number_threads(image,image,image->rows,1)
5330 for (y=0; y < (ssize_t) image->rows; y++)
5338 if (status == MagickFalse)
5340 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5347 for (x=0; x < (ssize_t) image->columns; x++)
5352 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5354 image_view=DestroyCacheView(image_view);
5358 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5359 const VirtualPixelMethod virtual_pixel_method)
5362 *magick_restrict cache_info;
5367 assert(image != (
Image *) NULL);
5368 assert(image->signature == MagickCoreSignature);
5369 if (IsEventLogging() != MagickFalse)
5370 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5371 assert(image->cache != (Cache) NULL);
5373 assert(cache_info->signature == MagickCoreSignature);
5374 method=cache_info->virtual_pixel_method;
5375 cache_info->virtual_pixel_method=virtual_pixel_method;
5376 if ((image->columns != 0) && (image->rows != 0))
5377 switch (virtual_pixel_method)
5379 case BackgroundVirtualPixelMethod:
5381 if ((image->background_color.opacity != OpaqueOpacity) &&
5382 (image->matte == MagickFalse))
5383 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5384 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5385 (IsGrayColorspace(image->colorspace) != MagickFalse))
5386 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5389 case TransparentVirtualPixelMethod:
5391 if (image->matte == MagickFalse)
5392 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5401 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5425 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5430 assert(cache_info != (
CacheInfo *)NULL);
5431 if ((cache_info->type != MemoryCache) ||
5437 LockSemaphoreInfo(cache_info->semaphore);
5446 clEnv=GetDefaultOpenCLEnv();
5447 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5448 if (events != (cl_event *) NULL)
5462 context=GetOpenCLContext(clEnv);
5463 queue=AcquireOpenCLCommandQueue(clEnv);
5464 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5465 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5466 cache_info->length,event_count,events,NULL,&status);
5467 assert(pixels == cache_info->pixels);
5468 events=(cl_event *) RelinquishMagickMemory(events);
5469 RelinquishOpenCLCommandQueue(clEnv,queue);
5471 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5473 UnlockSemaphoreInfo(cache_info->semaphore);
5476 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5479 *magick_restrict cache_info;
5481 assert(image != (
Image *)NULL);
5483 CopyOpenCLBuffer(cache_info);
5516 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5520 *magick_restrict cache_info;
5528 assert(image != (
Image *) NULL);
5529 assert(image->signature == MagickCoreSignature);
5530 if (image->cache == (Cache) NULL)
5531 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5533 assert(cache_info->signature == MagickCoreSignature);
5534 if (cache_info->type == UndefinedCache)
5535 return(MagickFalse);
5536 if ((image->storage_class == DirectClass) &&
5537 (image->clip_mask != (
Image *) NULL) &&
5538 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5539 return(MagickFalse);
5540 if ((image->storage_class == DirectClass) &&
5541 (image->mask != (
Image *) NULL) &&
5542 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5543 return(MagickFalse);
5544 if (nexus_info->authentic_pixel_cache != MagickFalse)
5546 if (image->taint == MagickFalse)
5547 image->taint=MagickTrue;
5550 assert(cache_info->signature == MagickCoreSignature);
5551 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5552 if ((cache_info->active_index_channel != MagickFalse) &&
5553 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5554 return(MagickFalse);
5555 if ((status != MagickFalse) && (image->taint == MagickFalse))
5556 image->taint=MagickTrue;
5587 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5591 *magick_restrict cache_info;
5594 id = GetOpenMPThreadId();
5599 assert(image != (
Image *) NULL);
5600 assert(image->signature == MagickCoreSignature);
5601 assert(image->cache != (Cache) NULL);
5603 assert(cache_info->signature == MagickCoreSignature);
5604 assert(
id < (
int) cache_info->number_threads);
5605 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5637 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5641 *magick_restrict cache_info;
5644 id = GetOpenMPThreadId();
5649 assert(image != (
Image *) NULL);
5650 assert(image->signature == MagickCoreSignature);
5651 assert(image->cache != (Cache) NULL);
5653 assert(cache_info->signature == MagickCoreSignature);
5654 if (cache_info->methods.sync_authentic_pixels_handler !=
5655 (SyncAuthenticPixelsHandler) NULL)
5656 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5657 assert(
id < (
int) cache_info->number_threads);
5658 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5690 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5694 *magick_restrict cache_info;
5696 assert(image != (
Image *) NULL);
5698 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5699 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5730 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5750 if (cache_info->active_index_channel == MagickFalse)
5751 return(MagickFalse);
5752 if (nexus_info->authentic_pixel_cache != MagickFalse)
5754 if (nexus_info->indexes == (IndexPacket *) NULL)
5755 return(MagickFalse);
5756 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5757 return(MagickFalse);
5758 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5759 nexus_info->region.x;
5760 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5761 rows=nexus_info->region.height;
5762 extent=(MagickSizeType) length*rows;
5763 p=nexus_info->indexes;
5765 switch (cache_info->type)
5776 if ((cache_info->columns == nexus_info->region.width) &&
5777 (extent == (MagickSizeType) ((
size_t) extent)))
5782 q=cache_info->indexes+offset;
5783 for (y=0; y < (ssize_t) rows; y++)
5785 (void) memcpy(q,p,(
size_t) length);
5786 p+=nexus_info->region.width;
5787 q+=cache_info->columns;
5796 LockSemaphoreInfo(cache_info->file_semaphore);
5797 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5799 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5800 cache_info->cache_filename);
5801 UnlockSemaphoreInfo(cache_info->file_semaphore);
5802 return(MagickFalse);
5804 if ((cache_info->columns == nexus_info->region.width) &&
5805 (extent <= MagickMaxBufferExtent))
5810 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5811 for (y=0; y < (ssize_t) rows; y++)
5813 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5814 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5815 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5817 if (count < (MagickOffsetType) length)
5819 p+=nexus_info->region.width;
5820 offset+=(MagickOffsetType) cache_info->columns;
5822 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5823 (
void) ClosePixelCacheOnDisk(cache_info);
5824 UnlockSemaphoreInfo(cache_info->file_semaphore);
5827 case DistributedCache:
5835 LockSemaphoreInfo(cache_info->file_semaphore);
5836 region=nexus_info->region;
5837 if ((cache_info->columns != nexus_info->region.width) ||
5838 (extent > MagickMaxBufferExtent))
5845 for (y=0; y < (ssize_t) rows; y++)
5848 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5849 if (count != (MagickOffsetType) length)
5851 p+=nexus_info->region.width;
5854 UnlockSemaphoreInfo(cache_info->file_semaphore);
5860 if (y < (ssize_t) rows)
5862 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5863 cache_info->cache_filename);
5864 return(MagickFalse);
5866 if ((cache_info->debug != MagickFalse) &&
5867 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5868 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5869 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5870 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5871 nexus_info->region.x,(
double) nexus_info->region.y);
5903 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5923 if (nexus_info->authentic_pixel_cache != MagickFalse)
5925 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5926 return(MagickFalse);
5927 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5928 nexus_info->region.x;
5929 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5930 rows=nexus_info->region.height;
5932 p=nexus_info->pixels;
5934 switch (cache_info->type)
5945 if ((cache_info->columns == nexus_info->region.width) &&
5946 (extent == (MagickSizeType) ((
size_t) extent)))
5951 q=cache_info->pixels+offset;
5952 for (y=0; y < (ssize_t) rows; y++)
5954 (void) memcpy(q,p,(
size_t) length);
5955 p+=nexus_info->region.width;
5956 q+=cache_info->columns;
5965 LockSemaphoreInfo(cache_info->file_semaphore);
5966 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5968 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5969 cache_info->cache_filename);
5970 UnlockSemaphoreInfo(cache_info->file_semaphore);
5971 return(MagickFalse);
5973 if ((cache_info->columns == nexus_info->region.width) &&
5974 (extent <= MagickMaxBufferExtent))
5979 for (y=0; y < (ssize_t) rows; y++)
5981 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5982 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
5983 if (count < (MagickOffsetType) length)
5985 p+=nexus_info->region.width;
5986 offset+=(MagickOffsetType) cache_info->columns;
5988 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5989 (
void) ClosePixelCacheOnDisk(cache_info);
5990 UnlockSemaphoreInfo(cache_info->file_semaphore);
5993 case DistributedCache:
6001 LockSemaphoreInfo(cache_info->file_semaphore);
6002 region=nexus_info->region;
6003 if ((cache_info->columns != nexus_info->region.width) ||
6004 (extent > MagickMaxBufferExtent))
6011 for (y=0; y < (ssize_t) rows; y++)
6014 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6015 if (count != (MagickOffsetType) length)
6017 p+=nexus_info->region.width;
6020 UnlockSemaphoreInfo(cache_info->file_semaphore);
6026 if (y < (ssize_t) rows)
6028 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6029 cache_info->cache_filename);
6030 return(MagickFalse);
6032 if ((cache_info->debug != MagickFalse) &&
6033 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6034 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6035 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6036 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6037 nexus_info->region.x,(
double) nexus_info->region.y);