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)
111static const IndexPacket
112 *GetVirtualIndexesFromCache(
const Image *);
115 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
117 *GetVirtualPixelsCache(
const Image *);
119static 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;
183static 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);
226static 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)
294extern 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);
351MagickExport 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);
424MagickExport
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;
479MagickExport
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);
518MagickExport MagickBooleanType CacheComponentGenesis(
void)
521 cache_semaphore=AllocateSemaphoreInfo();
543MagickExport
void CacheComponentTerminus(
void)
546 ActivateSemaphoreInfo(&cache_semaphore);
548 DestroySemaphoreInfo(&cache_semaphore);
580static 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);
691MagickExport 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);
735MagickExport
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;
782static 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)
846static 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);
1018static 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);
1050MagickExport
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);
1093static 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);
1108static 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;
1168MagickExport 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);
1241static 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);
1295static 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);
1337MagickExport 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)
1381MagickPrivate 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));
1726MagickExport 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)
1773extern 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);
1823static 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);
1843static 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);
1967MagickExport CacheType GetPixelCacheType(
const Image *image)
1969 return(GetImagePixelCacheType(image));
1972MagickExport 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);
2015MagickExport 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);
2070static 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);
2129MagickExport 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);
2196MagickExport 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);
2259MagickExport 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);
2324static 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);
2377MagickExport
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);
2413MagickExport 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);
2450MagickExport
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);
2485MagickExport
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;
2528MagickExport 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);
2573MagickExport
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);
2618MagickExport 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);
2659MagickExport
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)
2696MagickExport 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);
2732static 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]));
2775MagickExport
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);
2814MagickExport
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
2884static 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);
2897static 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);
2910static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2914 if (x >= (ssize_t) columns)
2915 return((ssize_t) (columns-1));
2919static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2923 if (y >= (ssize_t) rows)
2924 return((ssize_t) (rows-1));
2928static 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);
2937static 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);
2948static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2950 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2953static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2955 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2958static 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);
2979MagickExport
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]));
3563MagickExport
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);
3628static 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);
3743static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3744 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3749 if ((count == 0) || (quantum == 0))
3751 length=count*quantum;
3752 if (quantum != (length/count))
3759 return(MagickFalse);
3762static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3771 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3773 if (*cache_info->cache_filename ==
'\0')
3774 file=AcquireUniqueFileResource(cache_info->cache_filename);
3780 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3785 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3786 O_BINARY | O_EXCL,S_MODE);
3788 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3794 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3797 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3802 return(MagickFalse);
3803 (void) AcquireMagickResource(FileResource,1);
3804 if (cache_info->file != -1)
3805 (void) ClosePixelCacheOnDisk(cache_info);
3806 cache_info->file=file;
3807 cache_info->disk_mode=mode;
3811static inline MagickOffsetType WritePixelCacheRegion(
3812 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3813 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3821#if !defined(MAGICKCORE_HAVE_PWRITE)
3822 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3823 return((MagickOffsetType) -1);
3825 for (i=0; i < (MagickOffsetType) length; i+=count)
3827#if !defined(MAGICKCORE_HAVE_PWRITE)
3828 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3829 (MagickSizeType) i,MAGICK_SSIZE_MAX));
3831 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3832 (MagickSizeType) i,MAGICK_SSIZE_MAX),offset+i);
3844static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3847 *magick_restrict cache_info;
3853 if (cache_info->debug != MagickFalse)
3856 format[MaxTextExtent],
3857 message[MaxTextExtent];
3859 (void) FormatMagickSize(length,MagickFalse,format);
3860 (void) FormatLocaleString(message,MaxTextExtent,
3861 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3862 cache_info->cache_filename,cache_info->file,format);
3863 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3865 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3867 return(MagickFalse);
3868 if ((MagickSizeType) offset < length)
3874 extent=(MagickOffsetType) length-1;
3875 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3878 return(MagickFalse);
3879#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3880 if (cache_info->synchronize != MagickFalse)
3881 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3882 return(MagickFalse);
3885 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3887 return(MagickFalse);
3891static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3895 *magick_restrict cache_info,
3899 format[MaxTextExtent],
3900 message[MaxTextExtent];
3917 assert(image != (
const Image *) NULL);
3918 assert(image->signature == MagickCoreSignature);
3919 assert(image->cache != (Cache) NULL);
3920 if (IsEventLogging() != MagickFalse)
3921 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3922 if (cache_anonymous_memory < 0)
3930 cache_anonymous_memory=0;
3931 value=GetPolicyValue(
"pixel-cache-memory");
3932 if (value == (
char *) NULL)
3933 value=GetPolicyValue(
"cache:memory-map");
3934 if (LocaleCompare(value,
"anonymous") == 0)
3936#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3937 cache_anonymous_memory=1;
3939 (void) ThrowMagickException(exception,GetMagickModule(),
3940 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3941 "'%s' (policy requires anonymous memory mapping)",image->filename);
3944 value=DestroyString(value);
3946 if ((image->columns == 0) || (image->rows == 0))
3947 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3949 assert(cache_info->signature == MagickCoreSignature);
3950 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3951 ((MagickSizeType) image->rows > cache_info->height_limit))
3952 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3954 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3956 length=GetImageListLength(image);
3957 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3958 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3961 source_info=(*cache_info);
3962 source_info.file=(-1);
3963 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3964 image->filename,(
double) image->scene);
3965 cache_info->storage_class=image->storage_class;
3966 cache_info->colorspace=image->colorspace;
3967 cache_info->rows=image->rows;
3968 cache_info->columns=image->columns;
3969 cache_info->channels=image->channels;
3970 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3971 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3972 cache_info->mode=mode;
3973 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3975 if (cache_info->active_index_channel != MagickFalse)
3976 packet_size+=
sizeof(IndexPacket);
3977 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3979 cache_info->storage_class=UndefinedClass;
3980 cache_info->length=0;
3981 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3984 columns=(size_t) (length/cache_info->rows/packet_size);
3985 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3986 ((ssize_t) cache_info->rows < 0))
3988 cache_info->storage_class=UndefinedClass;
3989 cache_info->length=0;
3990 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3993 cache_info->length=length;
3994 if (image->ping != MagickFalse)
3996 cache_info->type=PingCache;
3999 status=AcquireMagickResource(AreaResource,(MagickSizeType)
4000 cache_info->columns*cache_info->rows);
4001 if (cache_info->mode == PersistMode)
4003 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4004 if ((status != MagickFalse) &&
4005 (length == (MagickSizeType) ((
size_t) length)) &&
4006 ((cache_info->type == UndefinedCache) ||
4007 (cache_info->type == MemoryCache)))
4009 status=AcquireMagickResource(MemoryResource,cache_info->length);
4010 if (status != MagickFalse)
4013 if (cache_anonymous_memory <= 0)
4015 cache_info->mapped=MagickFalse;
4016 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
4017 AcquireAlignedMemory(1,(
size_t) cache_info->length));
4021 cache_info->mapped=MagickTrue;
4022 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
4023 cache_info->length);
4027 cache_info->mapped=source_info.mapped;
4028 cache_info->pixels=source_info.pixels;
4035 cache_info->colorspace=image->colorspace;
4036 cache_info->type=MemoryCache;
4037 cache_info->indexes=(IndexPacket *) NULL;
4038 if (cache_info->active_index_channel != MagickFalse)
4039 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4041 if ((source_info.storage_class != UndefinedClass) &&
4044 status&=ClonePixelCacheRepository(cache_info,&source_info,
4046 RelinquishPixelCachePixels(&source_info);
4048 if (cache_info->debug != MagickFalse)
4050 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4051 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4053 (void) FormatLocaleString(message,MaxTextExtent,
4054 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4055 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4056 type,(double) cache_info->columns,(double) cache_info->rows,
4058 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4061 cache_info->storage_class=image->storage_class;
4064 cache_info->type=UndefinedCache;
4065 return(MagickFalse);
4071 status=AcquireMagickResource(DiskResource,cache_info->length);
4072 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4074 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4082 server_info=AcquireDistributeCacheInfo(exception);
4085 status=OpenDistributePixelCache(server_info,image);
4086 if (status == MagickFalse)
4088 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4089 GetDistributeCacheHostname(server_info));
4090 server_info=DestroyDistributeCacheInfo(server_info);
4098 cache_info->type=DistributedCache;
4099 cache_info->storage_class=image->storage_class;
4100 cache_info->colorspace=image->colorspace;
4101 cache_info->server_info=server_info;
4102 (void) FormatLocaleString(cache_info->cache_filename,
4103 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4106 cache_info->server_info));
4107 if ((source_info.storage_class != UndefinedClass) &&
4110 status=ClonePixelCacheRepository(cache_info,&source_info,
4112 RelinquishPixelCachePixels(&source_info);
4114 if (cache_info->debug != MagickFalse)
4116 (void) FormatMagickSize(cache_info->length,MagickFalse,
4118 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4120 (void) FormatLocaleString(message,MaxTextExtent,
4121 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4122 cache_info->cache_filename,GetDistributeCacheFile(
4124 (double) cache_info->columns,(
double) cache_info->rows,
4126 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4131 cache_info->type=UndefinedCache;
4132 return(MagickFalse);
4137 cache_info->type=UndefinedCache;
4138 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4139 "CacheResourcesExhausted",
"`%s'",image->filename);
4140 return(MagickFalse);
4145 if (status == MagickFalse)
4147 cache_info->type=UndefinedCache;
4148 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4149 "CacheResourcesExhausted",
"`%s'",image->filename);
4150 return(MagickFalse);
4152 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4153 (cache_info->mode != PersistMode))
4155 (void) ClosePixelCacheOnDisk(cache_info);
4156 *cache_info->cache_filename=
'\0';
4158 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4160 cache_info->type=UndefinedCache;
4161 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4163 return(MagickFalse);
4165 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4166 cache_info->length);
4167 if (status == MagickFalse)
4169 cache_info->type=UndefinedCache;
4170 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4172 return(MagickFalse);
4174 cache_info->storage_class=image->storage_class;
4175 cache_info->colorspace=image->colorspace;
4176 cache_info->type=DiskCache;
4177 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4178 if (length == (MagickSizeType) ((size_t) length))
4180 status=AcquireMagickResource(MapResource,cache_info->length);
4181 if (status != MagickFalse)
4183 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4184 cache_info->offset,(
size_t) cache_info->length);
4187 cache_info->mapped=source_info.mapped;
4188 cache_info->pixels=source_info.pixels;
4189 RelinquishMagickResource(MapResource,cache_info->length);
4196 (void) ClosePixelCacheOnDisk(cache_info);
4197 cache_info->type=MapCache;
4198 cache_info->mapped=MagickTrue;
4199 cache_info->indexes=(IndexPacket *) NULL;
4200 if (cache_info->active_index_channel != MagickFalse)
4201 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4203 if ((source_info.storage_class != UndefinedClass) &&
4206 status=ClonePixelCacheRepository(cache_info,&source_info,
4208 RelinquishPixelCachePixels(&source_info);
4210 if (cache_info->debug != MagickFalse)
4212 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4213 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4215 (void) FormatLocaleString(message,MaxTextExtent,
4216 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4217 cache_info->filename,cache_info->cache_filename,
4218 cache_info->file,type,(
double) cache_info->columns,
4219 (double) cache_info->rows,format);
4220 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4225 cache_info->type=UndefinedCache;
4226 return(MagickFalse);
4233 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4235 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4236 RelinquishPixelCachePixels(&source_info);
4238 if (cache_info->debug != MagickFalse)
4240 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4241 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4243 (void) FormatLocaleString(message,MaxTextExtent,
4244 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4245 cache_info->cache_filename,cache_info->file,type,(
double)
4246 cache_info->columns,(double) cache_info->rows,format);
4247 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4251 cache_info->type=UndefinedCache;
4252 return(MagickFalse);
4294MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4295 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4299 *magick_restrict cache_info,
4300 *magick_restrict clone_info;
4308 assert(image != (
Image *) NULL);
4309 assert(image->signature == MagickCoreSignature);
4310 if (IsEventLogging() != MagickFalse)
4311 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4312 assert(image->cache != (
void *) NULL);
4313 assert(filename != (
const char *) NULL);
4314 assert(offset != (MagickOffsetType *) NULL);
4315 page_size=GetMagickPageSize();
4317 assert(cache_info->signature == MagickCoreSignature);
4318#if defined(MAGICKCORE_OPENCL_SUPPORT)
4319 CopyOpenCLBuffer(cache_info);
4321 if (attach != MagickFalse)
4326 if (cache_info->debug != MagickFalse)
4327 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4328 "attach persistent cache");
4329 (void) CopyMagickString(cache_info->cache_filename,filename,
4331 cache_info->type=MapCache;
4332 cache_info->offset=(*offset);
4333 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4334 return(MagickFalse);
4335 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4336 ((MagickOffsetType) cache_info->length % page_size));
4342 status=AcquireMagickResource(DiskResource,cache_info->length);
4343 if (status == MagickFalse)
4345 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4346 "CacheResourcesExhausted",
"`%s'",image->filename);
4347 return(MagickFalse);
4349 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4350 clone_info->type=DiskCache;
4351 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4352 clone_info->file=(-1);
4353 clone_info->storage_class=cache_info->storage_class;
4354 clone_info->colorspace=cache_info->colorspace;
4355 clone_info->columns=cache_info->columns;
4356 clone_info->rows=cache_info->rows;
4357 clone_info->active_index_channel=cache_info->active_index_channel;
4358 clone_info->mode=PersistMode;
4359 clone_info->length=cache_info->length;
4360 clone_info->channels=cache_info->channels;
4361 clone_info->offset=(*offset);
4362 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4363 if (status != MagickFalse)
4364 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4365 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4366 ((MagickOffsetType) cache_info->length % page_size));
4367 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4410 const ssize_t y,
const size_t columns,
const size_t rows,
4411 const MagickBooleanType clone,
NexusInfo *nexus_info,
4414 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4419 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4423 *magick_restrict cache_info;
4432 *magick_restrict pixels;
4437 assert(image != (
const Image *) NULL);
4438 assert(image->signature == MagickCoreSignature);
4439 assert(image->cache != (Cache) NULL);
4440 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4441 if (cache_info == (Cache) NULL)
4443 assert(cache_info->signature == MagickCoreSignature);
4444 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4445 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4446 (y >= (ssize_t) cache_info->rows))
4448 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4449 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4452 if (IsValidOffset(y,cache_info->columns) == MagickFalse)
4454 offset=y*(MagickOffsetType) cache_info->columns+x;
4457 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4458 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4459 (MagickOffsetType) columns-1;
4460 if ((MagickSizeType) offset >= number_pixels)
4465 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4466 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4467 MagickTrue : MagickFalse,nexus_info,exception);
4505 const ssize_t y,
const size_t columns,
const size_t rows,
4509 *magick_restrict cache_info;
4512 id = GetOpenMPThreadId();
4514 assert(image != (
const Image *) NULL);
4515 assert(image->signature == MagickCoreSignature);
4516 assert(image->cache != (Cache) NULL);
4518 assert(cache_info->signature == MagickCoreSignature);
4519 assert(
id < (
int) cache_info->number_threads);
4520 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4521 cache_info->nexus_info[
id],exception));
4580MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4581 const ssize_t y,
const size_t columns,
const size_t rows,
4585 *magick_restrict cache_info;
4588 id = GetOpenMPThreadId();
4590 assert(image != (
Image *) NULL);
4591 assert(image->signature == MagickCoreSignature);
4592 assert(image->cache != (Cache) NULL);
4594 assert(cache_info->signature == MagickCoreSignature);
4595 if (cache_info->methods.queue_authentic_pixels_handler !=
4596 (QueueAuthenticPixelsHandler) NULL)
4597 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4599 assert(
id < (
int) cache_info->number_threads);
4600 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4601 cache_info->nexus_info[
id],exception));
4633static inline MagickOffsetType ReadPixelCacheRegion(
4634 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4635 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4643#if !defined(MAGICKCORE_HAVE_PREAD)
4644 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4645 return((MagickOffsetType) -1);
4647 for (i=0; i < (MagickOffsetType) length; i+=count)
4649#if !defined(MAGICKCORE_HAVE_PREAD)
4650 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4651 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX));
4653 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4654 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX),offset+i);
4666static MagickBooleanType ReadPixelCacheIndexes(
4687 if (cache_info->active_index_channel == MagickFalse)
4688 return(MagickFalse);
4689 if (nexus_info->authentic_pixel_cache != MagickFalse)
4691 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4692 return(MagickFalse);
4693 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4694 nexus_info->region.x;
4695 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4696 rows=nexus_info->region.height;
4698 q=nexus_info->indexes;
4700 switch (cache_info->type)
4711 if ((cache_info->columns == nexus_info->region.width) &&
4712 (extent == (MagickSizeType) ((
size_t) extent)))
4717 p=cache_info->indexes+offset;
4718 for (y=0; y < (ssize_t) rows; y++)
4720 (void) memcpy(q,p,(
size_t) length);
4721 p+=cache_info->columns;
4722 q+=nexus_info->region.width;
4731 LockSemaphoreInfo(cache_info->file_semaphore);
4732 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4734 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4735 cache_info->cache_filename);
4736 UnlockSemaphoreInfo(cache_info->file_semaphore);
4737 return(MagickFalse);
4739 if ((cache_info->columns == nexus_info->region.width) &&
4740 (extent <= MagickMaxBufferExtent))
4745 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4746 for (y=0; y < (ssize_t) rows; y++)
4748 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4749 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4750 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4751 if (count < (MagickOffsetType) length)
4753 offset+=(MagickOffsetType) cache_info->columns;
4754 q+=nexus_info->region.width;
4756 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4757 (void) ClosePixelCacheOnDisk(cache_info);
4758 UnlockSemaphoreInfo(cache_info->file_semaphore);
4761 case DistributedCache:
4769 LockSemaphoreInfo(cache_info->file_semaphore);
4770 region=nexus_info->region;
4771 if ((cache_info->columns != nexus_info->region.width) ||
4772 (extent > MagickMaxBufferExtent))
4779 for (y=0; y < (ssize_t) rows; y++)
4782 cache_info->server_info,®ion,length,(
unsigned char *) q);
4783 if (count != (MagickOffsetType) length)
4785 q+=nexus_info->region.width;
4788 UnlockSemaphoreInfo(cache_info->file_semaphore);
4794 if (y < (ssize_t) rows)
4796 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4797 cache_info->cache_filename);
4798 return(MagickFalse);
4800 if ((cache_info->debug != MagickFalse) &&
4801 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4802 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4803 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4804 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4805 nexus_info->region.x,(
double) nexus_info->region.y);
4837static MagickBooleanType ReadPixelCachePixels(
4858 if (nexus_info->authentic_pixel_cache != MagickFalse)
4860 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4861 return(MagickFalse);
4862 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4863 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4864 return(MagickFalse);
4865 offset+=nexus_info->region.x;
4866 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4867 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4868 return(MagickFalse);
4869 rows=nexus_info->region.height;
4871 if ((extent == 0) || ((extent/length) != rows))
4872 return(MagickFalse);
4873 q=nexus_info->pixels;
4875 switch (cache_info->type)
4886 if ((cache_info->columns == nexus_info->region.width) &&
4887 (extent == (MagickSizeType) ((
size_t) extent)))
4892 p=cache_info->pixels+offset;
4893 for (y=0; y < (ssize_t) rows; y++)
4895 (void) memcpy(q,p,(
size_t) length);
4896 p+=cache_info->columns;
4897 q+=nexus_info->region.width;
4906 LockSemaphoreInfo(cache_info->file_semaphore);
4907 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4909 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4910 cache_info->cache_filename);
4911 UnlockSemaphoreInfo(cache_info->file_semaphore);
4912 return(MagickFalse);
4914 if ((cache_info->columns == nexus_info->region.width) &&
4915 (extent <= MagickMaxBufferExtent))
4920 for (y=0; y < (ssize_t) rows; y++)
4922 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4923 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4924 if (count < (MagickOffsetType) length)
4926 offset+=(MagickOffsetType) cache_info->columns;
4927 q+=nexus_info->region.width;
4929 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4930 (void) ClosePixelCacheOnDisk(cache_info);
4931 UnlockSemaphoreInfo(cache_info->file_semaphore);
4934 case DistributedCache:
4942 LockSemaphoreInfo(cache_info->file_semaphore);
4943 region=nexus_info->region;
4944 if ((cache_info->columns != nexus_info->region.width) ||
4945 (extent > MagickMaxBufferExtent))
4952 for (y=0; y < (ssize_t) rows; y++)
4955 cache_info->server_info,®ion,length,(
unsigned char *) q);
4956 if (count != (MagickOffsetType) length)
4958 q+=nexus_info->region.width;
4961 UnlockSemaphoreInfo(cache_info->file_semaphore);
4967 if (y < (ssize_t) rows)
4969 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4970 cache_info->cache_filename);
4971 return(MagickFalse);
4973 if ((cache_info->debug != MagickFalse) &&
4974 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4975 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4976 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4977 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4978 nexus_info->region.x,(
double) nexus_info->region.y);
5005MagickExport Cache ReferencePixelCache(Cache cache)
5008 *magick_restrict cache_info;
5010 assert(cache != (Cache *) NULL);
5012 assert(cache_info->signature == MagickCoreSignature);
5013 LockSemaphoreInfo(cache_info->semaphore);
5014 cache_info->reference_count++;
5015 UnlockSemaphoreInfo(cache_info->semaphore);
5043MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5046 *magick_restrict cache_info;
5048 GetOneAuthenticPixelFromHandler
5049 get_one_authentic_pixel_from_handler;
5051 GetOneVirtualPixelFromHandler
5052 get_one_virtual_pixel_from_handler;
5057 assert(cache != (Cache) NULL);
5060 assert(cache_info->signature == MagickCoreSignature);
5061 if (IsEventLogging() != MagickFalse)
5062 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5063 cache_info->filename);
5064 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5065 cache_info->methods.get_virtual_pixel_handler=
5066 cache_methods->get_virtual_pixel_handler;
5067 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5068 cache_info->methods.destroy_pixel_handler=
5069 cache_methods->destroy_pixel_handler;
5070 if (cache_methods->get_virtual_indexes_from_handler !=
5071 (GetVirtualIndexesFromHandler) NULL)
5072 cache_info->methods.get_virtual_indexes_from_handler=
5073 cache_methods->get_virtual_indexes_from_handler;
5074 if (cache_methods->get_authentic_pixels_handler !=
5075 (GetAuthenticPixelsHandler) NULL)
5076 cache_info->methods.get_authentic_pixels_handler=
5077 cache_methods->get_authentic_pixels_handler;
5078 if (cache_methods->queue_authentic_pixels_handler !=
5079 (QueueAuthenticPixelsHandler) NULL)
5080 cache_info->methods.queue_authentic_pixels_handler=
5081 cache_methods->queue_authentic_pixels_handler;
5082 if (cache_methods->sync_authentic_pixels_handler !=
5083 (SyncAuthenticPixelsHandler) NULL)
5084 cache_info->methods.sync_authentic_pixels_handler=
5085 cache_methods->sync_authentic_pixels_handler;
5086 if (cache_methods->get_authentic_pixels_from_handler !=
5087 (GetAuthenticPixelsFromHandler) NULL)
5088 cache_info->methods.get_authentic_pixels_from_handler=
5089 cache_methods->get_authentic_pixels_from_handler;
5090 if (cache_methods->get_authentic_indexes_from_handler !=
5091 (GetAuthenticIndexesFromHandler) NULL)
5092 cache_info->methods.get_authentic_indexes_from_handler=
5093 cache_methods->get_authentic_indexes_from_handler;
5094 get_one_virtual_pixel_from_handler=
5095 cache_info->methods.get_one_virtual_pixel_from_handler;
5096 if (get_one_virtual_pixel_from_handler !=
5097 (GetOneVirtualPixelFromHandler) NULL)
5098 cache_info->methods.get_one_virtual_pixel_from_handler=
5099 cache_methods->get_one_virtual_pixel_from_handler;
5100 get_one_authentic_pixel_from_handler=
5101 cache_methods->get_one_authentic_pixel_from_handler;
5102 if (get_one_authentic_pixel_from_handler !=
5103 (GetOneAuthenticPixelFromHandler) NULL)
5104 cache_info->methods.get_one_authentic_pixel_from_handler=
5105 cache_methods->get_one_authentic_pixel_from_handler;
5146static inline MagickBooleanType AcquireCacheNexusPixels(
5147 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5150 if (length != (MagickSizeType) ((
size_t) length))
5152 (void) ThrowMagickException(exception,GetMagickModule(),
5153 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5154 cache_info->filename);
5155 return(MagickFalse);
5157 nexus_info->length=0;
5158 nexus_info->mapped=MagickFalse;
5159 if (cache_anonymous_memory <= 0)
5161 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5162 AcquireAlignedMemory(1,(
size_t) length));
5164 (
void) memset(nexus_info->cache,0,(
size_t) length);
5168 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5170 nexus_info->mapped=MagickTrue;
5174 (void) ThrowMagickException(exception,GetMagickModule(),
5175 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5176 cache_info->filename);
5177 return(MagickFalse);
5179 nexus_info->length=length;
5183static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5186 if (nexus_info->length < CACHE_LINE_SIZE)
5188 if (mode == ReadMode)
5190 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5194 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5197static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5200 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5201 return(MagickFalse);
5202 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5203 return(MagickFalse);
5208 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5209 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5210 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5220 assert(cache_info != (
const CacheInfo *) NULL);
5221 assert(cache_info->signature == MagickCoreSignature);
5222 if (cache_info->type == UndefinedCache)
5224 assert(nexus_info->signature == MagickCoreSignature);
5225 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5226 if ((width == 0) || (height == 0))
5228 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5229 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5232 if (((MagickSizeType) width > cache_info->width_limit) ||
5233 ((MagickSizeType) height > cache_info->height_limit) ||
5234 (ValidatePixelOffset(x,width) == MagickFalse) ||
5235 (ValidatePixelOffset(y,height) == MagickFalse))
5237 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5238 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5241 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5242 (buffered == MagickFalse))
5244 if (((x >= 0) && (y >= 0) &&
5245 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5246 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5247 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5255 if (IsValidOffset(y,cache_info->columns) == MagickFalse)
5257 offset=y*(MagickOffsetType) cache_info->columns+x;
5258 nexus_info->pixels=cache_info->pixels+offset;
5259 nexus_info->indexes=(IndexPacket *) NULL;
5260 if (cache_info->active_index_channel != MagickFalse)
5261 nexus_info->indexes=cache_info->indexes+offset;
5262 nexus_info->region.width=width;
5263 nexus_info->region.height=height;
5264 nexus_info->region.x=x;
5265 nexus_info->region.y=y;
5266 nexus_info->authentic_pixel_cache=MagickTrue;
5267 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5268 return(nexus_info->pixels);
5274 number_pixels=(MagickSizeType) width*height;
5275 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5277 if (cache_info->active_index_channel != MagickFalse)
5278 length+=number_pixels*
sizeof(IndexPacket);
5281 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5283 if (nexus_info->length < length)
5285 RelinquishCacheNexusPixels(nexus_info);
5286 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5288 if (status == MagickFalse)
5290 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5293 nexus_info->pixels=nexus_info->cache;
5294 nexus_info->indexes=(IndexPacket *) NULL;
5295 if (cache_info->active_index_channel != MagickFalse)
5296 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5297 nexus_info->region.width=width;
5298 nexus_info->region.height=height;
5299 nexus_info->region.x=x;
5300 nexus_info->region.y=y;
5301 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5302 MagickTrue : MagickFalse;
5303 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5304 return(nexus_info->pixels);
5335static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5336 const Quantum opacity)
5339 *magick_restrict image_view;
5347 assert(image != (
Image *) NULL);
5348 assert(image->signature == MagickCoreSignature);
5349 if (IsEventLogging() != MagickFalse)
5350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5351 assert(image->cache != (Cache) NULL);
5352 image->matte=MagickTrue;
5354 image_view=AcquireVirtualCacheView(image,&image->exception);
5355#if defined(MAGICKCORE_OPENMP_SUPPORT)
5356 #pragma omp parallel for schedule(static) shared(status) \
5357 magick_number_threads(image,image,image->rows,1)
5359 for (y=0; y < (ssize_t) image->rows; y++)
5367 if (status == MagickFalse)
5369 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5376 for (x=0; x < (ssize_t) image->columns; x++)
5381 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5383 image_view=DestroyCacheView(image_view);
5387MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5388 const VirtualPixelMethod virtual_pixel_method)
5391 *magick_restrict cache_info;
5396 assert(image != (
Image *) NULL);
5397 assert(image->signature == MagickCoreSignature);
5398 if (IsEventLogging() != MagickFalse)
5399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5400 assert(image->cache != (Cache) NULL);
5402 assert(cache_info->signature == MagickCoreSignature);
5403 method=cache_info->virtual_pixel_method;
5404 cache_info->virtual_pixel_method=virtual_pixel_method;
5405 if ((image->columns != 0) && (image->rows != 0))
5406 switch (virtual_pixel_method)
5408 case BackgroundVirtualPixelMethod:
5410 if ((image->background_color.opacity != OpaqueOpacity) &&
5411 (image->matte == MagickFalse))
5412 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5413 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5414 (IsGrayColorspace(image->colorspace) != MagickFalse))
5415 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5418 case TransparentVirtualPixelMethod:
5420 if (image->matte == MagickFalse)
5421 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5430#if defined(MAGICKCORE_OPENCL_SUPPORT)
5454static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5459 assert(cache_info != (
CacheInfo *)NULL);
5460 if ((cache_info->type != MemoryCache) ||
5466 LockSemaphoreInfo(cache_info->semaphore);
5475 clEnv=GetDefaultOpenCLEnv();
5476 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5477 if (events != (cl_event *) NULL)
5491 context=GetOpenCLContext(clEnv);
5492 queue=AcquireOpenCLCommandQueue(clEnv);
5493 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5494 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5495 cache_info->length,event_count,events,NULL,&status);
5496 assert(pixels == cache_info->pixels);
5497 events=(cl_event *) RelinquishMagickMemory(events);
5498 RelinquishOpenCLCommandQueue(clEnv,queue);
5500 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5502 UnlockSemaphoreInfo(cache_info->semaphore);
5505MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5508 *magick_restrict cache_info;
5510 assert(image != (
Image *)NULL);
5512 CopyOpenCLBuffer(cache_info);
5545MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5549 *magick_restrict cache_info;
5557 assert(image != (
Image *) NULL);
5558 assert(image->signature == MagickCoreSignature);
5559 if (image->cache == (Cache) NULL)
5560 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5562 assert(cache_info->signature == MagickCoreSignature);
5563 if (cache_info->type == UndefinedCache)
5564 return(MagickFalse);
5565 if ((image->storage_class == DirectClass) &&
5566 (image->clip_mask != (
Image *) NULL) &&
5567 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5568 return(MagickFalse);
5569 if ((image->storage_class == DirectClass) &&
5570 (image->mask != (
Image *) NULL) &&
5571 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5572 return(MagickFalse);
5573 if (nexus_info->authentic_pixel_cache != MagickFalse)
5575 if (image->taint == MagickFalse)
5576 image->taint=MagickTrue;
5579 assert(cache_info->signature == MagickCoreSignature);
5580 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5581 if ((cache_info->active_index_channel != MagickFalse) &&
5582 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5583 return(MagickFalse);
5584 if ((status != MagickFalse) && (image->taint == MagickFalse))
5585 image->taint=MagickTrue;
5616static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5620 *magick_restrict cache_info;
5623 id = GetOpenMPThreadId();
5628 assert(image != (
Image *) NULL);
5629 assert(image->signature == MagickCoreSignature);
5630 assert(image->cache != (Cache) NULL);
5632 assert(cache_info->signature == MagickCoreSignature);
5633 assert(
id < (
int) cache_info->number_threads);
5634 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5666MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5670 *magick_restrict cache_info;
5673 id = GetOpenMPThreadId();
5678 assert(image != (
Image *) NULL);
5679 assert(image->signature == MagickCoreSignature);
5680 assert(image->cache != (Cache) NULL);
5682 assert(cache_info->signature == MagickCoreSignature);
5683 if (cache_info->methods.sync_authentic_pixels_handler !=
5684 (SyncAuthenticPixelsHandler) NULL)
5685 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5686 assert(
id < (
int) cache_info->number_threads);
5687 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5719MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5723 *magick_restrict cache_info;
5725 assert(image != (
Image *) NULL);
5727 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5728 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5759static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5779 if (cache_info->active_index_channel == MagickFalse)
5780 return(MagickFalse);
5781 if (nexus_info->authentic_pixel_cache != MagickFalse)
5783 if (nexus_info->indexes == (IndexPacket *) NULL)
5784 return(MagickFalse);
5785 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5786 return(MagickFalse);
5787 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5788 nexus_info->region.x;
5789 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5790 rows=nexus_info->region.height;
5791 extent=(MagickSizeType) length*rows;
5792 p=nexus_info->indexes;
5794 switch (cache_info->type)
5805 if ((cache_info->columns == nexus_info->region.width) &&
5806 (extent == (MagickSizeType) ((
size_t) extent)))
5811 q=cache_info->indexes+offset;
5812 for (y=0; y < (ssize_t) rows; y++)
5814 (void) memcpy(q,p,(
size_t) length);
5815 p+=nexus_info->region.width;
5816 q+=cache_info->columns;
5825 LockSemaphoreInfo(cache_info->file_semaphore);
5826 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5828 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5829 cache_info->cache_filename);
5830 UnlockSemaphoreInfo(cache_info->file_semaphore);
5831 return(MagickFalse);
5833 if ((cache_info->columns == nexus_info->region.width) &&
5834 (extent <= MagickMaxBufferExtent))
5839 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5840 for (y=0; y < (ssize_t) rows; y++)
5842 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5843 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5844 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5846 if (count < (MagickOffsetType) length)
5848 p+=nexus_info->region.width;
5849 offset+=(MagickOffsetType) cache_info->columns;
5851 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5852 (void) ClosePixelCacheOnDisk(cache_info);
5853 UnlockSemaphoreInfo(cache_info->file_semaphore);
5856 case DistributedCache:
5864 LockSemaphoreInfo(cache_info->file_semaphore);
5865 region=nexus_info->region;
5866 if ((cache_info->columns != nexus_info->region.width) ||
5867 (extent > MagickMaxBufferExtent))
5874 for (y=0; y < (ssize_t) rows; y++)
5877 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5878 if (count != (MagickOffsetType) length)
5880 p+=nexus_info->region.width;
5883 UnlockSemaphoreInfo(cache_info->file_semaphore);
5889 if (y < (ssize_t) rows)
5891 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5892 cache_info->cache_filename);
5893 return(MagickFalse);
5895 if ((cache_info->debug != MagickFalse) &&
5896 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5897 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5898 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5899 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5900 nexus_info->region.x,(
double) nexus_info->region.y);
5932static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5952 if (nexus_info->authentic_pixel_cache != MagickFalse)
5954 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5955 return(MagickFalse);
5956 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5957 nexus_info->region.x;
5958 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5959 rows=nexus_info->region.height;
5961 p=nexus_info->pixels;
5963 switch (cache_info->type)
5974 if ((cache_info->columns == nexus_info->region.width) &&
5975 (extent == (MagickSizeType) ((
size_t) extent)))
5980 q=cache_info->pixels+offset;
5981 for (y=0; y < (ssize_t) rows; y++)
5983 (void) memcpy(q,p,(
size_t) length);
5984 p+=nexus_info->region.width;
5985 q+=cache_info->columns;
5994 LockSemaphoreInfo(cache_info->file_semaphore);
5995 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5997 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5998 cache_info->cache_filename);
5999 UnlockSemaphoreInfo(cache_info->file_semaphore);
6000 return(MagickFalse);
6002 if ((cache_info->columns == nexus_info->region.width) &&
6003 (extent <= MagickMaxBufferExtent))
6008 for (y=0; y < (ssize_t) rows; y++)
6010 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6011 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6012 if (count < (MagickOffsetType) length)
6014 p+=nexus_info->region.width;
6015 offset+=(MagickOffsetType) cache_info->columns;
6017 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6018 (void) ClosePixelCacheOnDisk(cache_info);
6019 UnlockSemaphoreInfo(cache_info->file_semaphore);
6022 case DistributedCache:
6030 LockSemaphoreInfo(cache_info->file_semaphore);
6031 region=nexus_info->region;
6032 if ((cache_info->columns != nexus_info->region.width) ||
6033 (extent > MagickMaxBufferExtent))
6040 for (y=0; y < (ssize_t) rows; y++)
6043 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6044 if (count != (MagickOffsetType) length)
6046 p+=nexus_info->region.width;
6049 UnlockSemaphoreInfo(cache_info->file_semaphore);
6055 if (y < (ssize_t) rows)
6057 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6058 cache_info->cache_filename);
6059 return(MagickFalse);
6061 if ((cache_info->debug != MagickFalse) &&
6062 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6063 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6064 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6065 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6066 nexus_info->region.x,(
double) nexus_info->region.y);