43 #include "magick/studio.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/cache.h"
47 #include "magick/cache-private.h"
48 #include "magick/color-private.h"
49 #include "magick/colorspace.h"
50 #include "magick/colorspace-private.h"
51 #include "magick/composite-private.h"
52 #include "magick/distribute-cache-private.h"
53 #include "magick/exception.h"
54 #include "magick/exception-private.h"
55 #include "magick/geometry.h"
56 #include "magick/list.h"
57 #include "magick/log.h"
58 #include "magick/magick.h"
59 #include "magick/memory_.h"
60 #include "magick/memory-private.h"
61 #include "magick/nt-base-private.h"
62 #include "magick/option.h"
63 #include "magick/pixel.h"
64 #include "magick/pixel-accessor.h"
65 #include "magick/pixel-private.h"
66 #include "magick/policy.h"
67 #include "magick/quantum.h"
68 #include "magick/random_.h"
69 #include "magick/registry.h"
70 #include "magick/resource_.h"
71 #include "magick/semaphore.h"
72 #include "magick/splay-tree.h"
73 #include "magick/string_.h"
74 #include "magick/string-private.h"
75 #include "magick/thread-private.h"
76 #include "magick/timer-private.h"
77 #include "magick/utility.h"
78 #include "magick/utility-private.h"
79 #if defined(MAGICKCORE_ZLIB_DELEGATE)
86 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
87 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
88 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
103 #if defined(__cplusplus) || defined(c_plusplus)
111 static const IndexPacket
112 *GetVirtualIndexesFromCache(const
Image *);
115 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
117 *GetVirtualPixelsCache(const Image *);
119 static MagickBooleanType
120 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,
122 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
123 const ssize_t,const ssize_t,PixelPacket *,ExceptionInfo *),
124 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
125 OpenPixelCacheOnDisk(
CacheInfo *,const MapMode),
126 ReadPixelCacheIndexes(CacheInfo *magick_restrict,
NexusInfo *magick_restrict,
128 ReadPixelCachePixels(CacheInfo *magick_restrict,
NexusInfo *magick_restrict,
130 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
131 WritePixelCacheIndexes(CacheInfo *,
NexusInfo *magick_restrict,
133 WritePixelCachePixels(CacheInfo *,
NexusInfo *magick_restrict,
137 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const
size_t,
138 const
size_t,ExceptionInfo *),
139 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const
size_t,
140 const
size_t,ExceptionInfo *),
141 *SetPixelCacheNexusPixels(const CacheInfo *magick_restrict,const MapMode,
142 const ssize_t,const ssize_t,const
size_t,const
size_t,
143 const MagickBooleanType,
NexusInfo *magick_restrict,ExceptionInfo *)
146 #if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(CacheInfo *magick_restrict);
151 #if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
167 #if defined(MAGICKCORE_OPENCL_SUPPORT)
174 for (i=0; i < (ssize_t) info->event_count; i++)
175 clEnv->library->clReleaseEvent(info->events[i]);
176 info->events=(cl_event *) RelinquishMagickMemory(info->events);
177 DestroySemaphoreInfo(&info->events_semaphore);
178 if (info->buffer != (cl_mem) NULL)
180 clEnv->library->clReleaseMemObject(info->buffer);
181 info->buffer=(cl_mem) NULL;
186 static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
187 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
202 magick_unreferenced(event);
203 magick_unreferenced(event_command_exec_status);
205 clEnv=GetDefaultOpenCLEnv();
206 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
214 status=clEnv->library->clGetEventInfo(info->events[i],
215 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
216 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
218 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
219 &RelinquishPixelCachePixelsDelayed,info);
224 RelinquishMagickResource(MemoryResource,info->length);
225 (void) RelinquishOpenCLCacheInfo(clEnv,info);
226 (void) RelinquishAlignedMemory(pixels);
229 static MagickBooleanType RelinquishOpenCLBuffer(
235 assert(cache_info != (
CacheInfo *) NULL);
238 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
243 cl_uint *event_count)
252 events=(cl_event *) NULL;
253 LockSemaphoreInfo(opencl_info->events_semaphore);
254 *event_count=opencl_info->event_count;
255 if (*event_count > 0)
257 events=AcquireQuantumMemory(*event_count,
sizeof(*events));
258 if (events == (cl_event *) NULL)
262 for (i=0; i < opencl_info->event_count; i++)
263 events[i]=opencl_info->events[i];
266 UnlockSemaphoreInfo(opencl_info->events_semaphore);
271 #if defined(MAGICKCORE_OPENCL_SUPPORT)
297 extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
300 *magick_restrict cache_info;
305 assert(image != (
const Image *) NULL);
306 assert(event != (cl_event) NULL);
309 clEnv=GetDefaultOpenCLEnv();
310 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
312 clEnv->library->clWaitForEvents(1,&event);
315 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
316 if (cache_info->opencl->events == (cl_event *) NULL)
318 cache_info->opencl->events=AcquireMagickMemory(
sizeof(
319 *cache_info->opencl->events));
320 cache_info->opencl->event_count=1;
323 cache_info->opencl->events=ResizeQuantumMemory(cache_info->opencl->events,
324 ++cache_info->opencl->event_count,
sizeof(*cache_info->opencl->events));
325 if (cache_info->opencl->events == (cl_event *) NULL)
326 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
327 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
328 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
354 MagickExport Cache AcquirePixelCache(
const size_t number_threads)
357 *magick_restrict cache_info;
362 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
364 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
365 (void) memset(cache_info,0,
sizeof(*cache_info));
366 cache_info->type=UndefinedCache;
367 cache_info->mode=IOMode;
368 cache_info->disk_mode=IOMode;
369 cache_info->colorspace=sRGBColorspace;
370 cache_info->channels=4;
371 cache_info->file=(-1);
372 cache_info->id=GetMagickThreadId();
373 cache_info->number_threads=number_threads;
374 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
375 cache_info->number_threads=GetOpenMPMaximumThreads();
376 if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
377 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
378 if (cache_info->number_threads == 0)
379 cache_info->number_threads=1;
380 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
381 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
382 if (value != (
const char *) NULL)
384 cache_info->synchronize=IsStringTrue(value);
385 value=DestroyString(value);
387 value=GetPolicyValue(
"cache:synchronize");
388 if (value != (
const char *) NULL)
390 cache_info->synchronize=IsStringTrue(value);
391 value=DestroyString(value);
393 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
394 (MagickSizeType) MAGICK_SSIZE_MAX);
395 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
396 (MagickSizeType) MAGICK_SSIZE_MAX);
397 cache_info->semaphore=AllocateSemaphoreInfo();
398 cache_info->reference_count=1;
399 cache_info->file_semaphore=AllocateSemaphoreInfo();
400 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
401 cache_info->signature=MagickCoreSignature;
402 return((Cache ) cache_info);
427 MagickExport
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
430 **magick_restrict nexus_info;
435 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
436 number_threads,
sizeof(*nexus_info)));
438 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
439 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
440 2*
sizeof(**nexus_info));
442 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
443 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
444 for (i=0; i < (ssize_t) (2*number_threads); i++)
446 nexus_info[i]=(*nexus_info+i);
447 if (i < (ssize_t) number_threads)
448 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
449 nexus_info[i]->signature=MagickCoreSignature;
482 MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
486 *magick_restrict cache_info;
488 assert(image != (
const Image *) NULL);
489 assert(image->signature == MagickCoreSignature);
491 assert(exception->signature == MagickCoreSignature);
492 assert(image->cache != (Cache) NULL);
494 assert(cache_info->signature == MagickCoreSignature);
497 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
498 return((
const void *) NULL);
499 *length=cache_info->length;
500 return((
const void *) cache_info->pixels);
521 MagickExport MagickBooleanType CacheComponentGenesis(
void)
524 cache_semaphore=AllocateSemaphoreInfo();
546 MagickExport
void CacheComponentTerminus(
void)
549 ActivateSemaphoreInfo(&cache_semaphore);
551 DestroySemaphoreInfo(&cache_semaphore);
583 static MagickBooleanType ClipPixelCacheNexus(
Image *image,
587 *magick_restrict cache_info;
593 *magick_restrict nexus_indexes,
594 *magick_restrict indexes;
600 **magick_restrict clip_nexus;
612 if (IsEventLogging() != MagickFalse)
613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
614 if ((image->clip_mask == (
Image *) NULL) ||
615 (image->storage_class == PseudoClass))
617 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
620 if (cache_info == (Cache) NULL)
622 clip_nexus=AcquirePixelCacheNexus(1);
623 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
624 nexus_info->region.width,nexus_info->region.height,
625 nexus_info->virtual_nexus,exception);
626 indexes=nexus_info->virtual_nexus->indexes;
627 q=nexus_info->pixels;
628 nexus_indexes=nexus_info->indexes;
629 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
630 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
631 nexus_info->region.height,clip_nexus[0],exception);
636 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
641 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
646 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
647 if (fabs(mask_alpha) >= MagickEpsilon)
649 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
650 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
651 GetPixelOpacity(q)));
652 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
653 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
654 GetPixelOpacity(q)));
655 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
656 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
657 GetPixelOpacity(q)));
658 SetPixelOpacity(q,GetPixelOpacity(p));
659 if (cache_info->active_index_channel != MagickFalse)
660 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
668 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
694 MagickExport Cache ClonePixelCache(
const Cache cache)
697 *magick_restrict clone_info;
700 *magick_restrict cache_info;
702 assert(cache != NULL);
704 assert(cache_info->signature == MagickCoreSignature);
705 if (IsEventLogging() != MagickFalse)
706 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
707 cache_info->filename);
708 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
709 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
710 return((Cache ) clone_info);
738 MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
741 *magick_restrict cache_info,
742 *magick_restrict source_info;
744 assert(clone != (Cache) NULL);
746 assert(source_info->signature == MagickCoreSignature);
747 if (IsEventLogging() != MagickFalse)
748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
749 source_info->filename);
750 assert(cache != (Cache) NULL);
752 assert(cache_info->signature == MagickCoreSignature);
753 source_info->methods=cache_info->methods;
785 static MagickBooleanType ClonePixelCacheOnDisk(
806 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
807 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
809 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
810 (lseek(clone_info->file,0,SEEK_SET) < 0))
812 quantum=(size_t) MagickMaxBufferExtent;
813 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
815 #if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
816 if (cache_info->length < 0x7ffff000)
818 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
819 (
size_t) cache_info->length);
820 if (count == (ssize_t) cache_info->length)
822 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
823 (lseek(clone_info->file,0,SEEK_SET) < 0))
827 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
829 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
830 if (buffer == (
unsigned char *) NULL)
831 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
833 while ((count=read(cache_info->file,buffer,quantum)) > 0)
838 number_bytes=write(clone_info->file,buffer,(
size_t) count);
839 if (number_bytes != count)
841 extent+=(size_t) number_bytes;
843 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
844 if (extent != cache_info->length)
849 static MagickBooleanType ClonePixelCacheRepository(
853 #define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
854 #define cache_number_threads(source,destination,chunk,multithreaded) \
855 num_threads((multithreaded) == 0 ? 1 : \
856 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
857 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
858 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
859 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
865 **magick_restrict cache_nexus,
866 **magick_restrict clone_nexus;
874 assert(cache_info != (
CacheInfo *) NULL);
875 assert(clone_info != (
CacheInfo *) NULL);
877 if (cache_info->type == PingCache)
879 if ((cache_info->storage_class == clone_info->storage_class) &&
880 (cache_info->colorspace == clone_info->colorspace) &&
881 (cache_info->channels == clone_info->channels) &&
882 (cache_info->columns == clone_info->columns) &&
883 (cache_info->rows == clone_info->rows) &&
884 (cache_info->active_index_channel == clone_info->active_index_channel))
889 if (((cache_info->type == MemoryCache) ||
890 (cache_info->type == MapCache)) &&
891 ((clone_info->type == MemoryCache) ||
892 (clone_info->type == MapCache)))
894 (void) memcpy(clone_info->pixels,cache_info->pixels,
895 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
896 if ((cache_info->active_index_channel != MagickFalse) &&
897 (clone_info->active_index_channel != MagickFalse))
898 (void) memcpy(clone_info->indexes,cache_info->indexes,
899 cache_info->columns*cache_info->rows*
900 sizeof(*cache_info->indexes));
903 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
904 return(ClonePixelCacheOnDisk(cache_info,clone_info));
909 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
910 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
911 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
912 sizeof(*cache_info->pixels);
914 #if defined(MAGICKCORE_OPENMP_SUPPORT)
915 #pragma omp parallel for schedule(static) shared(status) \
916 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
918 for (y=0; y < (ssize_t) cache_info->rows; y++)
921 id = GetOpenMPThreadId();
926 if (status == MagickFalse)
928 if (y >= (ssize_t) clone_info->rows)
930 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
931 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
934 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
935 if (status == MagickFalse)
937 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
938 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
941 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
942 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
943 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
945 if ((cache_info->active_index_channel != MagickFalse) &&
946 (clone_info->active_index_channel != MagickFalse))
951 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
952 sizeof(*cache_info->indexes);
953 #if defined(MAGICKCORE_OPENMP_SUPPORT)
954 #pragma omp parallel for schedule(static) shared(status) \
955 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
957 for (y=0; y < (ssize_t) cache_info->rows; y++)
960 id = GetOpenMPThreadId();
965 if (status == MagickFalse)
967 if (y >= (ssize_t) clone_info->rows)
969 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
970 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
973 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
974 if (status == MagickFalse)
976 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
977 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
980 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
981 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
984 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
985 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
986 if (cache_info->debug != MagickFalse)
989 message[MaxTextExtent];
991 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
992 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
993 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
994 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1021 static void DestroyImagePixelCache(
Image *image)
1023 assert(image != (
Image *) NULL);
1024 assert(image->signature == MagickCoreSignature);
1025 if (IsEventLogging() != MagickFalse)
1026 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1027 if (image->cache != (
void *) NULL)
1028 image->cache=DestroyPixelCache(image->cache);
1053 MagickExport
void DestroyImagePixels(
Image *image)
1056 *magick_restrict cache_info;
1058 assert(image != (
const Image *) NULL);
1059 assert(image->signature == MagickCoreSignature);
1060 if (IsEventLogging() != MagickFalse)
1061 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1062 assert(image->cache != (Cache) NULL);
1064 assert(cache_info->signature == MagickCoreSignature);
1065 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1067 cache_info->methods.destroy_pixel_handler(image);
1070 image->cache=DestroyPixelCache(image->cache);
1096 static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1102 if (cache_info->file != -1)
1104 status=close(cache_info->file);
1105 cache_info->file=(-1);
1106 RelinquishMagickResource(FileResource,1);
1108 return(status == -1 ? MagickFalse : MagickTrue);
1111 static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1113 switch (cache_info->type)
1117 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1118 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1119 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1125 if (cache_info->mapped == MagickFalse)
1126 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1127 cache_info->pixels);
1130 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1133 RelinquishMagickResource(MemoryResource,cache_info->length);
1138 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1140 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1141 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1142 *cache_info->cache_filename=
'\0';
1143 RelinquishMagickResource(MapResource,cache_info->length);
1148 if (cache_info->file != -1)
1149 (void) ClosePixelCacheOnDisk(cache_info);
1150 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1151 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1152 *cache_info->cache_filename=
'\0';
1153 RelinquishMagickResource(DiskResource,cache_info->length);
1156 case DistributedCache:
1158 *cache_info->cache_filename=
'\0';
1160 cache_info->server_info);
1166 cache_info->type=UndefinedCache;
1167 cache_info->mapped=MagickFalse;
1168 cache_info->indexes=(IndexPacket *) NULL;
1171 MagickExport Cache DestroyPixelCache(Cache cache)
1174 *magick_restrict cache_info;
1176 assert(cache != (Cache) NULL);
1178 assert(cache_info->signature == MagickCoreSignature);
1179 if (IsEventLogging() != MagickFalse)
1180 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1181 cache_info->filename);
1182 LockSemaphoreInfo(cache_info->semaphore);
1183 cache_info->reference_count--;
1184 if (cache_info->reference_count != 0)
1186 UnlockSemaphoreInfo(cache_info->semaphore);
1187 return((Cache) NULL);
1189 UnlockSemaphoreInfo(cache_info->semaphore);
1190 if (cache_info->debug != MagickFalse)
1193 message[MaxTextExtent];
1195 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1196 cache_info->filename);
1197 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1199 RelinquishPixelCachePixels(cache_info);
1202 cache_info->server_info);
1203 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1204 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1205 cache_info->number_threads);
1206 if (cache_info->random_info != (
RandomInfo *) NULL)
1207 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1209 DestroySemaphoreInfo(&cache_info->file_semaphore);
1211 DestroySemaphoreInfo(&cache_info->semaphore);
1212 cache_info->signature=(~MagickCoreSignature);
1213 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1244 static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1246 if (nexus_info->mapped == MagickFalse)
1247 (void) RelinquishAlignedMemory(nexus_info->cache);
1249 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1252 nexus_info->indexes=(IndexPacket *) NULL;
1253 nexus_info->length=0;
1254 nexus_info->mapped=MagickFalse;
1258 const size_t number_threads)
1263 assert(nexus_info != (
NexusInfo **) NULL);
1264 for (i=0; i < (ssize_t) (2*number_threads); i++)
1267 RelinquishCacheNexusPixels(nexus_info[i]);
1268 nexus_info[i]->signature=(~MagickCoreSignature);
1270 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1271 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1298 static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1301 *magick_restrict cache_info;
1304 id = GetOpenMPThreadId();
1306 assert(image != (
const Image *) NULL);
1307 assert(image->signature == MagickCoreSignature);
1308 assert(image->cache != (Cache) NULL);
1310 assert(cache_info->signature == MagickCoreSignature);
1311 assert(
id < (
int) cache_info->number_threads);
1312 return(cache_info->nexus_info[
id]->indexes);
1340 MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1343 *magick_restrict cache_info;
1346 id = GetOpenMPThreadId();
1348 assert(image != (
const Image *) NULL);
1349 assert(image->signature == MagickCoreSignature);
1350 assert(image->cache != (Cache) NULL);
1352 assert(cache_info->signature == MagickCoreSignature);
1353 if (cache_info->methods.get_authentic_indexes_from_handler !=
1354 (GetAuthenticIndexesFromHandler) NULL)
1355 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1356 assert(
id < (
int) cache_info->number_threads);
1357 return(cache_info->nexus_info[
id]->indexes);
1360 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1384 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1388 *magick_restrict cache_info;
1399 assert(image != (
const Image *) NULL);
1401 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1403 SyncImagePixelCache((
Image *) image,exception);
1406 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1407 return((cl_mem) NULL);
1408 LockSemaphoreInfo(cache_info->semaphore);
1409 clEnv=GetDefaultOpenCLEnv();
1412 assert(cache_info->pixels != NULL);
1413 context=GetOpenCLContext(clEnv);
1415 sizeof(*cache_info->opencl));
1416 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1417 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1418 cache_info->opencl->length=cache_info->length;
1419 cache_info->opencl->pixels=cache_info->pixels;
1420 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1421 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1422 if (status != CL_SUCCESS)
1423 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1426 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1427 UnlockSemaphoreInfo(cache_info->semaphore);
1429 return((cl_mem) NULL);
1430 return(cache_info->opencl->buffer);
1470 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1474 *magick_restrict cache_info;
1477 *magick_restrict pixels;
1482 assert(image != (
Image *) NULL);
1483 assert(image->signature == MagickCoreSignature);
1484 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1485 nexus_info,exception);
1489 assert(cache_info->signature == MagickCoreSignature);
1490 if (nexus_info->authentic_pixel_cache != MagickFalse)
1492 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1494 if (cache_info->active_index_channel != MagickFalse)
1495 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1526 *magick_restrict cache_info;
1529 id = GetOpenMPThreadId();
1531 assert(image != (
const Image *) NULL);
1532 assert(image->signature == MagickCoreSignature);
1533 assert(image->cache != (Cache) NULL);
1535 assert(cache_info->signature == MagickCoreSignature);
1536 assert(
id < (
int) cache_info->number_threads);
1537 return(cache_info->nexus_info[
id]->pixels);
1566 *magick_restrict cache_info;
1569 id = GetOpenMPThreadId();
1571 assert(image != (
const Image *) NULL);
1572 assert(image->signature == MagickCoreSignature);
1573 assert(image->cache != (Cache) NULL);
1575 assert(cache_info->signature == MagickCoreSignature);
1576 if (cache_info->methods.get_authentic_pixels_from_handler !=
1577 (GetAuthenticPixelsFromHandler) NULL)
1578 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1579 assert(
id < (
int) cache_info->number_threads);
1580 return(cache_info->nexus_info[
id]->pixels);
1630 const ssize_t y,
const size_t columns,
const size_t rows,
1634 *magick_restrict cache_info;
1637 id = GetOpenMPThreadId();
1639 assert(image != (
Image *) NULL);
1640 assert(image->signature == MagickCoreSignature);
1641 assert(image->cache != (Cache) NULL);
1643 assert(cache_info->signature == MagickCoreSignature);
1644 if (cache_info->methods.get_authentic_pixels_handler !=
1645 (GetAuthenticPixelsHandler) NULL)
1646 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1648 assert(
id < (
int) cache_info->number_threads);
1649 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1650 cache_info->nexus_info[
id],exception));
1685 const ssize_t y,
const size_t columns,
const size_t rows,
1689 *magick_restrict cache_info;
1692 id = GetOpenMPThreadId();
1694 assert(image != (
const Image *) NULL);
1695 assert(image->signature == MagickCoreSignature);
1696 assert(image->cache != (Cache) NULL);
1698 if (cache_info == (Cache) NULL)
1700 assert(cache_info->signature == MagickCoreSignature);
1701 assert(
id < (
int) cache_info->number_threads);
1702 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1703 cache_info->nexus_info[
id],exception));
1729 MagickExport MagickSizeType GetImageExtent(
const Image *image)
1732 *magick_restrict cache_info;
1735 id = GetOpenMPThreadId();
1737 assert(image != (
Image *) NULL);
1738 assert(image->signature == MagickCoreSignature);
1739 if (IsEventLogging() != MagickFalse)
1740 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1741 assert(image->cache != (Cache) NULL);
1743 assert(cache_info->signature == MagickCoreSignature);
1744 assert(
id < (
int) cache_info->number_threads);
1745 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1748 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1776 extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1777 cl_uint *event_count)
1780 *magick_restrict cache_info;
1785 assert(image != (
const Image *) NULL);
1786 assert(event_count != (cl_uint *) NULL);
1789 events=(cl_event *) NULL;
1791 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1826 static inline MagickBooleanType ValidatePixelCacheMorphology(
1827 const Image *magick_restrict image)
1830 *magick_restrict cache_info;
1836 if ((image->storage_class != cache_info->storage_class) ||
1837 (image->colorspace != cache_info->colorspace) ||
1838 (image->channels != cache_info->channels) ||
1839 (image->columns != cache_info->columns) ||
1840 (image->rows != cache_info->rows) ||
1841 (cache_info->nexus_info == (
NexusInfo **) NULL))
1842 return(MagickFalse);
1846 static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1850 *magick_restrict cache_info;
1856 static MagickSizeType
1857 cache_timelimit = MagickResourceInfinity,
1858 cpu_throttle = MagickResourceInfinity,
1862 if (cpu_throttle == MagickResourceInfinity)
1863 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1864 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1865 MagickDelay(cpu_throttle);
1866 if (cache_epoch == 0)
1871 cache_epoch=GetMagickTime();
1872 cache_timelimit=GetMagickResourceLimit(TimeResource);
1874 if ((cache_timelimit != MagickResourceInfinity) &&
1875 ((MagickSizeType) (GetMagickTime()-cache_epoch) >= cache_timelimit))
1877 #if defined(ECANCELED)
1881 if (cache_info->file != -1)
1882 (void) ClosePixelCacheOnDisk(cache_info);
1883 (void) ThrowMagickException(exception,GetMagickModule(),
1884 ResourceLimitFatalError,
"TimeLimitExceeded",
"`%s'",image->filename);
1885 return((Cache) NULL);
1887 LockSemaphoreInfo(image->semaphore);
1888 assert(image->cache != (Cache) NULL);
1890 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1891 CopyOpenCLBuffer(cache_info);
1893 destroy=MagickFalse;
1894 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1896 LockSemaphoreInfo(cache_info->semaphore);
1897 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1908 clone_image=(*image);
1909 clone_image.semaphore=AllocateSemaphoreInfo();
1910 clone_image.reference_count=1;
1911 clone_image.cache=ClonePixelCache(cache_info);
1912 clone_info=(
CacheInfo *) clone_image.cache;
1913 status=OpenPixelCache(&clone_image,IOMode,exception);
1914 if (status == MagickFalse)
1915 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1918 if (clone != MagickFalse)
1919 status=ClonePixelCacheRepository(clone_info,cache_info,
1921 if (status == MagickFalse)
1922 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1926 image->cache=clone_info;
1929 DestroySemaphoreInfo(&clone_image.semaphore);
1931 UnlockSemaphoreInfo(cache_info->semaphore);
1933 if (destroy != MagickFalse)
1934 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1935 if (status != MagickFalse)
1940 if (image->type != UndefinedType)
1941 image->type=UndefinedType;
1942 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1944 status=OpenPixelCache(image,IOMode,exception);
1946 if (cache_info->file != -1)
1947 (void) ClosePixelCacheOnDisk(cache_info);
1950 UnlockSemaphoreInfo(image->semaphore);
1951 if (status == MagickFalse)
1952 return((Cache) NULL);
1953 return(image->cache);
1980 MagickExport CacheType GetPixelCacheType(
const Image *image)
1982 return(GetImagePixelCacheType(image));
1985 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1988 *magick_restrict cache_info;
1990 assert(image != (
Image *) NULL);
1991 assert(image->signature == MagickCoreSignature);
1992 assert(image->cache != (Cache) NULL);
1994 assert(cache_info->signature == MagickCoreSignature);
1995 return(cache_info->type);
2028 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2032 *magick_restrict cache_info;
2035 *magick_restrict pixels;
2037 assert(image != (
Image *) NULL);
2038 assert(image->signature == MagickCoreSignature);
2039 assert(image->cache != (Cache) NULL);
2041 assert(cache_info->signature == MagickCoreSignature);
2042 *pixel=image->background_color;
2043 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2044 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2045 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2047 return(MagickFalse);
2083 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2087 *magick_restrict cache_info;
2090 id = GetOpenMPThreadId();
2093 *magick_restrict pixels;
2095 assert(image != (
const Image *) NULL);
2096 assert(image->signature == MagickCoreSignature);
2097 assert(image->cache != (Cache) NULL);
2099 assert(cache_info->signature == MagickCoreSignature);
2100 *pixel=image->background_color;
2101 assert(
id < (
int) cache_info->number_threads);
2102 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2103 cache_info->nexus_info[
id],exception);
2105 return(MagickFalse);
2142 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2147 *magick_restrict cache_info;
2150 id = GetOpenMPThreadId();
2153 *magick_restrict indexes;
2156 *magick_restrict pixels;
2158 assert(image != (
const Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(image->cache != (Cache) NULL);
2162 assert(cache_info->signature == MagickCoreSignature);
2163 assert(
id < (
int) cache_info->number_threads);
2164 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2165 1UL,1UL,cache_info->nexus_info[
id],exception);
2166 GetMagickPixelPacket(image,pixel);
2168 return(MagickFalse);
2169 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2170 SetMagickPixelPacket(image,pixels,indexes,pixel);
2209 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2210 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2214 *magick_restrict cache_info;
2217 id = GetOpenMPThreadId();
2220 *magick_restrict pixels;
2222 assert(image != (
const Image *) NULL);
2223 assert(image->signature == MagickCoreSignature);
2224 assert(image->cache != (Cache) NULL);
2226 assert(cache_info->signature == MagickCoreSignature);
2227 *pixel=image->background_color;
2228 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2229 (GetOneVirtualPixelFromHandler) NULL)
2230 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2231 virtual_pixel_method,x,y,pixel,exception));
2232 assert(
id < (
int) cache_info->number_threads);
2233 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2234 cache_info->nexus_info[
id],exception);
2236 return(MagickFalse);
2272 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2276 *magick_restrict cache_info;
2279 id = GetOpenMPThreadId();
2282 *magick_restrict pixels;
2284 assert(image != (
const Image *) NULL);
2285 assert(image->signature == MagickCoreSignature);
2286 assert(image->cache != (Cache) NULL);
2288 assert(cache_info->signature == MagickCoreSignature);
2289 *pixel=image->background_color;
2290 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2291 (GetOneVirtualPixelFromHandler) NULL)
2292 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2293 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2294 assert(
id < (
int) cache_info->number_threads);
2295 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2296 1UL,1UL,cache_info->nexus_info[
id],exception);
2298 return(MagickFalse);
2337 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2338 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2342 *magick_restrict cache_info;
2345 id = GetOpenMPThreadId();
2348 *magick_restrict pixels;
2350 assert(image != (
const Image *) NULL);
2351 assert(image->signature == MagickCoreSignature);
2352 assert(image->cache != (Cache) NULL);
2354 assert(cache_info->signature == MagickCoreSignature);
2355 assert(
id < (
int) cache_info->number_threads);
2356 *pixel=image->background_color;
2357 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2358 cache_info->nexus_info[
id],exception);
2360 return(MagickFalse);
2390 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2393 *magick_restrict cache_info;
2395 assert(cache != (Cache) NULL);
2397 assert(cache_info->signature == MagickCoreSignature);
2398 if (IsEventLogging() != MagickFalse)
2399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2400 cache_info->filename);
2401 return(cache_info->channels);
2426 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2429 *magick_restrict cache_info;
2431 assert(cache != (Cache) NULL);
2433 assert(cache_info->signature == MagickCoreSignature);
2434 if (IsEventLogging() != MagickFalse)
2435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2436 cache_info->filename);
2437 return(cache_info->colorspace);
2463 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2466 *magick_restrict cache_info;
2468 assert(image != (
const Image *) NULL);
2469 assert(image->signature == MagickCoreSignature);
2470 assert(image->cache != (Cache) NULL);
2472 assert(cache_info->signature == MagickCoreSignature);
2473 return(cache_info->cache_filename);
2498 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2501 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2502 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2503 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2504 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2505 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2506 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2507 cache_methods->get_authentic_indexes_from_handler=
2508 GetAuthenticIndexesFromCache;
2509 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2510 cache_methods->get_one_authentic_pixel_from_handler=
2511 GetOneAuthenticPixelFromCache;
2512 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2513 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2514 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2541 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2545 *magick_restrict cache_info;
2550 assert(cache != NULL);
2552 assert(cache_info->signature == MagickCoreSignature);
2553 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2555 return((MagickSizeType) cache_info->columns*cache_info->rows);
2586 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2590 *magick_restrict cache_info;
2592 assert(image != (
const Image *) NULL);
2593 assert(image->signature == MagickCoreSignature);
2594 assert(image->cache != (Cache) NULL);
2595 assert(length != (MagickSizeType *) NULL);
2597 assert(exception->signature == MagickCoreSignature);
2599 assert(cache_info->signature == MagickCoreSignature);
2601 *length=cache_info->length;
2602 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2603 return((
void *) NULL);
2604 return((
void *) cache_info->pixels);
2631 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2634 *magick_restrict cache_info;
2636 assert(cache != (Cache) NULL);
2638 assert(cache_info->signature == MagickCoreSignature);
2639 if (IsEventLogging() != MagickFalse)
2640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2641 cache_info->filename);
2642 return(cache_info->storage_class);
2672 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2675 assert(image != (
Image *) NULL);
2676 assert(image->signature == MagickCoreSignature);
2677 if (IsEventLogging() != MagickFalse)
2678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2680 if (GetImagePixelCacheType(image) == DiskCache)
2709 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2712 *magick_restrict cache_info;
2714 assert(image != (
Image *) NULL);
2715 assert(image->signature == MagickCoreSignature);
2716 assert(image->cache != (Cache) NULL);
2718 assert(cache_info->signature == MagickCoreSignature);
2719 return(cache_info->virtual_pixel_method);
2745 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2748 *magick_restrict cache_info;
2751 id = GetOpenMPThreadId();
2753 assert(image != (
const Image *) NULL);
2754 assert(image->signature == MagickCoreSignature);
2755 assert(image->cache != (Cache) NULL);
2757 assert(cache_info->signature == MagickCoreSignature);
2758 assert(
id < (
int) cache_info->number_threads);
2759 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2788 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2792 *magick_restrict cache_info;
2794 assert(cache != (Cache) NULL);
2796 assert(cache_info->signature == MagickCoreSignature);
2797 if (cache_info->storage_class == UndefinedClass)
2798 return((IndexPacket *) NULL);
2799 return(nexus_info->indexes);
2827 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2830 *magick_restrict cache_info;
2833 id = GetOpenMPThreadId();
2835 assert(image != (
const Image *) NULL);
2836 assert(image->signature == MagickCoreSignature);
2837 assert(image->cache != (Cache) NULL);
2839 assert(cache_info->signature == MagickCoreSignature);
2840 if (cache_info->methods.get_virtual_indexes_from_handler !=
2841 (GetVirtualIndexesFromHandler) NULL)
2842 return(cache_info->methods.get_virtual_indexes_from_handler(image));
2843 assert(
id < (
int) cache_info->number_threads);
2844 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2887 0, 48, 12, 60, 3, 51, 15, 63,
2888 32, 16, 44, 28, 35, 19, 47, 31,
2889 8, 56, 4, 52, 11, 59, 7, 55,
2890 40, 24, 36, 20, 43, 27, 39, 23,
2891 2, 50, 14, 62, 1, 49, 13, 61,
2892 34, 18, 46, 30, 33, 17, 45, 29,
2893 10, 58, 6, 54, 9, 57, 5, 53,
2894 42, 26, 38, 22, 41, 25, 37, 21
2897 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2902 index=x+DitherMatrix[x & 0x07]-32L;
2905 if (index >= (ssize_t) columns)
2906 return((ssize_t) columns-1L);
2910 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2915 index=y+DitherMatrix[y & 0x07]-32L;
2918 if (index >= (ssize_t) rows)
2919 return((ssize_t) rows-1L);
2923 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2927 if (x >= (ssize_t) columns)
2928 return((ssize_t) (columns-1));
2932 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2936 if (y >= (ssize_t) rows)
2937 return((ssize_t) (rows-1));
2941 static inline MagickBooleanType IsValidOffset(
const ssize_t y,
2942 const size_t columns)
2946 if (y >= (MAGICK_SSIZE_MAX/(ssize_t) columns))
2947 return(MagickFalse);
2948 if (y <= (MAGICK_SSIZE_MIN/(ssize_t) columns))
2949 return(MagickFalse);
2953 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2955 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2958 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2960 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2963 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2964 const size_t extent)
2969 modulo.quotient=offset;
2973 modulo.quotient=offset/((ssize_t) extent);
2974 modulo.remainder=offset % ((ssize_t) extent);
2976 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2979 modulo.remainder+=((ssize_t) extent);
2984 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2985 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2986 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2990 *magick_restrict cache_info;
2993 *magick_restrict virtual_indexes;
3000 *magick_restrict indexes;
3010 *magick_restrict virtual_nexus;
3013 *magick_restrict pixels,
3024 assert(image != (
const Image *) NULL);
3025 assert(image->signature == MagickCoreSignature);
3026 assert(image->cache != (Cache) NULL);
3028 assert(cache_info->signature == MagickCoreSignature);
3029 if (cache_info->type == UndefinedCache)
3031 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3032 CopyOpenCLBuffer(cache_info);
3034 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3035 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3036 MagickTrue : MagickFalse,nexus_info,exception);
3039 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3041 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
3042 nexus_info->region.x;
3043 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3044 nexus_info->region.width-1L;
3045 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3046 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3047 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3048 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3056 if (nexus_info->authentic_pixel_cache != MagickFalse)
3058 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3059 if (status == MagickFalse)
3061 if ((cache_info->storage_class == PseudoClass) ||
3062 (cache_info->colorspace == CMYKColorspace))
3064 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3065 if (status == MagickFalse)
3073 virtual_nexus=nexus_info->virtual_nexus;
3075 indexes=nexus_info->indexes;
3076 switch (virtual_pixel_method)
3078 case BlackVirtualPixelMethod:
3080 SetPixelRed(&virtual_pixel,0);
3081 SetPixelGreen(&virtual_pixel,0);
3082 SetPixelBlue(&virtual_pixel,0);
3083 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3086 case GrayVirtualPixelMethod:
3088 SetPixelRed(&virtual_pixel,QuantumRange/2);
3089 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3090 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3091 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3094 case TransparentVirtualPixelMethod:
3096 SetPixelRed(&virtual_pixel,0);
3097 SetPixelGreen(&virtual_pixel,0);
3098 SetPixelBlue(&virtual_pixel,0);
3099 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3102 case MaskVirtualPixelMethod:
3103 case WhiteVirtualPixelMethod:
3105 SetPixelRed(&virtual_pixel,QuantumRange);
3106 SetPixelGreen(&virtual_pixel,QuantumRange);
3107 SetPixelBlue(&virtual_pixel,QuantumRange);
3108 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3113 virtual_pixel=image->background_color;
3117 virtual_index=(IndexPacket) 0;
3118 for (v=0; v < (ssize_t) rows; v++)
3124 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3125 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3126 y_offset=EdgeY(y_offset,cache_info->rows);
3127 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3133 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3134 (ssize_t) columns-u);
3135 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3136 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3146 length=(MagickSizeType) 1;
3147 switch (virtual_pixel_method)
3149 case BackgroundVirtualPixelMethod:
3150 case ConstantVirtualPixelMethod:
3151 case BlackVirtualPixelMethod:
3152 case GrayVirtualPixelMethod:
3153 case TransparentVirtualPixelMethod:
3154 case MaskVirtualPixelMethod:
3155 case WhiteVirtualPixelMethod:
3158 virtual_indexes=(&virtual_index);
3161 case EdgeVirtualPixelMethod:
3164 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3165 EdgeX(x_offset,cache_info->columns),
3166 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3168 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3172 case RandomVirtualPixelMethod:
3174 if (cache_info->random_info == (
RandomInfo *) NULL)
3175 cache_info->random_info=AcquireRandomInfo();
3176 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3177 RandomX(cache_info->random_info,cache_info->columns),
3178 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3179 virtual_nexus,exception);
3180 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3184 case DitherVirtualPixelMethod:
3186 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3187 DitherX(x_offset,cache_info->columns),
3188 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3190 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3194 case TileVirtualPixelMethod:
3196 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3197 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3198 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3199 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3201 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3205 case MirrorVirtualPixelMethod:
3207 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3208 if ((x_modulo.quotient & 0x01) == 1L)
3209 x_modulo.remainder=(ssize_t) cache_info->columns-
3210 x_modulo.remainder-1L;
3211 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3212 if ((y_modulo.quotient & 0x01) == 1L)
3213 y_modulo.remainder=(ssize_t) cache_info->rows-
3214 y_modulo.remainder-1L;
3215 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3216 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3218 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3222 case CheckerTileVirtualPixelMethod:
3224 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3225 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3226 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3229 virtual_indexes=(&virtual_index);
3232 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3233 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3235 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3239 case HorizontalTileVirtualPixelMethod:
3241 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3244 virtual_indexes=(&virtual_index);
3247 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3248 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3249 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3250 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3252 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3256 case VerticalTileVirtualPixelMethod:
3258 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3261 virtual_indexes=(&virtual_index);
3264 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3265 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3266 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3267 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3269 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3273 case HorizontalTileEdgeVirtualPixelMethod:
3275 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3276 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3277 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3278 virtual_nexus,exception);
3279 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3283 case VerticalTileEdgeVirtualPixelMethod:
3285 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3286 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3287 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3288 virtual_nexus,exception);
3289 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3297 if ((indexes != (IndexPacket *) NULL) &&
3298 (virtual_indexes != (
const IndexPacket *) NULL))
3299 *indexes++=(*virtual_indexes);
3305 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3306 (
size_t) length,1UL,virtual_nexus,exception);
3309 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3310 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3312 if ((indexes != (IndexPacket *) NULL) &&
3313 (virtual_indexes != (
const IndexPacket *) NULL))
3315 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3316 sizeof(*virtual_indexes));
3320 if (u < (ssize_t) columns)
3326 if (v < (ssize_t) rows)
3366 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3367 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3370 *magick_restrict cache_info;
3373 id = GetOpenMPThreadId();
3375 assert(image != (
const Image *) NULL);
3376 assert(image->signature == MagickCoreSignature);
3377 assert(image->cache != (Cache) NULL);
3379 assert(cache_info->signature == MagickCoreSignature);
3380 assert(
id < (
int) cache_info->number_threads);
3381 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3382 cache_info->nexus_info[
id],exception));
3411 *magick_restrict cache_info;
3414 id = GetOpenMPThreadId();
3416 assert(image != (
const Image *) NULL);
3417 assert(image->signature == MagickCoreSignature);
3418 assert(image->cache != (Cache) NULL);
3420 assert(cache_info->signature == MagickCoreSignature);
3421 if (cache_info->methods.get_virtual_pixels_handler !=
3422 (GetVirtualPixelsHandler) NULL)
3423 return(cache_info->methods.get_virtual_pixels_handler(image));
3424 assert(
id < (
int) cache_info->number_threads);
3425 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3477 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3481 *magick_restrict cache_info;
3484 id = GetOpenMPThreadId();
3486 assert(image != (
const Image *) NULL);
3487 assert(image->signature == MagickCoreSignature);
3488 assert(image->cache != (Cache) NULL);
3490 assert(cache_info->signature == MagickCoreSignature);
3491 if (cache_info->methods.get_virtual_pixel_handler !=
3492 (GetVirtualPixelHandler) NULL)
3493 return(cache_info->methods.get_virtual_pixel_handler(image,
3494 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3495 assert(
id < (
int) cache_info->number_threads);
3496 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3497 columns,rows,cache_info->nexus_info[
id],exception));
3526 *magick_restrict cache_info;
3529 id = GetOpenMPThreadId();
3531 assert(image != (
const Image *) NULL);
3532 assert(image->signature == MagickCoreSignature);
3533 assert(image->cache != (Cache) NULL);
3535 assert(cache_info->signature == MagickCoreSignature);
3536 assert(
id < (
int) cache_info->number_threads);
3537 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3566 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3570 *magick_restrict cache_info;
3572 assert(cache != (Cache) NULL);
3574 assert(cache_info->signature == MagickCoreSignature);
3575 if (cache_info->storage_class == UndefinedClass)
3617 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3622 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3623 gamma=PerceptibleReciprocal(gamma);
3624 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3625 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3626 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3627 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3628 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3631 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3635 *magick_restrict cache_info;
3641 *magick_restrict nexus_indexes,
3642 *magick_restrict indexes;
3652 **magick_restrict mask_nexus;
3664 if (IsEventLogging() != MagickFalse)
3665 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3666 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3668 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3671 if (cache_info == (Cache) NULL)
3672 return(MagickFalse);
3673 mask_nexus=AcquirePixelCacheNexus(1);
3674 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3675 nexus_info->virtual_nexus,exception);
3676 indexes=nexus_info->virtual_nexus->indexes;
3677 q=nexus_info->pixels;
3678 nexus_indexes=nexus_info->indexes;
3679 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3680 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3681 nexus_info->region.height,mask_nexus[0],&image->exception);
3684 return(MagickFalse);
3686 GetMagickPixelPacket(image,&alpha);
3687 GetMagickPixelPacket(image,&beta);
3688 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3693 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3695 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3696 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3697 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3698 alpha.opacity,&beta);
3699 SetPixelRed(q,ClampToQuantum(beta.red));
3700 SetPixelGreen(q,ClampToQuantum(beta.green));
3701 SetPixelBlue(q,ClampToQuantum(beta.blue));
3702 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3703 if (cache_info->active_index_channel != MagickFalse)
3704 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3711 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3746 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3755 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3757 if (*cache_info->cache_filename ==
'\0')
3758 file=AcquireUniqueFileResource(cache_info->cache_filename);
3764 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3769 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3770 O_BINARY | O_EXCL,S_MODE);
3772 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3778 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3781 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3786 return(MagickFalse);
3787 (void) AcquireMagickResource(FileResource,1);
3788 if (cache_info->file != -1)
3789 (void) ClosePixelCacheOnDisk(cache_info);
3790 cache_info->file=file;
3791 cache_info->disk_mode=mode;
3795 static inline MagickOffsetType WritePixelCacheRegion(
3796 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3797 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3805 #if !defined(MAGICKCORE_HAVE_PWRITE)
3806 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3807 return((MagickOffsetType) -1);
3809 for (i=0; i < (MagickOffsetType) length; i+=count)
3811 #if !defined(MAGICKCORE_HAVE_PWRITE)
3812 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3813 (MagickSizeType) i,MAGICK_SSIZE_MAX));
3815 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3816 (MagickSizeType) i,MAGICK_SSIZE_MAX),offset+i);
3828 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3831 *magick_restrict cache_info;
3837 if (cache_info->debug != MagickFalse)
3840 format[MaxTextExtent],
3841 message[MaxTextExtent];
3843 (void) FormatMagickSize(length,MagickFalse,format);
3844 (void) FormatLocaleString(message,MaxTextExtent,
3845 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3846 cache_info->cache_filename,cache_info->file,format);
3847 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3849 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3851 return(MagickFalse);
3852 if ((MagickSizeType) offset < length)
3858 extent=(MagickOffsetType) length-1;
3859 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3862 return(MagickFalse);
3863 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3864 if (cache_info->synchronize != MagickFalse)
3865 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3866 return(MagickFalse);
3869 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3871 return(MagickFalse);
3875 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3879 *magick_restrict cache_info,
3883 format[MaxTextExtent],
3884 message[MaxTextExtent];
3901 assert(image != (
const Image *) NULL);
3902 assert(image->signature == MagickCoreSignature);
3903 assert(image->cache != (Cache) NULL);
3904 if (IsEventLogging() != MagickFalse)
3905 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3906 if (cache_anonymous_memory < 0)
3914 cache_anonymous_memory=0;
3915 value=GetPolicyValue(
"pixel-cache-memory");
3916 if (value == (
char *) NULL)
3917 value=GetPolicyValue(
"cache:memory-map");
3918 if (LocaleCompare(value,
"anonymous") == 0)
3920 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3921 cache_anonymous_memory=1;
3923 (void) ThrowMagickException(exception,GetMagickModule(),
3924 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3925 "'%s' (policy requires anonymous memory mapping)",image->filename);
3928 value=DestroyString(value);
3930 if ((image->columns == 0) || (image->rows == 0))
3931 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3933 assert(cache_info->signature == MagickCoreSignature);
3934 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3935 ((MagickSizeType) image->rows > cache_info->height_limit))
3936 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3938 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3940 length=GetImageListLength(image);
3941 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3942 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3945 source_info=(*cache_info);
3946 source_info.file=(-1);
3947 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3948 image->filename,(
double) image->scene);
3949 cache_info->storage_class=image->storage_class;
3950 cache_info->colorspace=image->colorspace;
3951 cache_info->rows=image->rows;
3952 cache_info->columns=image->columns;
3953 cache_info->channels=image->channels;
3954 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3955 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3956 cache_info->mode=mode;
3957 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3959 if (cache_info->active_index_channel != MagickFalse)
3960 packet_size+=
sizeof(IndexPacket);
3961 length=number_pixels*packet_size;
3962 columns=(size_t) (length/cache_info->rows/packet_size);
3963 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3964 ((ssize_t) cache_info->rows < 0))
3965 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3967 cache_info->length=length;
3968 if (image->ping != MagickFalse)
3970 cache_info->type=PingCache;
3973 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3974 cache_info->columns*cache_info->rows);
3975 if (cache_info->mode == PersistMode)
3977 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3978 if ((status != MagickFalse) &&
3979 (length == (MagickSizeType) ((
size_t) length)) &&
3980 ((cache_info->type == UndefinedCache) ||
3981 (cache_info->type == MemoryCache)))
3983 status=AcquireMagickResource(MemoryResource,cache_info->length);
3984 if (status != MagickFalse)
3987 if (cache_anonymous_memory <= 0)
3989 cache_info->mapped=MagickFalse;
3990 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3991 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3995 cache_info->mapped=MagickTrue;
3996 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3997 cache_info->length);
4001 cache_info->mapped=source_info.mapped;
4002 cache_info->pixels=source_info.pixels;
4009 cache_info->colorspace=image->colorspace;
4010 cache_info->type=MemoryCache;
4011 cache_info->indexes=(IndexPacket *) NULL;
4012 if (cache_info->active_index_channel != MagickFalse)
4013 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4015 if ((source_info.storage_class != UndefinedClass) &&
4018 status&=ClonePixelCacheRepository(cache_info,&source_info,
4020 RelinquishPixelCachePixels(&source_info);
4022 if (cache_info->debug != MagickFalse)
4024 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4025 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4027 (void) FormatLocaleString(message,MaxTextExtent,
4028 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4029 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4030 type,(
double) cache_info->columns,(double) cache_info->rows,
4032 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4035 cache_info->storage_class=image->storage_class;
4038 cache_info->type=UndefinedCache;
4039 return(MagickFalse);
4045 status=AcquireMagickResource(DiskResource,cache_info->length);
4046 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4048 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4056 server_info=AcquireDistributeCacheInfo(exception);
4059 status=OpenDistributePixelCache(server_info,image);
4060 if (status == MagickFalse)
4062 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4063 GetDistributeCacheHostname(server_info));
4064 server_info=DestroyDistributeCacheInfo(server_info);
4072 cache_info->type=DistributedCache;
4073 cache_info->storage_class=image->storage_class;
4074 cache_info->colorspace=image->colorspace;
4075 cache_info->server_info=server_info;
4076 (void) FormatLocaleString(cache_info->cache_filename,
4077 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4080 cache_info->server_info));
4081 if ((source_info.storage_class != UndefinedClass) &&
4084 status=ClonePixelCacheRepository(cache_info,&source_info,
4086 RelinquishPixelCachePixels(&source_info);
4088 if (cache_info->debug != MagickFalse)
4090 (void) FormatMagickSize(cache_info->length,MagickFalse,
4092 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4094 (void) FormatLocaleString(message,MaxTextExtent,
4095 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4096 cache_info->cache_filename,GetDistributeCacheFile(
4098 (double) cache_info->columns,(
double) cache_info->rows,
4100 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4105 cache_info->type=UndefinedCache;
4106 return(MagickFalse);
4111 cache_info->type=UndefinedCache;
4112 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4113 "CacheResourcesExhausted",
"`%s'",image->filename);
4114 return(MagickFalse);
4119 if (status == MagickFalse)
4121 cache_info->type=UndefinedCache;
4122 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4123 "CacheResourcesExhausted",
"`%s'",image->filename);
4124 return(MagickFalse);
4126 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4127 (cache_info->mode != PersistMode))
4129 (void) ClosePixelCacheOnDisk(cache_info);
4130 *cache_info->cache_filename=
'\0';
4132 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4134 cache_info->type=UndefinedCache;
4135 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4137 return(MagickFalse);
4139 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4140 cache_info->length);
4141 if (status == MagickFalse)
4143 cache_info->type=UndefinedCache;
4144 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4146 return(MagickFalse);
4148 cache_info->storage_class=image->storage_class;
4149 cache_info->colorspace=image->colorspace;
4150 cache_info->type=DiskCache;
4151 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4152 if (length == (MagickSizeType) ((size_t) length))
4154 status=AcquireMagickResource(MapResource,cache_info->length);
4155 if (status != MagickFalse)
4157 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4158 cache_info->offset,(
size_t) cache_info->length);
4161 cache_info->mapped=source_info.mapped;
4162 cache_info->pixels=source_info.pixels;
4163 RelinquishMagickResource(MapResource,cache_info->length);
4170 (void) ClosePixelCacheOnDisk(cache_info);
4171 cache_info->type=MapCache;
4172 cache_info->mapped=MagickTrue;
4173 cache_info->indexes=(IndexPacket *) NULL;
4174 if (cache_info->active_index_channel != MagickFalse)
4175 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4177 if ((source_info.storage_class != UndefinedClass) &&
4180 status=ClonePixelCacheRepository(cache_info,&source_info,
4182 RelinquishPixelCachePixels(&source_info);
4184 if (cache_info->debug != MagickFalse)
4186 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4187 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4189 (void) FormatLocaleString(message,MaxTextExtent,
4190 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4191 cache_info->filename,cache_info->cache_filename,
4192 cache_info->file,type,(
double) cache_info->columns,
4193 (double) cache_info->rows,format);
4194 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4199 cache_info->type=UndefinedCache;
4200 return(MagickFalse);
4207 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4209 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4210 RelinquishPixelCachePixels(&source_info);
4212 if (cache_info->debug != MagickFalse)
4214 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4215 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4217 (void) FormatLocaleString(message,MaxTextExtent,
4218 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4219 cache_info->cache_filename,cache_info->file,type,(
double)
4220 cache_info->columns,(double) cache_info->rows,format);
4221 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4225 cache_info->type=UndefinedCache;
4226 return(MagickFalse);
4268 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4269 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4273 *magick_restrict cache_info,
4274 *magick_restrict clone_info;
4282 assert(image != (
Image *) NULL);
4283 assert(image->signature == MagickCoreSignature);
4284 if (IsEventLogging() != MagickFalse)
4285 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4286 assert(image->cache != (
void *) NULL);
4287 assert(filename != (
const char *) NULL);
4288 assert(offset != (MagickOffsetType *) NULL);
4289 page_size=GetMagickPageSize();
4291 assert(cache_info->signature == MagickCoreSignature);
4292 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4293 CopyOpenCLBuffer(cache_info);
4295 if (attach != MagickFalse)
4300 if (cache_info->debug != MagickFalse)
4301 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4302 "attach persistent cache");
4303 (void) CopyMagickString(cache_info->cache_filename,filename,
4305 cache_info->type=MapCache;
4306 cache_info->offset=(*offset);
4307 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4308 return(MagickFalse);
4309 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4310 ((MagickOffsetType) cache_info->length % page_size));
4316 status=AcquireMagickResource(DiskResource,cache_info->length);
4317 if (status == MagickFalse)
4319 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4320 "CacheResourcesExhausted",
"`%s'",image->filename);
4321 return(MagickFalse);
4323 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4324 clone_info->type=DiskCache;
4325 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4326 clone_info->file=(-1);
4327 clone_info->storage_class=cache_info->storage_class;
4328 clone_info->colorspace=cache_info->colorspace;
4329 clone_info->columns=cache_info->columns;
4330 clone_info->rows=cache_info->rows;
4331 clone_info->active_index_channel=cache_info->active_index_channel;
4332 clone_info->mode=PersistMode;
4333 clone_info->length=cache_info->length;
4334 clone_info->channels=cache_info->channels;
4335 clone_info->offset=(*offset);
4336 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4337 if (status != MagickFalse)
4338 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4339 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4340 ((MagickOffsetType) cache_info->length % page_size));
4341 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4383 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4384 const ssize_t y,
const size_t columns,
const size_t rows,
4385 const MagickBooleanType clone,
NexusInfo *nexus_info,
4388 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4393 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4397 *magick_restrict cache_info;
4406 *magick_restrict pixels;
4411 assert(image != (
const Image *) NULL);
4412 assert(image->signature == MagickCoreSignature);
4413 assert(image->cache != (Cache) NULL);
4414 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4415 if (cache_info == (Cache) NULL)
4417 assert(cache_info->signature == MagickCoreSignature);
4418 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4419 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4420 (y >= (ssize_t) cache_info->rows))
4422 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4423 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4426 if (IsValidOffset(y,cache_info->columns) == MagickFalse)
4428 offset=y*(MagickOffsetType) cache_info->columns+x;
4431 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4432 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4433 (MagickOffsetType) columns-1;
4434 if ((MagickSizeType) offset >= number_pixels)
4439 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4440 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4441 MagickTrue : MagickFalse,nexus_info,exception);
4478 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4479 const ssize_t y,
const size_t columns,
const size_t rows,
4483 *magick_restrict cache_info;
4486 id = GetOpenMPThreadId();
4488 assert(image != (
const Image *) NULL);
4489 assert(image->signature == MagickCoreSignature);
4490 assert(image->cache != (Cache) NULL);
4492 assert(cache_info->signature == MagickCoreSignature);
4493 assert(
id < (
int) cache_info->number_threads);
4494 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4495 cache_info->nexus_info[
id],exception));
4554 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4555 const ssize_t y,
const size_t columns,
const size_t rows,
4559 *magick_restrict cache_info;
4562 id = GetOpenMPThreadId();
4564 assert(image != (
Image *) NULL);
4565 assert(image->signature == MagickCoreSignature);
4566 assert(image->cache != (Cache) NULL);
4568 assert(cache_info->signature == MagickCoreSignature);
4569 if (cache_info->methods.queue_authentic_pixels_handler !=
4570 (QueueAuthenticPixelsHandler) NULL)
4571 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4573 assert(
id < (
int) cache_info->number_threads);
4574 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4575 cache_info->nexus_info[
id],exception));
4607 static inline MagickOffsetType ReadPixelCacheRegion(
4608 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4609 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4617 #if !defined(MAGICKCORE_HAVE_PREAD)
4618 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4619 return((MagickOffsetType) -1);
4621 for (i=0; i < (MagickOffsetType) length; i+=count)
4623 #if !defined(MAGICKCORE_HAVE_PREAD)
4624 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4625 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX));
4627 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4628 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX),offset+i);
4640 static MagickBooleanType ReadPixelCacheIndexes(
4661 if (cache_info->active_index_channel == MagickFalse)
4662 return(MagickFalse);
4663 if (nexus_info->authentic_pixel_cache != MagickFalse)
4665 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4666 return(MagickFalse);
4667 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4668 nexus_info->region.x;
4669 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4670 rows=nexus_info->region.height;
4672 q=nexus_info->indexes;
4674 switch (cache_info->type)
4685 if ((cache_info->columns == nexus_info->region.width) &&
4686 (extent == (MagickSizeType) ((
size_t) extent)))
4691 p=cache_info->indexes+offset;
4692 for (y=0; y < (ssize_t) rows; y++)
4694 (void) memcpy(q,p,(
size_t) length);
4695 p+=cache_info->columns;
4696 q+=nexus_info->region.width;
4705 LockSemaphoreInfo(cache_info->file_semaphore);
4706 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4708 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4709 cache_info->cache_filename);
4710 UnlockSemaphoreInfo(cache_info->file_semaphore);
4711 return(MagickFalse);
4713 if ((cache_info->columns == nexus_info->region.width) &&
4714 (extent <= MagickMaxBufferExtent))
4719 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4720 for (y=0; y < (ssize_t) rows; y++)
4722 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4723 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4724 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4725 if (count < (MagickOffsetType) length)
4727 offset+=(MagickOffsetType) cache_info->columns;
4728 q+=nexus_info->region.width;
4730 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4731 (
void) ClosePixelCacheOnDisk(cache_info);
4732 UnlockSemaphoreInfo(cache_info->file_semaphore);
4735 case DistributedCache:
4743 LockSemaphoreInfo(cache_info->file_semaphore);
4744 region=nexus_info->region;
4745 if ((cache_info->columns != nexus_info->region.width) ||
4746 (extent > MagickMaxBufferExtent))
4753 for (y=0; y < (ssize_t) rows; y++)
4756 cache_info->server_info,®ion,length,(
unsigned char *) q);
4757 if (count != (MagickOffsetType) length)
4759 q+=nexus_info->region.width;
4762 UnlockSemaphoreInfo(cache_info->file_semaphore);
4768 if (y < (ssize_t) rows)
4770 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4771 cache_info->cache_filename);
4772 return(MagickFalse);
4774 if ((cache_info->debug != MagickFalse) &&
4775 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4776 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4777 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4778 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4779 nexus_info->region.x,(
double) nexus_info->region.y);
4811 static MagickBooleanType ReadPixelCachePixels(
4832 if (nexus_info->authentic_pixel_cache != MagickFalse)
4834 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4835 return(MagickFalse);
4836 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4837 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4838 return(MagickFalse);
4839 offset+=nexus_info->region.x;
4840 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4841 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4842 return(MagickFalse);
4843 rows=nexus_info->region.height;
4845 if ((extent == 0) || ((extent/length) != rows))
4846 return(MagickFalse);
4847 q=nexus_info->pixels;
4849 switch (cache_info->type)
4860 if ((cache_info->columns == nexus_info->region.width) &&
4861 (extent == (MagickSizeType) ((
size_t) extent)))
4866 p=cache_info->pixels+offset;
4867 for (y=0; y < (ssize_t) rows; y++)
4869 (void) memcpy(q,p,(
size_t) length);
4870 p+=cache_info->columns;
4871 q+=nexus_info->region.width;
4880 LockSemaphoreInfo(cache_info->file_semaphore);
4881 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4883 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4884 cache_info->cache_filename);
4885 UnlockSemaphoreInfo(cache_info->file_semaphore);
4886 return(MagickFalse);
4888 if ((cache_info->columns == nexus_info->region.width) &&
4889 (extent <= MagickMaxBufferExtent))
4894 for (y=0; y < (ssize_t) rows; y++)
4896 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4897 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4898 if (count < (MagickOffsetType) length)
4900 offset+=(MagickOffsetType) cache_info->columns;
4901 q+=nexus_info->region.width;
4903 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4904 (
void) ClosePixelCacheOnDisk(cache_info);
4905 UnlockSemaphoreInfo(cache_info->file_semaphore);
4908 case DistributedCache:
4916 LockSemaphoreInfo(cache_info->file_semaphore);
4917 region=nexus_info->region;
4918 if ((cache_info->columns != nexus_info->region.width) ||
4919 (extent > MagickMaxBufferExtent))
4926 for (y=0; y < (ssize_t) rows; y++)
4929 cache_info->server_info,®ion,length,(
unsigned char *) q);
4930 if (count != (MagickOffsetType) length)
4932 q+=nexus_info->region.width;
4935 UnlockSemaphoreInfo(cache_info->file_semaphore);
4941 if (y < (ssize_t) rows)
4943 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4944 cache_info->cache_filename);
4945 return(MagickFalse);
4947 if ((cache_info->debug != MagickFalse) &&
4948 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4949 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4950 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4951 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4952 nexus_info->region.x,(
double) nexus_info->region.y);
4979 MagickExport Cache ReferencePixelCache(Cache cache)
4982 *magick_restrict cache_info;
4984 assert(cache != (Cache *) NULL);
4986 assert(cache_info->signature == MagickCoreSignature);
4987 LockSemaphoreInfo(cache_info->semaphore);
4988 cache_info->reference_count++;
4989 UnlockSemaphoreInfo(cache_info->semaphore);
5011 MagickPrivate
void ResetPixelCacheEpoch(
void)
5040 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5043 *magick_restrict cache_info;
5045 GetOneAuthenticPixelFromHandler
5046 get_one_authentic_pixel_from_handler;
5048 GetOneVirtualPixelFromHandler
5049 get_one_virtual_pixel_from_handler;
5054 assert(cache != (Cache) NULL);
5057 assert(cache_info->signature == MagickCoreSignature);
5058 if (IsEventLogging() != MagickFalse)
5059 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5060 cache_info->filename);
5061 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5062 cache_info->methods.get_virtual_pixel_handler=
5063 cache_methods->get_virtual_pixel_handler;
5064 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5065 cache_info->methods.destroy_pixel_handler=
5066 cache_methods->destroy_pixel_handler;
5067 if (cache_methods->get_virtual_indexes_from_handler !=
5068 (GetVirtualIndexesFromHandler) NULL)
5069 cache_info->methods.get_virtual_indexes_from_handler=
5070 cache_methods->get_virtual_indexes_from_handler;
5071 if (cache_methods->get_authentic_pixels_handler !=
5072 (GetAuthenticPixelsHandler) NULL)
5073 cache_info->methods.get_authentic_pixels_handler=
5074 cache_methods->get_authentic_pixels_handler;
5075 if (cache_methods->queue_authentic_pixels_handler !=
5076 (QueueAuthenticPixelsHandler) NULL)
5077 cache_info->methods.queue_authentic_pixels_handler=
5078 cache_methods->queue_authentic_pixels_handler;
5079 if (cache_methods->sync_authentic_pixels_handler !=
5080 (SyncAuthenticPixelsHandler) NULL)
5081 cache_info->methods.sync_authentic_pixels_handler=
5082 cache_methods->sync_authentic_pixels_handler;
5083 if (cache_methods->get_authentic_pixels_from_handler !=
5084 (GetAuthenticPixelsFromHandler) NULL)
5085 cache_info->methods.get_authentic_pixels_from_handler=
5086 cache_methods->get_authentic_pixels_from_handler;
5087 if (cache_methods->get_authentic_indexes_from_handler !=
5088 (GetAuthenticIndexesFromHandler) NULL)
5089 cache_info->methods.get_authentic_indexes_from_handler=
5090 cache_methods->get_authentic_indexes_from_handler;
5091 get_one_virtual_pixel_from_handler=
5092 cache_info->methods.get_one_virtual_pixel_from_handler;
5093 if (get_one_virtual_pixel_from_handler !=
5094 (GetOneVirtualPixelFromHandler) NULL)
5095 cache_info->methods.get_one_virtual_pixel_from_handler=
5096 cache_methods->get_one_virtual_pixel_from_handler;
5097 get_one_authentic_pixel_from_handler=
5098 cache_methods->get_one_authentic_pixel_from_handler;
5099 if (get_one_authentic_pixel_from_handler !=
5100 (GetOneAuthenticPixelFromHandler) NULL)
5101 cache_info->methods.get_one_authentic_pixel_from_handler=
5102 cache_methods->get_one_authentic_pixel_from_handler;
5143 static inline MagickBooleanType AcquireCacheNexusPixels(
5144 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5147 if (length != (MagickSizeType) ((
size_t) length))
5149 (void) ThrowMagickException(exception,GetMagickModule(),
5150 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5151 cache_info->filename);
5152 return(MagickFalse);
5154 nexus_info->length=0;
5155 nexus_info->mapped=MagickFalse;
5156 if (cache_anonymous_memory <= 0)
5158 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5159 AcquireAlignedMemory(1,(
size_t) length));
5161 (
void) memset(nexus_info->cache,0,(
size_t) length);
5165 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5167 nexus_info->mapped=MagickTrue;
5171 (void) ThrowMagickException(exception,GetMagickModule(),
5172 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5173 cache_info->filename);
5174 return(MagickFalse);
5176 nexus_info->length=length;
5180 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5183 if (nexus_info->length < CACHE_LINE_SIZE)
5185 if (mode == ReadMode)
5187 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5191 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5194 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5197 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5198 return(MagickFalse);
5199 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5200 return(MagickFalse);
5205 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5206 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5207 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5217 assert(cache_info != (
const CacheInfo *) NULL);
5218 assert(cache_info->signature == MagickCoreSignature);
5219 if (cache_info->type == UndefinedCache)
5221 assert(nexus_info->signature == MagickCoreSignature);
5222 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5223 if ((width == 0) || (height == 0))
5225 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5226 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5229 if (((MagickSizeType) width > cache_info->width_limit) ||
5230 ((MagickSizeType) height > cache_info->height_limit) ||
5231 (ValidatePixelOffset(x,width) == MagickFalse) ||
5232 (ValidatePixelOffset(y,height) == MagickFalse))
5234 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5235 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5238 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5239 (buffered == MagickFalse))
5241 if (((x >= 0) && (y >= 0) &&
5242 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5243 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5244 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5252 if (IsValidOffset(y,cache_info->columns) == MagickFalse)
5254 offset=y*(MagickOffsetType) cache_info->columns+x;
5255 nexus_info->pixels=cache_info->pixels+offset;
5256 nexus_info->indexes=(IndexPacket *) NULL;
5257 if (cache_info->active_index_channel != MagickFalse)
5258 nexus_info->indexes=cache_info->indexes+offset;
5259 nexus_info->region.width=width;
5260 nexus_info->region.height=height;
5261 nexus_info->region.x=x;
5262 nexus_info->region.y=y;
5263 nexus_info->authentic_pixel_cache=MagickTrue;
5264 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5265 return(nexus_info->pixels);
5271 number_pixels=(MagickSizeType) width*height;
5272 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5274 if (cache_info->active_index_channel != MagickFalse)
5275 length+=number_pixels*
sizeof(IndexPacket);
5278 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5280 if (nexus_info->length < length)
5282 RelinquishCacheNexusPixels(nexus_info);
5283 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5285 if (status == MagickFalse)
5287 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5290 nexus_info->pixels=nexus_info->cache;
5291 nexus_info->indexes=(IndexPacket *) NULL;
5292 if (cache_info->active_index_channel != MagickFalse)
5293 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5294 nexus_info->region.width=width;
5295 nexus_info->region.height=height;
5296 nexus_info->region.x=x;
5297 nexus_info->region.y=y;
5298 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5299 MagickTrue : MagickFalse;
5300 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5301 return(nexus_info->pixels);
5332 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5333 const Quantum opacity)
5336 *magick_restrict image_view;
5344 assert(image != (
Image *) NULL);
5345 assert(image->signature == MagickCoreSignature);
5346 if (IsEventLogging() != MagickFalse)
5347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5348 assert(image->cache != (Cache) NULL);
5349 image->matte=MagickTrue;
5351 image_view=AcquireVirtualCacheView(image,&image->exception);
5352 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5353 #pragma omp parallel for schedule(static) shared(status) \
5354 magick_number_threads(image,image,image->rows,1)
5356 for (y=0; y < (ssize_t) image->rows; y++)
5364 if (status == MagickFalse)
5366 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5373 for (x=0; x < (ssize_t) image->columns; x++)
5378 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5380 image_view=DestroyCacheView(image_view);
5384 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5385 const VirtualPixelMethod virtual_pixel_method)
5388 *magick_restrict cache_info;
5393 assert(image != (
Image *) NULL);
5394 assert(image->signature == MagickCoreSignature);
5395 if (IsEventLogging() != MagickFalse)
5396 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5397 assert(image->cache != (Cache) NULL);
5399 assert(cache_info->signature == MagickCoreSignature);
5400 method=cache_info->virtual_pixel_method;
5401 cache_info->virtual_pixel_method=virtual_pixel_method;
5402 if ((image->columns != 0) && (image->rows != 0))
5403 switch (virtual_pixel_method)
5405 case BackgroundVirtualPixelMethod:
5407 if ((image->background_color.opacity != OpaqueOpacity) &&
5408 (image->matte == MagickFalse))
5409 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5410 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5411 (IsGrayColorspace(image->colorspace) != MagickFalse))
5412 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5415 case TransparentVirtualPixelMethod:
5417 if (image->matte == MagickFalse)
5418 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5427 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5451 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5456 assert(cache_info != (
CacheInfo *)NULL);
5457 if ((cache_info->type != MemoryCache) ||
5463 LockSemaphoreInfo(cache_info->semaphore);
5472 clEnv=GetDefaultOpenCLEnv();
5473 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5474 if (events != (cl_event *) NULL)
5488 context=GetOpenCLContext(clEnv);
5489 queue=AcquireOpenCLCommandQueue(clEnv);
5490 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5491 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5492 cache_info->length,event_count,events,NULL,&status);
5493 assert(pixels == cache_info->pixels);
5494 events=(cl_event *) RelinquishMagickMemory(events);
5495 RelinquishOpenCLCommandQueue(clEnv,queue);
5497 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5499 UnlockSemaphoreInfo(cache_info->semaphore);
5502 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5505 *magick_restrict cache_info;
5507 assert(image != (
Image *)NULL);
5509 CopyOpenCLBuffer(cache_info);
5542 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5546 *magick_restrict cache_info;
5554 assert(image != (
Image *) NULL);
5555 assert(image->signature == MagickCoreSignature);
5556 if (image->cache == (Cache) NULL)
5557 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5559 assert(cache_info->signature == MagickCoreSignature);
5560 if (cache_info->type == UndefinedCache)
5561 return(MagickFalse);
5562 if ((image->storage_class == DirectClass) &&
5563 (image->clip_mask != (
Image *) NULL) &&
5564 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5565 return(MagickFalse);
5566 if ((image->storage_class == DirectClass) &&
5567 (image->mask != (
Image *) NULL) &&
5568 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5569 return(MagickFalse);
5570 if (nexus_info->authentic_pixel_cache != MagickFalse)
5572 if (image->taint == MagickFalse)
5573 image->taint=MagickTrue;
5576 assert(cache_info->signature == MagickCoreSignature);
5577 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5578 if ((cache_info->active_index_channel != MagickFalse) &&
5579 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5580 return(MagickFalse);
5581 if ((status != MagickFalse) && (image->taint == MagickFalse))
5582 image->taint=MagickTrue;
5613 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5617 *magick_restrict cache_info;
5620 id = GetOpenMPThreadId();
5625 assert(image != (
Image *) NULL);
5626 assert(image->signature == MagickCoreSignature);
5627 assert(image->cache != (Cache) NULL);
5629 assert(cache_info->signature == MagickCoreSignature);
5630 assert(
id < (
int) cache_info->number_threads);
5631 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5663 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5667 *magick_restrict cache_info;
5670 id = GetOpenMPThreadId();
5675 assert(image != (
Image *) NULL);
5676 assert(image->signature == MagickCoreSignature);
5677 assert(image->cache != (Cache) NULL);
5679 assert(cache_info->signature == MagickCoreSignature);
5680 if (cache_info->methods.sync_authentic_pixels_handler !=
5681 (SyncAuthenticPixelsHandler) NULL)
5682 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5683 assert(
id < (
int) cache_info->number_threads);
5684 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5716 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5720 *magick_restrict cache_info;
5722 assert(image != (
Image *) NULL);
5724 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5725 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5756 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5776 if (cache_info->active_index_channel == MagickFalse)
5777 return(MagickFalse);
5778 if (nexus_info->authentic_pixel_cache != MagickFalse)
5780 if (nexus_info->indexes == (IndexPacket *) NULL)
5781 return(MagickFalse);
5782 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5783 return(MagickFalse);
5784 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5785 nexus_info->region.x;
5786 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5787 rows=nexus_info->region.height;
5788 extent=(MagickSizeType) length*rows;
5789 p=nexus_info->indexes;
5791 switch (cache_info->type)
5802 if ((cache_info->columns == nexus_info->region.width) &&
5803 (extent == (MagickSizeType) ((
size_t) extent)))
5808 q=cache_info->indexes+offset;
5809 for (y=0; y < (ssize_t) rows; y++)
5811 (void) memcpy(q,p,(
size_t) length);
5812 p+=nexus_info->region.width;
5813 q+=cache_info->columns;
5822 LockSemaphoreInfo(cache_info->file_semaphore);
5823 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5825 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5826 cache_info->cache_filename);
5827 UnlockSemaphoreInfo(cache_info->file_semaphore);
5828 return(MagickFalse);
5830 if ((cache_info->columns == nexus_info->region.width) &&
5831 (extent <= MagickMaxBufferExtent))
5836 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5837 for (y=0; y < (ssize_t) rows; y++)
5839 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5840 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5841 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5843 if (count < (MagickOffsetType) length)
5845 p+=nexus_info->region.width;
5846 offset+=(MagickOffsetType) cache_info->columns;
5848 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5849 (
void) ClosePixelCacheOnDisk(cache_info);
5850 UnlockSemaphoreInfo(cache_info->file_semaphore);
5853 case DistributedCache:
5861 LockSemaphoreInfo(cache_info->file_semaphore);
5862 region=nexus_info->region;
5863 if ((cache_info->columns != nexus_info->region.width) ||
5864 (extent > MagickMaxBufferExtent))
5871 for (y=0; y < (ssize_t) rows; y++)
5874 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5875 if (count != (MagickOffsetType) length)
5877 p+=nexus_info->region.width;
5880 UnlockSemaphoreInfo(cache_info->file_semaphore);
5886 if (y < (ssize_t) rows)
5888 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5889 cache_info->cache_filename);
5890 return(MagickFalse);
5892 if ((cache_info->debug != MagickFalse) &&
5893 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5894 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5895 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5896 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5897 nexus_info->region.x,(
double) nexus_info->region.y);
5929 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5949 if (nexus_info->authentic_pixel_cache != MagickFalse)
5951 if (IsValidOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5952 return(MagickFalse);
5953 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5954 nexus_info->region.x;
5955 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5956 rows=nexus_info->region.height;
5958 p=nexus_info->pixels;
5960 switch (cache_info->type)
5971 if ((cache_info->columns == nexus_info->region.width) &&
5972 (extent == (MagickSizeType) ((
size_t) extent)))
5977 q=cache_info->pixels+offset;
5978 for (y=0; y < (ssize_t) rows; y++)
5980 (void) memcpy(q,p,(
size_t) length);
5981 p+=nexus_info->region.width;
5982 q+=cache_info->columns;
5991 LockSemaphoreInfo(cache_info->file_semaphore);
5992 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5994 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5995 cache_info->cache_filename);
5996 UnlockSemaphoreInfo(cache_info->file_semaphore);
5997 return(MagickFalse);
5999 if ((cache_info->columns == nexus_info->region.width) &&
6000 (extent <= MagickMaxBufferExtent))
6005 for (y=0; y < (ssize_t) rows; y++)
6007 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6008 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6009 if (count < (MagickOffsetType) length)
6011 p+=nexus_info->region.width;
6012 offset+=(MagickOffsetType) cache_info->columns;
6014 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6015 (
void) ClosePixelCacheOnDisk(cache_info);
6016 UnlockSemaphoreInfo(cache_info->file_semaphore);
6019 case DistributedCache:
6027 LockSemaphoreInfo(cache_info->file_semaphore);
6028 region=nexus_info->region;
6029 if ((cache_info->columns != nexus_info->region.width) ||
6030 (extent > MagickMaxBufferExtent))
6037 for (y=0; y < (ssize_t) rows; y++)
6040 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6041 if (count != (MagickOffsetType) length)
6043 p+=nexus_info->region.width;
6046 UnlockSemaphoreInfo(cache_info->file_semaphore);
6052 if (y < (ssize_t) rows)
6054 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6055 cache_info->cache_filename);
6056 return(MagickFalse);
6058 if ((cache_info->debug != MagickFalse) &&
6059 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6060 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6061 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6062 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6063 nexus_info->region.x,(
double) nexus_info->region.y);