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);
164 #if defined(MAGICKCORE_OPENCL_SUPPORT)
171 for (i=0; i < (ssize_t) info->event_count; i++)
172 clEnv->library->clReleaseEvent(info->events[i]);
173 info->events=(cl_event *) RelinquishMagickMemory(info->events);
174 DestroySemaphoreInfo(&info->events_semaphore);
175 if (info->buffer != (cl_mem) NULL)
177 clEnv->library->clReleaseMemObject(info->buffer);
178 info->buffer=(cl_mem) NULL;
183 static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
184 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
199 magick_unreferenced(event);
200 magick_unreferenced(event_command_exec_status);
202 clEnv=GetDefaultOpenCLEnv();
203 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
211 status=clEnv->library->clGetEventInfo(info->events[i],
212 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
213 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
215 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
216 &RelinquishPixelCachePixelsDelayed,info);
221 RelinquishMagickResource(MemoryResource,info->length);
222 (void) RelinquishOpenCLCacheInfo(clEnv,info);
223 (void) RelinquishAlignedMemory(pixels);
226 static MagickBooleanType RelinquishOpenCLBuffer(
232 assert(cache_info != (
CacheInfo *) NULL);
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
240 cl_uint *event_count)
249 events=(cl_event *) NULL;
250 LockSemaphoreInfo(opencl_info->events_semaphore);
251 *event_count=opencl_info->event_count;
252 if (*event_count > 0)
254 events=AcquireQuantumMemory(*event_count,
sizeof(*events));
255 if (events == (cl_event *) NULL)
259 for (i=0; i < opencl_info->event_count; i++)
260 events[i]=opencl_info->events[i];
263 UnlockSemaphoreInfo(opencl_info->events_semaphore);
268 #if defined(MAGICKCORE_OPENCL_SUPPORT)
294 extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
297 *magick_restrict cache_info;
302 assert(image != (
const Image *) NULL);
303 assert(event != (cl_event) NULL);
306 clEnv=GetDefaultOpenCLEnv();
307 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
309 clEnv->library->clWaitForEvents(1,&event);
312 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
313 if (cache_info->opencl->events == (cl_event *) NULL)
315 cache_info->opencl->events=AcquireMagickMemory(
sizeof(
316 *cache_info->opencl->events));
317 cache_info->opencl->event_count=1;
320 cache_info->opencl->events=ResizeQuantumMemory(cache_info->opencl->events,
321 ++cache_info->opencl->event_count,
sizeof(*cache_info->opencl->events));
322 if (cache_info->opencl->events == (cl_event *) NULL)
323 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
324 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
325 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
351 MagickExport Cache AcquirePixelCache(
const size_t number_threads)
354 *magick_restrict cache_info;
359 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
361 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
362 (void) memset(cache_info,0,
sizeof(*cache_info));
363 cache_info->type=UndefinedCache;
364 cache_info->mode=IOMode;
365 cache_info->disk_mode=IOMode;
366 cache_info->colorspace=sRGBColorspace;
367 cache_info->channels=4;
368 cache_info->file=(-1);
369 cache_info->id=GetMagickThreadId();
370 cache_info->number_threads=number_threads;
371 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
372 cache_info->number_threads=GetOpenMPMaximumThreads();
373 if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
374 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
375 if (cache_info->number_threads == 0)
376 cache_info->number_threads=1;
377 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
378 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
379 if (value != (
const char *) NULL)
381 cache_info->synchronize=IsStringTrue(value);
382 value=DestroyString(value);
384 value=GetPolicyValue(
"cache:synchronize");
385 if (value != (
const char *) NULL)
387 cache_info->synchronize=IsStringTrue(value);
388 value=DestroyString(value);
390 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
391 (MagickSizeType) MAGICK_SSIZE_MAX);
392 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
393 (MagickSizeType) MAGICK_SSIZE_MAX);
394 cache_info->semaphore=AllocateSemaphoreInfo();
395 cache_info->reference_count=1;
396 cache_info->file_semaphore=AllocateSemaphoreInfo();
397 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
398 cache_info->signature=MagickCoreSignature;
399 return((Cache ) cache_info);
424 MagickExport
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
427 **magick_restrict nexus_info;
432 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
433 number_threads,
sizeof(*nexus_info)));
435 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
436 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
437 2*
sizeof(**nexus_info));
439 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
440 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
441 for (i=0; i < (ssize_t) (2*number_threads); i++)
443 nexus_info[i]=(*nexus_info+i);
444 if (i < (ssize_t) number_threads)
445 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
446 nexus_info[i]->signature=MagickCoreSignature;
479 MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
483 *magick_restrict cache_info;
485 assert(image != (
const Image *) NULL);
486 assert(image->signature == MagickCoreSignature);
488 assert(exception->signature == MagickCoreSignature);
489 assert(image->cache != (Cache) NULL);
491 assert(cache_info->signature == MagickCoreSignature);
494 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
495 return((
const void *) NULL);
496 *length=cache_info->length;
497 return((
const void *) cache_info->pixels);
518 MagickExport MagickBooleanType CacheComponentGenesis(
void)
521 cache_semaphore=AllocateSemaphoreInfo();
543 MagickExport
void CacheComponentTerminus(
void)
546 ActivateSemaphoreInfo(&cache_semaphore);
548 DestroySemaphoreInfo(&cache_semaphore);
580 static MagickBooleanType ClipPixelCacheNexus(
Image *image,
584 *magick_restrict cache_info;
590 *magick_restrict nexus_indexes,
591 *magick_restrict indexes;
597 **magick_restrict clip_nexus;
609 if (IsEventLogging() != MagickFalse)
610 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
611 if ((image->clip_mask == (
Image *) NULL) ||
612 (image->storage_class == PseudoClass))
614 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
617 if (cache_info == (Cache) NULL)
619 clip_nexus=AcquirePixelCacheNexus(1);
620 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
621 nexus_info->region.width,nexus_info->region.height,
622 nexus_info->virtual_nexus,exception);
623 indexes=nexus_info->virtual_nexus->indexes;
624 q=nexus_info->pixels;
625 nexus_indexes=nexus_info->indexes;
626 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
627 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
628 nexus_info->region.height,clip_nexus[0],exception);
633 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
638 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
643 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
644 if (fabs(mask_alpha) >= MagickEpsilon)
646 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
647 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
648 GetPixelOpacity(q)));
649 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
650 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
651 GetPixelOpacity(q)));
652 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
653 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
654 GetPixelOpacity(q)));
655 SetPixelOpacity(q,GetPixelOpacity(p));
656 if (cache_info->active_index_channel != MagickFalse)
657 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
665 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
691 MagickExport Cache ClonePixelCache(
const Cache cache)
694 *magick_restrict clone_info;
697 *magick_restrict cache_info;
699 assert(cache != NULL);
701 assert(cache_info->signature == MagickCoreSignature);
702 if (IsEventLogging() != MagickFalse)
703 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
704 cache_info->filename);
705 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
706 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
707 return((Cache ) clone_info);
735 MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
738 *magick_restrict cache_info,
739 *magick_restrict source_info;
741 assert(clone != (Cache) NULL);
743 assert(source_info->signature == MagickCoreSignature);
744 if (IsEventLogging() != MagickFalse)
745 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
746 source_info->filename);
747 assert(cache != (Cache) NULL);
749 assert(cache_info->signature == MagickCoreSignature);
750 source_info->methods=cache_info->methods;
782 static MagickBooleanType ClonePixelCacheOnDisk(
803 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
804 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
806 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
807 (lseek(clone_info->file,0,SEEK_SET) < 0))
809 quantum=(size_t) MagickMaxBufferExtent;
810 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
812 #if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
813 if (cache_info->length < 0x7ffff000)
815 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
816 (
size_t) cache_info->length);
817 if (count == (ssize_t) cache_info->length)
819 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
820 (lseek(clone_info->file,0,SEEK_SET) < 0))
824 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
826 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
827 if (buffer == (
unsigned char *) NULL)
828 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
830 while ((count=read(cache_info->file,buffer,quantum)) > 0)
835 number_bytes=write(clone_info->file,buffer,(
size_t) count);
836 if (number_bytes != count)
838 extent+=(size_t) number_bytes;
840 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
841 if (extent != cache_info->length)
846 static MagickBooleanType ClonePixelCacheRepository(
850 #define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
851 #define cache_number_threads(source,destination,chunk,multithreaded) \
852 num_threads((multithreaded) == 0 ? 1 : \
853 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
854 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
855 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
856 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
862 **magick_restrict cache_nexus,
863 **magick_restrict clone_nexus;
871 assert(cache_info != (
CacheInfo *) NULL);
872 assert(clone_info != (
CacheInfo *) NULL);
874 if (cache_info->type == PingCache)
876 if ((cache_info->storage_class == clone_info->storage_class) &&
877 (cache_info->colorspace == clone_info->colorspace) &&
878 (cache_info->channels == clone_info->channels) &&
879 (cache_info->columns == clone_info->columns) &&
880 (cache_info->rows == clone_info->rows) &&
881 (cache_info->active_index_channel == clone_info->active_index_channel))
886 if (((cache_info->type == MemoryCache) ||
887 (cache_info->type == MapCache)) &&
888 ((clone_info->type == MemoryCache) ||
889 (clone_info->type == MapCache)))
891 (void) memcpy(clone_info->pixels,cache_info->pixels,
892 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
893 if ((cache_info->active_index_channel != MagickFalse) &&
894 (clone_info->active_index_channel != MagickFalse))
895 (void) memcpy(clone_info->indexes,cache_info->indexes,
896 cache_info->columns*cache_info->rows*
897 sizeof(*cache_info->indexes));
900 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
901 return(ClonePixelCacheOnDisk(cache_info,clone_info));
906 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
907 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
908 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
909 sizeof(*cache_info->pixels);
911 #if defined(MAGICKCORE_OPENMP_SUPPORT)
912 #pragma omp parallel for schedule(static) shared(status) \
913 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
915 for (y=0; y < (ssize_t) cache_info->rows; y++)
918 id = GetOpenMPThreadId();
923 if (status == MagickFalse)
925 if (y >= (ssize_t) clone_info->rows)
927 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
928 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
931 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
932 if (status == MagickFalse)
934 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
935 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
938 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
939 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
940 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
942 if ((cache_info->active_index_channel != MagickFalse) &&
943 (clone_info->active_index_channel != MagickFalse))
948 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
949 sizeof(*cache_info->indexes);
950 #if defined(MAGICKCORE_OPENMP_SUPPORT)
951 #pragma omp parallel for schedule(static) shared(status) \
952 cache_number_threads(cache_info,clone_info,cache_info->rows,1)
954 for (y=0; y < (ssize_t) cache_info->rows; y++)
957 id = GetOpenMPThreadId();
962 if (status == MagickFalse)
964 if (y >= (ssize_t) clone_info->rows)
966 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
967 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
970 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
971 if (status == MagickFalse)
973 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
974 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
977 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
978 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
981 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
982 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
983 if (cache_info->debug != MagickFalse)
986 message[MaxTextExtent];
988 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
989 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
990 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
991 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1018 static void DestroyImagePixelCache(
Image *image)
1020 assert(image != (
Image *) NULL);
1021 assert(image->signature == MagickCoreSignature);
1022 if (IsEventLogging() != MagickFalse)
1023 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1024 if (image->cache != (
void *) NULL)
1025 image->cache=DestroyPixelCache(image->cache);
1050 MagickExport
void DestroyImagePixels(
Image *image)
1053 *magick_restrict cache_info;
1055 assert(image != (
const Image *) NULL);
1056 assert(image->signature == MagickCoreSignature);
1057 if (IsEventLogging() != MagickFalse)
1058 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1059 assert(image->cache != (Cache) NULL);
1061 assert(cache_info->signature == MagickCoreSignature);
1062 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1064 cache_info->methods.destroy_pixel_handler(image);
1067 image->cache=DestroyPixelCache(image->cache);
1093 static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1099 if (cache_info->file != -1)
1101 status=close(cache_info->file);
1102 cache_info->file=(-1);
1103 RelinquishMagickResource(FileResource,1);
1105 return(status == -1 ? MagickFalse : MagickTrue);
1108 static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1110 switch (cache_info->type)
1114 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1115 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1116 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1122 if (cache_info->mapped == MagickFalse)
1123 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1124 cache_info->pixels);
1127 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1130 RelinquishMagickResource(MemoryResource,cache_info->length);
1135 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1137 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1138 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1139 *cache_info->cache_filename=
'\0';
1140 RelinquishMagickResource(MapResource,cache_info->length);
1145 if (cache_info->file != -1)
1146 (void) ClosePixelCacheOnDisk(cache_info);
1147 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1148 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1149 *cache_info->cache_filename=
'\0';
1150 RelinquishMagickResource(DiskResource,cache_info->length);
1153 case DistributedCache:
1155 *cache_info->cache_filename=
'\0';
1157 cache_info->server_info);
1163 cache_info->type=UndefinedCache;
1164 cache_info->mapped=MagickFalse;
1165 cache_info->indexes=(IndexPacket *) NULL;
1168 MagickExport Cache DestroyPixelCache(Cache cache)
1171 *magick_restrict cache_info;
1173 assert(cache != (Cache) NULL);
1175 assert(cache_info->signature == MagickCoreSignature);
1176 if (IsEventLogging() != MagickFalse)
1177 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1178 cache_info->filename);
1179 LockSemaphoreInfo(cache_info->semaphore);
1180 cache_info->reference_count--;
1181 if (cache_info->reference_count != 0)
1183 UnlockSemaphoreInfo(cache_info->semaphore);
1184 return((Cache) NULL);
1186 UnlockSemaphoreInfo(cache_info->semaphore);
1187 if (cache_info->debug != MagickFalse)
1190 message[MaxTextExtent];
1192 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1193 cache_info->filename);
1194 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1196 RelinquishPixelCachePixels(cache_info);
1199 cache_info->server_info);
1200 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1201 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1202 cache_info->number_threads);
1203 if (cache_info->random_info != (
RandomInfo *) NULL)
1204 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1206 DestroySemaphoreInfo(&cache_info->file_semaphore);
1208 DestroySemaphoreInfo(&cache_info->semaphore);
1209 cache_info->signature=(~MagickCoreSignature);
1210 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1241 static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1243 if (nexus_info->mapped == MagickFalse)
1244 (void) RelinquishAlignedMemory(nexus_info->cache);
1246 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1249 nexus_info->indexes=(IndexPacket *) NULL;
1250 nexus_info->length=0;
1251 nexus_info->mapped=MagickFalse;
1255 const size_t number_threads)
1260 assert(nexus_info != (
NexusInfo **) NULL);
1261 for (i=0; i < (ssize_t) (2*number_threads); i++)
1264 RelinquishCacheNexusPixels(nexus_info[i]);
1265 nexus_info[i]->signature=(~MagickCoreSignature);
1267 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1268 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1295 static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1298 *magick_restrict cache_info;
1301 id = GetOpenMPThreadId();
1303 assert(image != (
const Image *) NULL);
1304 assert(image->signature == MagickCoreSignature);
1305 assert(image->cache != (Cache) NULL);
1307 assert(cache_info->signature == MagickCoreSignature);
1308 assert(
id < (
int) cache_info->number_threads);
1309 return(cache_info->nexus_info[
id]->indexes);
1337 MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1340 *magick_restrict cache_info;
1343 id = GetOpenMPThreadId();
1345 assert(image != (
const Image *) NULL);
1346 assert(image->signature == MagickCoreSignature);
1347 assert(image->cache != (Cache) NULL);
1349 assert(cache_info->signature == MagickCoreSignature);
1350 if (cache_info->methods.get_authentic_indexes_from_handler !=
1351 (GetAuthenticIndexesFromHandler) NULL)
1352 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1353 assert(
id < (
int) cache_info->number_threads);
1354 return(cache_info->nexus_info[
id]->indexes);
1357 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1381 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1385 *magick_restrict cache_info;
1396 assert(image != (
const Image *) NULL);
1398 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1400 SyncImagePixelCache((
Image *) image,exception);
1403 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1404 return((cl_mem) NULL);
1405 LockSemaphoreInfo(cache_info->semaphore);
1406 clEnv=GetDefaultOpenCLEnv();
1409 assert(cache_info->pixels != NULL);
1410 context=GetOpenCLContext(clEnv);
1412 sizeof(*cache_info->opencl));
1413 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1414 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1415 cache_info->opencl->length=cache_info->length;
1416 cache_info->opencl->pixels=cache_info->pixels;
1417 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1418 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1419 if (status != CL_SUCCESS)
1420 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1423 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1424 UnlockSemaphoreInfo(cache_info->semaphore);
1426 return((cl_mem) NULL);
1427 return(cache_info->opencl->buffer);
1467 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1471 *magick_restrict cache_info;
1474 *magick_restrict pixels;
1479 assert(image != (
Image *) NULL);
1480 assert(image->signature == MagickCoreSignature);
1481 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1482 nexus_info,exception);
1486 assert(cache_info->signature == MagickCoreSignature);
1487 if (nexus_info->authentic_pixel_cache != MagickFalse)
1489 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1491 if (cache_info->active_index_channel != MagickFalse)
1492 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1523 *magick_restrict cache_info;
1526 id = GetOpenMPThreadId();
1528 assert(image != (
const Image *) NULL);
1529 assert(image->signature == MagickCoreSignature);
1530 assert(image->cache != (Cache) NULL);
1532 assert(cache_info->signature == MagickCoreSignature);
1533 assert(
id < (
int) cache_info->number_threads);
1534 return(cache_info->nexus_info[
id]->pixels);
1563 *magick_restrict cache_info;
1566 id = GetOpenMPThreadId();
1568 assert(image != (
const Image *) NULL);
1569 assert(image->signature == MagickCoreSignature);
1570 assert(image->cache != (Cache) NULL);
1572 assert(cache_info->signature == MagickCoreSignature);
1573 if (cache_info->methods.get_authentic_pixels_from_handler !=
1574 (GetAuthenticPixelsFromHandler) NULL)
1575 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1576 assert(
id < (
int) cache_info->number_threads);
1577 return(cache_info->nexus_info[
id]->pixels);
1627 const ssize_t y,
const size_t columns,
const size_t rows,
1631 *magick_restrict cache_info;
1634 id = GetOpenMPThreadId();
1636 assert(image != (
Image *) NULL);
1637 assert(image->signature == MagickCoreSignature);
1638 assert(image->cache != (Cache) NULL);
1640 assert(cache_info->signature == MagickCoreSignature);
1641 if (cache_info->methods.get_authentic_pixels_handler !=
1642 (GetAuthenticPixelsHandler) NULL)
1643 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1645 assert(
id < (
int) cache_info->number_threads);
1646 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1647 cache_info->nexus_info[
id],exception));
1682 const ssize_t y,
const size_t columns,
const size_t rows,
1686 *magick_restrict cache_info;
1689 id = GetOpenMPThreadId();
1691 assert(image != (
const Image *) NULL);
1692 assert(image->signature == MagickCoreSignature);
1693 assert(image->cache != (Cache) NULL);
1695 if (cache_info == (Cache) NULL)
1697 assert(cache_info->signature == MagickCoreSignature);
1698 assert(
id < (
int) cache_info->number_threads);
1699 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1700 cache_info->nexus_info[
id],exception));
1726 MagickExport MagickSizeType GetImageExtent(
const Image *image)
1729 *magick_restrict cache_info;
1732 id = GetOpenMPThreadId();
1734 assert(image != (
Image *) NULL);
1735 assert(image->signature == MagickCoreSignature);
1736 if (IsEventLogging() != MagickFalse)
1737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1738 assert(image->cache != (Cache) NULL);
1740 assert(cache_info->signature == MagickCoreSignature);
1741 assert(
id < (
int) cache_info->number_threads);
1742 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1745 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1773 extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1774 cl_uint *event_count)
1777 *magick_restrict cache_info;
1782 assert(image != (
const Image *) NULL);
1783 assert(event_count != (cl_uint *) NULL);
1786 events=(cl_event *) NULL;
1788 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1823 static inline MagickBooleanType ValidatePixelCacheMorphology(
1824 const Image *magick_restrict image)
1827 *magick_restrict cache_info;
1833 if ((image->storage_class != cache_info->storage_class) ||
1834 (image->colorspace != cache_info->colorspace) ||
1835 (image->channels != cache_info->channels) ||
1836 (image->columns != cache_info->columns) ||
1837 (image->rows != cache_info->rows) ||
1838 (cache_info->nexus_info == (
NexusInfo **) NULL))
1839 return(MagickFalse);
1843 static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1847 *magick_restrict cache_info;
1851 status = MagickTrue;
1853 static MagickSizeType
1854 cpu_throttle = MagickResourceInfinity,
1857 if (IsImageTTLExpired(image) != MagickFalse)
1859 (void) ThrowMagickException(exception,GetMagickModule(),
1860 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1861 return((Cache) NULL);
1863 if (cpu_throttle == MagickResourceInfinity)
1864 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1865 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1866 MagickDelay(cpu_throttle);
1867 LockSemaphoreInfo(image->semaphore);
1868 assert(image->cache != (Cache) NULL);
1870 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1871 CopyOpenCLBuffer(cache_info);
1873 destroy=MagickFalse;
1874 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1876 LockSemaphoreInfo(cache_info->semaphore);
1877 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1888 clone_image=(*image);
1889 clone_image.semaphore=AllocateSemaphoreInfo();
1890 clone_image.reference_count=1;
1891 clone_image.cache=ClonePixelCache(cache_info);
1892 clone_info=(
CacheInfo *) clone_image.cache;
1893 status=OpenPixelCache(&clone_image,IOMode,exception);
1894 if (status == MagickFalse)
1895 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1898 if (clone != MagickFalse)
1899 status=ClonePixelCacheRepository(clone_info,cache_info,
1901 if (status == MagickFalse)
1902 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1906 image->cache=clone_info;
1909 DestroySemaphoreInfo(&clone_image.semaphore);
1911 UnlockSemaphoreInfo(cache_info->semaphore);
1913 if (destroy != MagickFalse)
1914 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1915 if (status != MagickFalse)
1920 if (image->type != UndefinedType)
1921 image->type=UndefinedType;
1922 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1924 status=OpenPixelCache(image,IOMode,exception);
1926 if (cache_info->file != -1)
1927 (void) ClosePixelCacheOnDisk(cache_info);
1930 UnlockSemaphoreInfo(image->semaphore);
1931 if (status == MagickFalse)
1932 return((Cache) NULL);
1933 return(image->cache);
1960 MagickExport CacheType GetPixelCacheType(
const Image *image)
1962 return(GetImagePixelCacheType(image));
1965 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1968 *magick_restrict cache_info;
1970 assert(image != (
Image *) NULL);
1971 assert(image->signature == MagickCoreSignature);
1972 assert(image->cache != (Cache) NULL);
1974 assert(cache_info->signature == MagickCoreSignature);
1975 return(cache_info->type);
2008 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2012 *magick_restrict cache_info;
2015 *magick_restrict pixels;
2017 assert(image != (
Image *) NULL);
2018 assert(image->signature == MagickCoreSignature);
2019 assert(image->cache != (Cache) NULL);
2021 assert(cache_info->signature == MagickCoreSignature);
2022 *pixel=image->background_color;
2023 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2024 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2025 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2027 return(MagickFalse);
2063 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2067 *magick_restrict cache_info;
2070 id = GetOpenMPThreadId();
2073 *magick_restrict pixels;
2075 assert(image != (
const Image *) NULL);
2076 assert(image->signature == MagickCoreSignature);
2077 assert(image->cache != (Cache) NULL);
2079 assert(cache_info->signature == MagickCoreSignature);
2080 *pixel=image->background_color;
2081 assert(
id < (
int) cache_info->number_threads);
2082 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2083 cache_info->nexus_info[
id],exception);
2085 return(MagickFalse);
2122 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2127 *magick_restrict cache_info;
2130 id = GetOpenMPThreadId();
2133 *magick_restrict indexes;
2136 *magick_restrict pixels;
2138 assert(image != (
const Image *) NULL);
2139 assert(image->signature == MagickCoreSignature);
2140 assert(image->cache != (Cache) NULL);
2142 assert(cache_info->signature == MagickCoreSignature);
2143 assert(
id < (
int) cache_info->number_threads);
2144 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2145 1UL,1UL,cache_info->nexus_info[
id],exception);
2146 GetMagickPixelPacket(image,pixel);
2148 return(MagickFalse);
2149 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2150 SetMagickPixelPacket(image,pixels,indexes,pixel);
2189 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2190 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2194 *magick_restrict cache_info;
2197 id = GetOpenMPThreadId();
2200 *magick_restrict pixels;
2202 assert(image != (
const Image *) NULL);
2203 assert(image->signature == MagickCoreSignature);
2204 assert(image->cache != (Cache) NULL);
2206 assert(cache_info->signature == MagickCoreSignature);
2207 *pixel=image->background_color;
2208 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2209 (GetOneVirtualPixelFromHandler) NULL)
2210 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2211 virtual_pixel_method,x,y,pixel,exception));
2212 assert(
id < (
int) cache_info->number_threads);
2213 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2214 cache_info->nexus_info[
id],exception);
2216 return(MagickFalse);
2252 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2256 *magick_restrict cache_info;
2259 id = GetOpenMPThreadId();
2262 *magick_restrict pixels;
2264 assert(image != (
const Image *) NULL);
2265 assert(image->signature == MagickCoreSignature);
2266 assert(image->cache != (Cache) NULL);
2268 assert(cache_info->signature == MagickCoreSignature);
2269 *pixel=image->background_color;
2270 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2271 (GetOneVirtualPixelFromHandler) NULL)
2272 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2273 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2274 assert(
id < (
int) cache_info->number_threads);
2275 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2276 1UL,1UL,cache_info->nexus_info[
id],exception);
2278 return(MagickFalse);
2317 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2318 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2322 *magick_restrict cache_info;
2325 id = GetOpenMPThreadId();
2328 *magick_restrict pixels;
2330 assert(image != (
const Image *) NULL);
2331 assert(image->signature == MagickCoreSignature);
2332 assert(image->cache != (Cache) NULL);
2334 assert(cache_info->signature == MagickCoreSignature);
2335 assert(
id < (
int) cache_info->number_threads);
2336 *pixel=image->background_color;
2337 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2338 cache_info->nexus_info[
id],exception);
2340 return(MagickFalse);
2370 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2373 *magick_restrict cache_info;
2375 assert(cache != (Cache) NULL);
2377 assert(cache_info->signature == MagickCoreSignature);
2378 if (IsEventLogging() != MagickFalse)
2379 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2380 cache_info->filename);
2381 return(cache_info->channels);
2406 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2409 *magick_restrict cache_info;
2411 assert(cache != (Cache) NULL);
2413 assert(cache_info->signature == MagickCoreSignature);
2414 if (IsEventLogging() != MagickFalse)
2415 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2416 cache_info->filename);
2417 return(cache_info->colorspace);
2443 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2446 *magick_restrict cache_info;
2448 assert(image != (
const Image *) NULL);
2449 assert(image->signature == MagickCoreSignature);
2450 assert(image->cache != (Cache) NULL);
2452 assert(cache_info->signature == MagickCoreSignature);
2453 return(cache_info->cache_filename);
2478 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2481 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2482 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2483 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2484 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2485 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2486 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2487 cache_methods->get_authentic_indexes_from_handler=
2488 GetAuthenticIndexesFromCache;
2489 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2490 cache_methods->get_one_authentic_pixel_from_handler=
2491 GetOneAuthenticPixelFromCache;
2492 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2493 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2494 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2521 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2525 *magick_restrict cache_info;
2530 assert(cache != NULL);
2532 assert(cache_info->signature == MagickCoreSignature);
2533 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2535 return((MagickSizeType) cache_info->columns*cache_info->rows);
2566 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2570 *magick_restrict cache_info;
2572 assert(image != (
const Image *) NULL);
2573 assert(image->signature == MagickCoreSignature);
2574 assert(image->cache != (Cache) NULL);
2575 assert(length != (MagickSizeType *) NULL);
2577 assert(exception->signature == MagickCoreSignature);
2579 assert(cache_info->signature == MagickCoreSignature);
2581 *length=cache_info->length;
2582 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2583 return((
void *) NULL);
2584 return((
void *) cache_info->pixels);
2611 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2614 *magick_restrict cache_info;
2616 assert(cache != (Cache) NULL);
2618 assert(cache_info->signature == MagickCoreSignature);
2619 if (IsEventLogging() != MagickFalse)
2620 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2621 cache_info->filename);
2622 return(cache_info->storage_class);
2652 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2655 assert(image != (
Image *) NULL);
2656 assert(image->signature == MagickCoreSignature);
2657 if (IsEventLogging() != MagickFalse)
2658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2660 if (GetImagePixelCacheType(image) == DiskCache)
2689 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2692 *magick_restrict cache_info;
2694 assert(image != (
Image *) NULL);
2695 assert(image->signature == MagickCoreSignature);
2696 assert(image->cache != (Cache) NULL);
2698 assert(cache_info->signature == MagickCoreSignature);
2699 return(cache_info->virtual_pixel_method);
2725 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2728 *magick_restrict cache_info;
2731 id = GetOpenMPThreadId();
2733 assert(image != (
const Image *) NULL);
2734 assert(image->signature == MagickCoreSignature);
2735 assert(image->cache != (Cache) NULL);
2737 assert(cache_info->signature == MagickCoreSignature);
2738 assert(
id < (
int) cache_info->number_threads);
2739 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2768 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2772 *magick_restrict cache_info;
2774 assert(cache != (Cache) NULL);
2776 assert(cache_info->signature == MagickCoreSignature);
2777 if (cache_info->storage_class == UndefinedClass)
2778 return((IndexPacket *) NULL);
2779 return(nexus_info->indexes);
2807 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2810 *magick_restrict cache_info;
2813 id = GetOpenMPThreadId();
2815 assert(image != (
const Image *) NULL);
2816 assert(image->signature == MagickCoreSignature);
2817 assert(image->cache != (Cache) NULL);
2819 assert(cache_info->signature == MagickCoreSignature);
2820 if (cache_info->methods.get_virtual_indexes_from_handler !=
2821 (GetVirtualIndexesFromHandler) NULL)
2826 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2827 if (indexes != (IndexPacket *) NULL)
2830 assert(
id < (
int) cache_info->number_threads);
2831 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2874 0, 48, 12, 60, 3, 51, 15, 63,
2875 32, 16, 44, 28, 35, 19, 47, 31,
2876 8, 56, 4, 52, 11, 59, 7, 55,
2877 40, 24, 36, 20, 43, 27, 39, 23,
2878 2, 50, 14, 62, 1, 49, 13, 61,
2879 34, 18, 46, 30, 33, 17, 45, 29,
2880 10, 58, 6, 54, 9, 57, 5, 53,
2881 42, 26, 38, 22, 41, 25, 37, 21
2884 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2889 index=x+DitherMatrix[x & 0x07]-32L;
2892 if (index >= (ssize_t) columns)
2893 return((ssize_t) columns-1L);
2897 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2902 index=y+DitherMatrix[y & 0x07]-32L;
2905 if (index >= (ssize_t) rows)
2906 return((ssize_t) rows-1L);
2910 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2914 if (x >= (ssize_t) columns)
2915 return((ssize_t) (columns-1));
2919 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2923 if (y >= (ssize_t) rows)
2924 return((ssize_t) (rows-1));
2928 static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2931 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2932 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2933 return(MagickFalse);
2937 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2939 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2942 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2944 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2947 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2948 const size_t extent)
2953 modulo.quotient=offset;
2957 modulo.quotient=offset/((ssize_t) extent);
2958 modulo.remainder=offset % ((ssize_t) extent);
2960 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2963 modulo.remainder+=((ssize_t) extent);
2968 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2969 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2970 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2974 *magick_restrict cache_info;
2977 *magick_restrict virtual_indexes;
2984 *magick_restrict indexes;
2994 *magick_restrict virtual_nexus;
2997 *magick_restrict pixels,
3008 assert(image != (
const Image *) NULL);
3009 assert(image->signature == MagickCoreSignature);
3010 assert(image->cache != (Cache) NULL);
3012 assert(cache_info->signature == MagickCoreSignature);
3013 if (cache_info->type == UndefinedCache)
3015 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3016 CopyOpenCLBuffer(cache_info);
3018 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3019 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3020 MagickTrue : MagickFalse,nexus_info,exception);
3023 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3025 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3026 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3028 offset+=nexus_info->region.x;
3029 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3030 nexus_info->region.width-1L;
3031 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3032 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3033 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3034 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3042 if (nexus_info->authentic_pixel_cache != MagickFalse)
3044 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3045 if (status == MagickFalse)
3047 if ((cache_info->storage_class == PseudoClass) ||
3048 (cache_info->colorspace == CMYKColorspace))
3050 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3051 if (status == MagickFalse)
3059 virtual_nexus=nexus_info->virtual_nexus;
3061 indexes=nexus_info->indexes;
3062 switch (virtual_pixel_method)
3064 case BlackVirtualPixelMethod:
3066 SetPixelRed(&virtual_pixel,0);
3067 SetPixelGreen(&virtual_pixel,0);
3068 SetPixelBlue(&virtual_pixel,0);
3069 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3072 case GrayVirtualPixelMethod:
3074 SetPixelRed(&virtual_pixel,QuantumRange/2);
3075 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3076 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3077 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3080 case TransparentVirtualPixelMethod:
3082 SetPixelRed(&virtual_pixel,0);
3083 SetPixelGreen(&virtual_pixel,0);
3084 SetPixelBlue(&virtual_pixel,0);
3085 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3088 case MaskVirtualPixelMethod:
3089 case WhiteVirtualPixelMethod:
3091 SetPixelRed(&virtual_pixel,QuantumRange);
3092 SetPixelGreen(&virtual_pixel,QuantumRange);
3093 SetPixelBlue(&virtual_pixel,QuantumRange);
3094 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3099 virtual_pixel=image->background_color;
3103 virtual_index=(IndexPacket) 0;
3104 for (v=0; v < (ssize_t) rows; v++)
3110 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3111 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3112 y_offset=EdgeY(y_offset,cache_info->rows);
3113 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3119 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3120 (ssize_t) columns-u);
3121 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3122 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3132 length=(MagickSizeType) 1;
3133 switch (virtual_pixel_method)
3135 case BackgroundVirtualPixelMethod:
3136 case ConstantVirtualPixelMethod:
3137 case BlackVirtualPixelMethod:
3138 case GrayVirtualPixelMethod:
3139 case TransparentVirtualPixelMethod:
3140 case MaskVirtualPixelMethod:
3141 case WhiteVirtualPixelMethod:
3144 virtual_indexes=(&virtual_index);
3147 case EdgeVirtualPixelMethod:
3150 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3151 EdgeX(x_offset,cache_info->columns),
3152 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3154 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3158 case RandomVirtualPixelMethod:
3160 if (cache_info->random_info == (
RandomInfo *) NULL)
3161 cache_info->random_info=AcquireRandomInfo();
3162 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3163 RandomX(cache_info->random_info,cache_info->columns),
3164 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3165 virtual_nexus,exception);
3166 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3170 case DitherVirtualPixelMethod:
3172 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3173 DitherX(x_offset,cache_info->columns),
3174 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3176 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3180 case TileVirtualPixelMethod:
3182 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3183 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3184 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3185 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3187 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3191 case MirrorVirtualPixelMethod:
3193 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3194 if ((x_modulo.quotient & 0x01) == 1L)
3195 x_modulo.remainder=(ssize_t) cache_info->columns-
3196 x_modulo.remainder-1L;
3197 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3198 if ((y_modulo.quotient & 0x01) == 1L)
3199 y_modulo.remainder=(ssize_t) cache_info->rows-
3200 y_modulo.remainder-1L;
3201 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3202 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3204 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3208 case CheckerTileVirtualPixelMethod:
3210 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3211 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3212 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3215 virtual_indexes=(&virtual_index);
3218 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3219 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3221 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3225 case HorizontalTileVirtualPixelMethod:
3227 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3230 virtual_indexes=(&virtual_index);
3233 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3234 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3235 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3236 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3238 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3242 case VerticalTileVirtualPixelMethod:
3244 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3247 virtual_indexes=(&virtual_index);
3250 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3251 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3252 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3253 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3255 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3259 case HorizontalTileEdgeVirtualPixelMethod:
3261 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3262 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3263 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3264 virtual_nexus,exception);
3265 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3269 case VerticalTileEdgeVirtualPixelMethod:
3271 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3272 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3273 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3274 virtual_nexus,exception);
3275 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3283 if ((indexes != (IndexPacket *) NULL) &&
3284 (virtual_indexes != (
const IndexPacket *) NULL))
3285 *indexes++=(*virtual_indexes);
3291 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3292 (
size_t) length,1UL,virtual_nexus,exception);
3295 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3296 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3298 if ((indexes != (IndexPacket *) NULL) &&
3299 (virtual_indexes != (
const IndexPacket *) NULL))
3301 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3302 sizeof(*virtual_indexes));
3306 if (u < (ssize_t) columns)
3312 if (v < (ssize_t) rows)
3352 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3353 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3356 *magick_restrict cache_info;
3359 id = GetOpenMPThreadId();
3361 assert(image != (
const Image *) NULL);
3362 assert(image->signature == MagickCoreSignature);
3363 assert(image->cache != (Cache) NULL);
3365 assert(cache_info->signature == MagickCoreSignature);
3366 assert(
id < (
int) cache_info->number_threads);
3367 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3368 cache_info->nexus_info[
id],exception));
3397 *magick_restrict cache_info;
3400 id = GetOpenMPThreadId();
3402 assert(image != (
const Image *) NULL);
3403 assert(image->signature == MagickCoreSignature);
3404 assert(image->cache != (Cache) NULL);
3406 assert(cache_info->signature == MagickCoreSignature);
3407 if (cache_info->methods.get_virtual_pixels_handler !=
3408 (GetVirtualPixelsHandler) NULL)
3409 return(cache_info->methods.get_virtual_pixels_handler(image));
3410 assert(
id < (
int) cache_info->number_threads);
3411 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3463 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3467 *magick_restrict cache_info;
3470 id = GetOpenMPThreadId();
3472 assert(image != (
const Image *) NULL);
3473 assert(image->signature == MagickCoreSignature);
3474 assert(image->cache != (Cache) NULL);
3476 assert(cache_info->signature == MagickCoreSignature);
3477 if (cache_info->methods.get_virtual_pixel_handler !=
3478 (GetVirtualPixelHandler) NULL)
3479 return(cache_info->methods.get_virtual_pixel_handler(image,
3480 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3481 assert(
id < (
int) cache_info->number_threads);
3482 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3483 columns,rows,cache_info->nexus_info[
id],exception));
3512 *magick_restrict cache_info;
3515 id = GetOpenMPThreadId();
3517 assert(image != (
const Image *) NULL);
3518 assert(image->signature == MagickCoreSignature);
3519 assert(image->cache != (Cache) NULL);
3521 assert(cache_info->signature == MagickCoreSignature);
3522 assert(
id < (
int) cache_info->number_threads);
3523 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3552 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3556 *magick_restrict cache_info;
3558 assert(cache != (Cache) NULL);
3560 assert(cache_info->signature == MagickCoreSignature);
3561 if (cache_info->storage_class == UndefinedClass)
3603 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3608 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3609 gamma=PerceptibleReciprocal(gamma);
3610 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3611 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3612 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3613 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3614 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3617 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3621 *magick_restrict cache_info;
3627 *magick_restrict nexus_indexes,
3628 *magick_restrict indexes;
3638 **magick_restrict mask_nexus;
3650 if (IsEventLogging() != MagickFalse)
3651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3652 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3654 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3657 if (cache_info == (Cache) NULL)
3658 return(MagickFalse);
3659 mask_nexus=AcquirePixelCacheNexus(1);
3660 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3661 nexus_info->virtual_nexus,exception);
3662 indexes=nexus_info->virtual_nexus->indexes;
3663 q=nexus_info->pixels;
3664 nexus_indexes=nexus_info->indexes;
3665 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3666 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3667 nexus_info->region.height,mask_nexus[0],&image->exception);
3670 return(MagickFalse);
3672 GetMagickPixelPacket(image,&alpha);
3673 GetMagickPixelPacket(image,&beta);
3674 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3679 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3681 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3682 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3683 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3684 alpha.opacity,&beta);
3685 SetPixelRed(q,ClampToQuantum(beta.red));
3686 SetPixelGreen(q,ClampToQuantum(beta.green));
3687 SetPixelBlue(q,ClampToQuantum(beta.blue));
3688 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3689 if (cache_info->active_index_channel != MagickFalse)
3690 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3697 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3732 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3741 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3743 if (*cache_info->cache_filename ==
'\0')
3744 file=AcquireUniqueFileResource(cache_info->cache_filename);
3750 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3755 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3756 O_BINARY | O_EXCL,S_MODE);
3758 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3764 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3767 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3772 return(MagickFalse);
3773 (void) AcquireMagickResource(FileResource,1);
3774 if (cache_info->file != -1)
3775 (void) ClosePixelCacheOnDisk(cache_info);
3776 cache_info->file=file;
3777 cache_info->disk_mode=mode;
3781 static inline MagickOffsetType WritePixelCacheRegion(
3782 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3783 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3791 #if !defined(MAGICKCORE_HAVE_PWRITE)
3792 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3793 return((MagickOffsetType) -1);
3795 for (i=0; i < (MagickOffsetType) length; i+=count)
3797 #if !defined(MAGICKCORE_HAVE_PWRITE)
3798 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3799 (MagickSizeType) i,MAGICK_SSIZE_MAX));
3801 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3802 (MagickSizeType) i,MAGICK_SSIZE_MAX),offset+i);
3814 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3817 *magick_restrict cache_info;
3823 if (cache_info->debug != MagickFalse)
3826 format[MaxTextExtent],
3827 message[MaxTextExtent];
3829 (void) FormatMagickSize(length,MagickFalse,format);
3830 (void) FormatLocaleString(message,MaxTextExtent,
3831 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3832 cache_info->cache_filename,cache_info->file,format);
3833 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3835 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3837 return(MagickFalse);
3838 if ((MagickSizeType) offset < length)
3844 extent=(MagickOffsetType) length-1;
3845 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3848 return(MagickFalse);
3849 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3850 if (cache_info->synchronize != MagickFalse)
3851 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3852 return(MagickFalse);
3855 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3857 return(MagickFalse);
3861 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3865 *magick_restrict cache_info,
3869 format[MaxTextExtent],
3870 message[MaxTextExtent];
3887 assert(image != (
const Image *) NULL);
3888 assert(image->signature == MagickCoreSignature);
3889 assert(image->cache != (Cache) NULL);
3890 if (IsEventLogging() != MagickFalse)
3891 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3892 if (cache_anonymous_memory < 0)
3900 cache_anonymous_memory=0;
3901 value=GetPolicyValue(
"pixel-cache-memory");
3902 if (value == (
char *) NULL)
3903 value=GetPolicyValue(
"cache:memory-map");
3904 if (LocaleCompare(value,
"anonymous") == 0)
3906 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3907 cache_anonymous_memory=1;
3909 (void) ThrowMagickException(exception,GetMagickModule(),
3910 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3911 "'%s' (policy requires anonymous memory mapping)",image->filename);
3914 value=DestroyString(value);
3916 if ((image->columns == 0) || (image->rows == 0))
3917 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3919 assert(cache_info->signature == MagickCoreSignature);
3920 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3921 ((MagickSizeType) image->rows > cache_info->height_limit))
3922 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3924 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3926 length=GetImageListLength(image);
3927 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3928 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3931 source_info=(*cache_info);
3932 source_info.file=(-1);
3933 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3934 image->filename,(
double) image->scene);
3935 cache_info->storage_class=image->storage_class;
3936 cache_info->colorspace=image->colorspace;
3937 cache_info->rows=image->rows;
3938 cache_info->columns=image->columns;
3939 cache_info->channels=image->channels;
3940 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3941 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3942 cache_info->mode=mode;
3943 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3945 if (cache_info->active_index_channel != MagickFalse)
3946 packet_size+=
sizeof(IndexPacket);
3947 length=number_pixels*packet_size;
3948 columns=(size_t) (length/cache_info->rows/packet_size);
3949 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3950 ((ssize_t) cache_info->rows < 0))
3951 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3953 cache_info->length=length;
3954 if (image->ping != MagickFalse)
3956 cache_info->type=PingCache;
3959 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3960 cache_info->columns*cache_info->rows);
3961 if (cache_info->mode == PersistMode)
3963 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3964 if ((status != MagickFalse) &&
3965 (length == (MagickSizeType) ((
size_t) length)) &&
3966 ((cache_info->type == UndefinedCache) ||
3967 (cache_info->type == MemoryCache)))
3969 status=AcquireMagickResource(MemoryResource,cache_info->length);
3970 if (status != MagickFalse)
3973 if (cache_anonymous_memory <= 0)
3975 cache_info->mapped=MagickFalse;
3976 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3977 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3981 cache_info->mapped=MagickTrue;
3982 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3983 cache_info->length);
3987 cache_info->mapped=source_info.mapped;
3988 cache_info->pixels=source_info.pixels;
3995 cache_info->colorspace=image->colorspace;
3996 cache_info->type=MemoryCache;
3997 cache_info->indexes=(IndexPacket *) NULL;
3998 if (cache_info->active_index_channel != MagickFalse)
3999 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4001 if ((source_info.storage_class != UndefinedClass) &&
4004 status&=ClonePixelCacheRepository(cache_info,&source_info,
4006 RelinquishPixelCachePixels(&source_info);
4008 if (cache_info->debug != MagickFalse)
4010 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4011 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4013 (void) FormatLocaleString(message,MaxTextExtent,
4014 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4015 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4016 type,(
double) cache_info->columns,(double) cache_info->rows,
4018 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4021 cache_info->storage_class=image->storage_class;
4024 cache_info->type=UndefinedCache;
4025 return(MagickFalse);
4031 status=AcquireMagickResource(DiskResource,cache_info->length);
4032 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4034 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4042 server_info=AcquireDistributeCacheInfo(exception);
4045 status=OpenDistributePixelCache(server_info,image);
4046 if (status == MagickFalse)
4048 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4049 GetDistributeCacheHostname(server_info));
4050 server_info=DestroyDistributeCacheInfo(server_info);
4058 cache_info->type=DistributedCache;
4059 cache_info->storage_class=image->storage_class;
4060 cache_info->colorspace=image->colorspace;
4061 cache_info->server_info=server_info;
4062 (void) FormatLocaleString(cache_info->cache_filename,
4063 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4066 cache_info->server_info));
4067 if ((source_info.storage_class != UndefinedClass) &&
4070 status=ClonePixelCacheRepository(cache_info,&source_info,
4072 RelinquishPixelCachePixels(&source_info);
4074 if (cache_info->debug != MagickFalse)
4076 (void) FormatMagickSize(cache_info->length,MagickFalse,
4078 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4080 (void) FormatLocaleString(message,MaxTextExtent,
4081 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4082 cache_info->cache_filename,GetDistributeCacheFile(
4084 (double) cache_info->columns,(
double) cache_info->rows,
4086 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4091 cache_info->type=UndefinedCache;
4092 return(MagickFalse);
4097 cache_info->type=UndefinedCache;
4098 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4099 "CacheResourcesExhausted",
"`%s'",image->filename);
4100 return(MagickFalse);
4105 if (status == MagickFalse)
4107 cache_info->type=UndefinedCache;
4108 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4109 "CacheResourcesExhausted",
"`%s'",image->filename);
4110 return(MagickFalse);
4112 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4113 (cache_info->mode != PersistMode))
4115 (void) ClosePixelCacheOnDisk(cache_info);
4116 *cache_info->cache_filename=
'\0';
4118 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4120 cache_info->type=UndefinedCache;
4121 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4123 return(MagickFalse);
4125 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4126 cache_info->length);
4127 if (status == MagickFalse)
4129 cache_info->type=UndefinedCache;
4130 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4132 return(MagickFalse);
4134 cache_info->storage_class=image->storage_class;
4135 cache_info->colorspace=image->colorspace;
4136 cache_info->type=DiskCache;
4137 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4138 if (length == (MagickSizeType) ((size_t) length))
4140 status=AcquireMagickResource(MapResource,cache_info->length);
4141 if (status != MagickFalse)
4143 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4144 cache_info->offset,(
size_t) cache_info->length);
4147 cache_info->mapped=source_info.mapped;
4148 cache_info->pixels=source_info.pixels;
4149 RelinquishMagickResource(MapResource,cache_info->length);
4156 (void) ClosePixelCacheOnDisk(cache_info);
4157 cache_info->type=MapCache;
4158 cache_info->mapped=MagickTrue;
4159 cache_info->indexes=(IndexPacket *) NULL;
4160 if (cache_info->active_index_channel != MagickFalse)
4161 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4163 if ((source_info.storage_class != UndefinedClass) &&
4166 status=ClonePixelCacheRepository(cache_info,&source_info,
4168 RelinquishPixelCachePixels(&source_info);
4170 if (cache_info->debug != MagickFalse)
4172 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4173 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4175 (void) FormatLocaleString(message,MaxTextExtent,
4176 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4177 cache_info->filename,cache_info->cache_filename,
4178 cache_info->file,type,(
double) cache_info->columns,
4179 (double) cache_info->rows,format);
4180 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4185 cache_info->type=UndefinedCache;
4186 return(MagickFalse);
4193 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4195 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4196 RelinquishPixelCachePixels(&source_info);
4198 if (cache_info->debug != MagickFalse)
4200 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4201 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4203 (void) FormatLocaleString(message,MaxTextExtent,
4204 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4205 cache_info->cache_filename,cache_info->file,type,(
double)
4206 cache_info->columns,(double) cache_info->rows,format);
4207 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4211 cache_info->type=UndefinedCache;
4212 return(MagickFalse);
4254 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4255 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4259 *magick_restrict cache_info,
4260 *magick_restrict clone_info;
4268 assert(image != (
Image *) NULL);
4269 assert(image->signature == MagickCoreSignature);
4270 if (IsEventLogging() != MagickFalse)
4271 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4272 assert(image->cache != (
void *) NULL);
4273 assert(filename != (
const char *) NULL);
4274 assert(offset != (MagickOffsetType *) NULL);
4275 page_size=GetMagickPageSize();
4277 assert(cache_info->signature == MagickCoreSignature);
4278 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4279 CopyOpenCLBuffer(cache_info);
4281 if (attach != MagickFalse)
4286 if (cache_info->debug != MagickFalse)
4287 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4288 "attach persistent cache");
4289 (void) CopyMagickString(cache_info->cache_filename,filename,
4291 cache_info->type=MapCache;
4292 cache_info->offset=(*offset);
4293 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4294 return(MagickFalse);
4295 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4296 ((MagickOffsetType) cache_info->length % page_size));
4302 status=AcquireMagickResource(DiskResource,cache_info->length);
4303 if (status == MagickFalse)
4305 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4306 "CacheResourcesExhausted",
"`%s'",image->filename);
4307 return(MagickFalse);
4309 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4310 clone_info->type=DiskCache;
4311 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4312 clone_info->file=(-1);
4313 clone_info->storage_class=cache_info->storage_class;
4314 clone_info->colorspace=cache_info->colorspace;
4315 clone_info->columns=cache_info->columns;
4316 clone_info->rows=cache_info->rows;
4317 clone_info->active_index_channel=cache_info->active_index_channel;
4318 clone_info->mode=PersistMode;
4319 clone_info->length=cache_info->length;
4320 clone_info->channels=cache_info->channels;
4321 clone_info->offset=(*offset);
4322 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4323 if (status != MagickFalse)
4324 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4325 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4326 ((MagickOffsetType) cache_info->length % page_size));
4327 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4369 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4370 const ssize_t y,
const size_t columns,
const size_t rows,
4371 const MagickBooleanType clone,
NexusInfo *nexus_info,
4374 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4379 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4383 *magick_restrict cache_info;
4392 *magick_restrict pixels;
4397 assert(image != (
const Image *) NULL);
4398 assert(image->signature == MagickCoreSignature);
4399 assert(image->cache != (Cache) NULL);
4400 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4401 if (cache_info == (Cache) NULL)
4403 assert(cache_info->signature == MagickCoreSignature);
4404 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4405 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4406 (y >= (ssize_t) cache_info->rows))
4408 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4409 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4412 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4414 offset=y*(MagickOffsetType) cache_info->columns+x;
4417 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4418 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4419 (MagickOffsetType) columns-1;
4420 if ((MagickSizeType) offset >= number_pixels)
4425 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4426 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4427 MagickTrue : MagickFalse,nexus_info,exception);
4464 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4465 const ssize_t y,
const size_t columns,
const size_t rows,
4469 *magick_restrict cache_info;
4472 id = GetOpenMPThreadId();
4474 assert(image != (
const Image *) NULL);
4475 assert(image->signature == MagickCoreSignature);
4476 assert(image->cache != (Cache) NULL);
4478 assert(cache_info->signature == MagickCoreSignature);
4479 assert(
id < (
int) cache_info->number_threads);
4480 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4481 cache_info->nexus_info[
id],exception));
4540 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4541 const ssize_t y,
const size_t columns,
const size_t rows,
4545 *magick_restrict cache_info;
4548 id = GetOpenMPThreadId();
4550 assert(image != (
Image *) NULL);
4551 assert(image->signature == MagickCoreSignature);
4552 assert(image->cache != (Cache) NULL);
4554 assert(cache_info->signature == MagickCoreSignature);
4555 if (cache_info->methods.queue_authentic_pixels_handler !=
4556 (QueueAuthenticPixelsHandler) NULL)
4557 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4559 assert(
id < (
int) cache_info->number_threads);
4560 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4561 cache_info->nexus_info[
id],exception));
4593 static inline MagickOffsetType ReadPixelCacheRegion(
4594 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4595 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4603 #if !defined(MAGICKCORE_HAVE_PREAD)
4604 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4605 return((MagickOffsetType) -1);
4607 for (i=0; i < (MagickOffsetType) length; i+=count)
4609 #if !defined(MAGICKCORE_HAVE_PREAD)
4610 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4611 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX));
4613 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4614 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX),offset+i);
4626 static MagickBooleanType ReadPixelCacheIndexes(
4647 if (cache_info->active_index_channel == MagickFalse)
4648 return(MagickFalse);
4649 if (nexus_info->authentic_pixel_cache != MagickFalse)
4651 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4652 return(MagickFalse);
4653 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4654 nexus_info->region.x;
4655 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4656 rows=nexus_info->region.height;
4658 q=nexus_info->indexes;
4660 switch (cache_info->type)
4671 if ((cache_info->columns == nexus_info->region.width) &&
4672 (extent == (MagickSizeType) ((
size_t) extent)))
4677 p=cache_info->indexes+offset;
4678 for (y=0; y < (ssize_t) rows; y++)
4680 (void) memcpy(q,p,(
size_t) length);
4681 p+=cache_info->columns;
4682 q+=nexus_info->region.width;
4691 LockSemaphoreInfo(cache_info->file_semaphore);
4692 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4694 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4695 cache_info->cache_filename);
4696 UnlockSemaphoreInfo(cache_info->file_semaphore);
4697 return(MagickFalse);
4699 if ((cache_info->columns == nexus_info->region.width) &&
4700 (extent <= MagickMaxBufferExtent))
4705 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4706 for (y=0; y < (ssize_t) rows; y++)
4708 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4709 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4710 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4711 if (count < (MagickOffsetType) length)
4713 offset+=(MagickOffsetType) cache_info->columns;
4714 q+=nexus_info->region.width;
4716 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4717 (
void) ClosePixelCacheOnDisk(cache_info);
4718 UnlockSemaphoreInfo(cache_info->file_semaphore);
4721 case DistributedCache:
4729 LockSemaphoreInfo(cache_info->file_semaphore);
4730 region=nexus_info->region;
4731 if ((cache_info->columns != nexus_info->region.width) ||
4732 (extent > MagickMaxBufferExtent))
4739 for (y=0; y < (ssize_t) rows; y++)
4742 cache_info->server_info,®ion,length,(
unsigned char *) q);
4743 if (count != (MagickOffsetType) length)
4745 q+=nexus_info->region.width;
4748 UnlockSemaphoreInfo(cache_info->file_semaphore);
4754 if (y < (ssize_t) rows)
4756 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4757 cache_info->cache_filename);
4758 return(MagickFalse);
4760 if ((cache_info->debug != MagickFalse) &&
4761 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4762 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4763 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4764 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4765 nexus_info->region.x,(
double) nexus_info->region.y);
4797 static MagickBooleanType ReadPixelCachePixels(
4818 if (nexus_info->authentic_pixel_cache != MagickFalse)
4820 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4821 return(MagickFalse);
4822 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4823 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4824 return(MagickFalse);
4825 offset+=nexus_info->region.x;
4826 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4827 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4828 return(MagickFalse);
4829 rows=nexus_info->region.height;
4831 if ((extent == 0) || ((extent/length) != rows))
4832 return(MagickFalse);
4833 q=nexus_info->pixels;
4835 switch (cache_info->type)
4846 if ((cache_info->columns == nexus_info->region.width) &&
4847 (extent == (MagickSizeType) ((
size_t) extent)))
4852 p=cache_info->pixels+offset;
4853 for (y=0; y < (ssize_t) rows; y++)
4855 (void) memcpy(q,p,(
size_t) length);
4856 p+=cache_info->columns;
4857 q+=nexus_info->region.width;
4866 LockSemaphoreInfo(cache_info->file_semaphore);
4867 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4869 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4870 cache_info->cache_filename);
4871 UnlockSemaphoreInfo(cache_info->file_semaphore);
4872 return(MagickFalse);
4874 if ((cache_info->columns == nexus_info->region.width) &&
4875 (extent <= MagickMaxBufferExtent))
4880 for (y=0; y < (ssize_t) rows; y++)
4882 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4883 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4884 if (count < (MagickOffsetType) length)
4886 offset+=(MagickOffsetType) cache_info->columns;
4887 q+=nexus_info->region.width;
4889 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4890 (
void) ClosePixelCacheOnDisk(cache_info);
4891 UnlockSemaphoreInfo(cache_info->file_semaphore);
4894 case DistributedCache:
4902 LockSemaphoreInfo(cache_info->file_semaphore);
4903 region=nexus_info->region;
4904 if ((cache_info->columns != nexus_info->region.width) ||
4905 (extent > MagickMaxBufferExtent))
4912 for (y=0; y < (ssize_t) rows; y++)
4915 cache_info->server_info,®ion,length,(
unsigned char *) q);
4916 if (count != (MagickOffsetType) length)
4918 q+=nexus_info->region.width;
4921 UnlockSemaphoreInfo(cache_info->file_semaphore);
4927 if (y < (ssize_t) rows)
4929 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4930 cache_info->cache_filename);
4931 return(MagickFalse);
4933 if ((cache_info->debug != MagickFalse) &&
4934 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4935 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4936 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4937 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4938 nexus_info->region.x,(
double) nexus_info->region.y);
4965 MagickExport Cache ReferencePixelCache(Cache cache)
4968 *magick_restrict cache_info;
4970 assert(cache != (Cache *) NULL);
4972 assert(cache_info->signature == MagickCoreSignature);
4973 LockSemaphoreInfo(cache_info->semaphore);
4974 cache_info->reference_count++;
4975 UnlockSemaphoreInfo(cache_info->semaphore);
4997 MagickPrivate
void ResetCacheAnonymousMemory(
void)
4999 cache_anonymous_memory=0;
5026 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5029 *magick_restrict cache_info;
5031 GetOneAuthenticPixelFromHandler
5032 get_one_authentic_pixel_from_handler;
5034 GetOneVirtualPixelFromHandler
5035 get_one_virtual_pixel_from_handler;
5040 assert(cache != (Cache) NULL);
5043 assert(cache_info->signature == MagickCoreSignature);
5044 if (IsEventLogging() != MagickFalse)
5045 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5046 cache_info->filename);
5047 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5048 cache_info->methods.get_virtual_pixel_handler=
5049 cache_methods->get_virtual_pixel_handler;
5050 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5051 cache_info->methods.destroy_pixel_handler=
5052 cache_methods->destroy_pixel_handler;
5053 if (cache_methods->get_virtual_indexes_from_handler !=
5054 (GetVirtualIndexesFromHandler) NULL)
5055 cache_info->methods.get_virtual_indexes_from_handler=
5056 cache_methods->get_virtual_indexes_from_handler;
5057 if (cache_methods->get_authentic_pixels_handler !=
5058 (GetAuthenticPixelsHandler) NULL)
5059 cache_info->methods.get_authentic_pixels_handler=
5060 cache_methods->get_authentic_pixels_handler;
5061 if (cache_methods->queue_authentic_pixels_handler !=
5062 (QueueAuthenticPixelsHandler) NULL)
5063 cache_info->methods.queue_authentic_pixels_handler=
5064 cache_methods->queue_authentic_pixels_handler;
5065 if (cache_methods->sync_authentic_pixels_handler !=
5066 (SyncAuthenticPixelsHandler) NULL)
5067 cache_info->methods.sync_authentic_pixels_handler=
5068 cache_methods->sync_authentic_pixels_handler;
5069 if (cache_methods->get_authentic_pixels_from_handler !=
5070 (GetAuthenticPixelsFromHandler) NULL)
5071 cache_info->methods.get_authentic_pixels_from_handler=
5072 cache_methods->get_authentic_pixels_from_handler;
5073 if (cache_methods->get_authentic_indexes_from_handler !=
5074 (GetAuthenticIndexesFromHandler) NULL)
5075 cache_info->methods.get_authentic_indexes_from_handler=
5076 cache_methods->get_authentic_indexes_from_handler;
5077 get_one_virtual_pixel_from_handler=
5078 cache_info->methods.get_one_virtual_pixel_from_handler;
5079 if (get_one_virtual_pixel_from_handler !=
5080 (GetOneVirtualPixelFromHandler) NULL)
5081 cache_info->methods.get_one_virtual_pixel_from_handler=
5082 cache_methods->get_one_virtual_pixel_from_handler;
5083 get_one_authentic_pixel_from_handler=
5084 cache_methods->get_one_authentic_pixel_from_handler;
5085 if (get_one_authentic_pixel_from_handler !=
5086 (GetOneAuthenticPixelFromHandler) NULL)
5087 cache_info->methods.get_one_authentic_pixel_from_handler=
5088 cache_methods->get_one_authentic_pixel_from_handler;
5129 static inline MagickBooleanType AcquireCacheNexusPixels(
5130 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5133 if (length != (MagickSizeType) ((
size_t) length))
5135 (void) ThrowMagickException(exception,GetMagickModule(),
5136 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5137 cache_info->filename);
5138 return(MagickFalse);
5140 nexus_info->length=0;
5141 nexus_info->mapped=MagickFalse;
5142 if (cache_anonymous_memory <= 0)
5144 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5145 AcquireAlignedMemory(1,(
size_t) length));
5147 (
void) memset(nexus_info->cache,0,(
size_t) length);
5151 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5153 nexus_info->mapped=MagickTrue;
5157 (void) ThrowMagickException(exception,GetMagickModule(),
5158 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5159 cache_info->filename);
5160 return(MagickFalse);
5162 nexus_info->length=length;
5166 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5169 if (nexus_info->length < CACHE_LINE_SIZE)
5171 if (mode == ReadMode)
5173 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5177 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5180 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5183 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5184 return(MagickFalse);
5185 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5186 return(MagickFalse);
5191 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5192 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5193 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5203 assert(cache_info != (
const CacheInfo *) NULL);
5204 assert(cache_info->signature == MagickCoreSignature);
5205 if (cache_info->type == UndefinedCache)
5207 assert(nexus_info->signature == MagickCoreSignature);
5208 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5209 if ((width == 0) || (height == 0))
5211 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5212 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5215 if (((MagickSizeType) width > cache_info->width_limit) ||
5216 ((MagickSizeType) height > cache_info->height_limit))
5218 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5219 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5222 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5223 (ValidatePixelOffset(y,height) == MagickFalse))
5225 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5226 "InvalidPixel",
"`%s'",cache_info->filename);
5229 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5230 (buffered == MagickFalse))
5232 if (((x >= 0) && (y >= 0) &&
5233 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5234 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5235 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5243 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5245 offset=y*(MagickOffsetType) cache_info->columns+x;
5246 nexus_info->pixels=cache_info->pixels+offset;
5247 nexus_info->indexes=(IndexPacket *) NULL;
5248 if (cache_info->active_index_channel != MagickFalse)
5249 nexus_info->indexes=cache_info->indexes+offset;
5250 nexus_info->region.width=width;
5251 nexus_info->region.height=height;
5252 nexus_info->region.x=x;
5253 nexus_info->region.y=y;
5254 nexus_info->authentic_pixel_cache=MagickTrue;
5255 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5256 return(nexus_info->pixels);
5262 number_pixels=(MagickSizeType) width*height;
5263 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5265 if (cache_info->active_index_channel != MagickFalse)
5266 length+=number_pixels*
sizeof(IndexPacket);
5269 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5271 if (nexus_info->length < length)
5273 RelinquishCacheNexusPixels(nexus_info);
5274 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5276 if (status == MagickFalse)
5278 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5281 nexus_info->pixels=nexus_info->cache;
5282 nexus_info->indexes=(IndexPacket *) NULL;
5283 if (cache_info->active_index_channel != MagickFalse)
5284 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5285 nexus_info->region.width=width;
5286 nexus_info->region.height=height;
5287 nexus_info->region.x=x;
5288 nexus_info->region.y=y;
5289 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5290 MagickTrue : MagickFalse;
5291 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5292 return(nexus_info->pixels);
5323 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5324 const Quantum opacity)
5327 *magick_restrict image_view;
5335 assert(image != (
Image *) NULL);
5336 assert(image->signature == MagickCoreSignature);
5337 if (IsEventLogging() != MagickFalse)
5338 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5339 assert(image->cache != (Cache) NULL);
5340 image->matte=MagickTrue;
5342 image_view=AcquireVirtualCacheView(image,&image->exception);
5343 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5344 #pragma omp parallel for schedule(static) shared(status) \
5345 magick_number_threads(image,image,image->rows,1)
5347 for (y=0; y < (ssize_t) image->rows; y++)
5355 if (status == MagickFalse)
5357 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5364 for (x=0; x < (ssize_t) image->columns; x++)
5369 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5371 image_view=DestroyCacheView(image_view);
5375 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5376 const VirtualPixelMethod virtual_pixel_method)
5379 *magick_restrict cache_info;
5384 assert(image != (
Image *) NULL);
5385 assert(image->signature == MagickCoreSignature);
5386 if (IsEventLogging() != MagickFalse)
5387 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5388 assert(image->cache != (Cache) NULL);
5390 assert(cache_info->signature == MagickCoreSignature);
5391 method=cache_info->virtual_pixel_method;
5392 cache_info->virtual_pixel_method=virtual_pixel_method;
5393 if ((image->columns != 0) && (image->rows != 0))
5394 switch (virtual_pixel_method)
5396 case BackgroundVirtualPixelMethod:
5398 if ((image->background_color.opacity != OpaqueOpacity) &&
5399 (image->matte == MagickFalse))
5400 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5401 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5402 (IsGrayColorspace(image->colorspace) != MagickFalse))
5403 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5406 case TransparentVirtualPixelMethod:
5408 if (image->matte == MagickFalse)
5409 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5418 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5442 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5447 assert(cache_info != (
CacheInfo *)NULL);
5448 if ((cache_info->type != MemoryCache) ||
5454 LockSemaphoreInfo(cache_info->semaphore);
5463 clEnv=GetDefaultOpenCLEnv();
5464 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5465 if (events != (cl_event *) NULL)
5479 context=GetOpenCLContext(clEnv);
5480 queue=AcquireOpenCLCommandQueue(clEnv);
5481 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5482 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5483 cache_info->length,event_count,events,NULL,&status);
5484 assert(pixels == cache_info->pixels);
5485 events=(cl_event *) RelinquishMagickMemory(events);
5486 RelinquishOpenCLCommandQueue(clEnv,queue);
5488 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5490 UnlockSemaphoreInfo(cache_info->semaphore);
5493 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5496 *magick_restrict cache_info;
5498 assert(image != (
Image *)NULL);
5500 CopyOpenCLBuffer(cache_info);
5533 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5537 *magick_restrict cache_info;
5545 assert(image != (
Image *) NULL);
5546 assert(image->signature == MagickCoreSignature);
5547 if (image->cache == (Cache) NULL)
5548 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5550 assert(cache_info->signature == MagickCoreSignature);
5551 if (cache_info->type == UndefinedCache)
5552 return(MagickFalse);
5553 if ((image->storage_class == DirectClass) &&
5554 (image->clip_mask != (
Image *) NULL) &&
5555 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5556 return(MagickFalse);
5557 if ((image->storage_class == DirectClass) &&
5558 (image->mask != (
Image *) NULL) &&
5559 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5560 return(MagickFalse);
5561 if (nexus_info->authentic_pixel_cache != MagickFalse)
5563 if (image->taint == MagickFalse)
5564 image->taint=MagickTrue;
5567 assert(cache_info->signature == MagickCoreSignature);
5568 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5569 if ((cache_info->active_index_channel != MagickFalse) &&
5570 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5571 return(MagickFalse);
5572 if ((status != MagickFalse) && (image->taint == MagickFalse))
5573 image->taint=MagickTrue;
5604 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5608 *magick_restrict cache_info;
5611 id = GetOpenMPThreadId();
5616 assert(image != (
Image *) NULL);
5617 assert(image->signature == MagickCoreSignature);
5618 assert(image->cache != (Cache) NULL);
5620 assert(cache_info->signature == MagickCoreSignature);
5621 assert(
id < (
int) cache_info->number_threads);
5622 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5654 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5658 *magick_restrict cache_info;
5661 id = GetOpenMPThreadId();
5666 assert(image != (
Image *) NULL);
5667 assert(image->signature == MagickCoreSignature);
5668 assert(image->cache != (Cache) NULL);
5670 assert(cache_info->signature == MagickCoreSignature);
5671 if (cache_info->methods.sync_authentic_pixels_handler !=
5672 (SyncAuthenticPixelsHandler) NULL)
5673 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5674 assert(
id < (
int) cache_info->number_threads);
5675 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5707 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5711 *magick_restrict cache_info;
5713 assert(image != (
Image *) NULL);
5715 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5716 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5747 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5767 if (cache_info->active_index_channel == MagickFalse)
5768 return(MagickFalse);
5769 if (nexus_info->authentic_pixel_cache != MagickFalse)
5771 if (nexus_info->indexes == (IndexPacket *) NULL)
5772 return(MagickFalse);
5773 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5774 return(MagickFalse);
5775 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5776 nexus_info->region.x;
5777 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5778 rows=nexus_info->region.height;
5779 extent=(MagickSizeType) length*rows;
5780 p=nexus_info->indexes;
5782 switch (cache_info->type)
5793 if ((cache_info->columns == nexus_info->region.width) &&
5794 (extent == (MagickSizeType) ((
size_t) extent)))
5799 q=cache_info->indexes+offset;
5800 for (y=0; y < (ssize_t) rows; y++)
5802 (void) memcpy(q,p,(
size_t) length);
5803 p+=nexus_info->region.width;
5804 q+=cache_info->columns;
5813 LockSemaphoreInfo(cache_info->file_semaphore);
5814 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5816 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5817 cache_info->cache_filename);
5818 UnlockSemaphoreInfo(cache_info->file_semaphore);
5819 return(MagickFalse);
5821 if ((cache_info->columns == nexus_info->region.width) &&
5822 (extent <= MagickMaxBufferExtent))
5827 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5828 for (y=0; y < (ssize_t) rows; y++)
5830 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5831 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5832 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5834 if (count < (MagickOffsetType) length)
5836 p+=nexus_info->region.width;
5837 offset+=(MagickOffsetType) cache_info->columns;
5839 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5840 (
void) ClosePixelCacheOnDisk(cache_info);
5841 UnlockSemaphoreInfo(cache_info->file_semaphore);
5844 case DistributedCache:
5852 LockSemaphoreInfo(cache_info->file_semaphore);
5853 region=nexus_info->region;
5854 if ((cache_info->columns != nexus_info->region.width) ||
5855 (extent > MagickMaxBufferExtent))
5862 for (y=0; y < (ssize_t) rows; y++)
5865 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5866 if (count != (MagickOffsetType) length)
5868 p+=nexus_info->region.width;
5871 UnlockSemaphoreInfo(cache_info->file_semaphore);
5877 if (y < (ssize_t) rows)
5879 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5880 cache_info->cache_filename);
5881 return(MagickFalse);
5883 if ((cache_info->debug != MagickFalse) &&
5884 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5885 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5886 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5887 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5888 nexus_info->region.x,(
double) nexus_info->region.y);
5920 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5940 if (nexus_info->authentic_pixel_cache != MagickFalse)
5942 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5943 return(MagickFalse);
5944 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5945 nexus_info->region.x;
5946 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5947 rows=nexus_info->region.height;
5949 p=nexus_info->pixels;
5951 switch (cache_info->type)
5962 if ((cache_info->columns == nexus_info->region.width) &&
5963 (extent == (MagickSizeType) ((
size_t) extent)))
5968 q=cache_info->pixels+offset;
5969 for (y=0; y < (ssize_t) rows; y++)
5971 (void) memcpy(q,p,(
size_t) length);
5972 p+=nexus_info->region.width;
5973 q+=cache_info->columns;
5982 LockSemaphoreInfo(cache_info->file_semaphore);
5983 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5985 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5986 cache_info->cache_filename);
5987 UnlockSemaphoreInfo(cache_info->file_semaphore);
5988 return(MagickFalse);
5990 if ((cache_info->columns == nexus_info->region.width) &&
5991 (extent <= MagickMaxBufferExtent))
5996 for (y=0; y < (ssize_t) rows; y++)
5998 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5999 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6000 if (count < (MagickOffsetType) length)
6002 p+=nexus_info->region.width;
6003 offset+=(MagickOffsetType) cache_info->columns;
6005 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6006 (
void) ClosePixelCacheOnDisk(cache_info);
6007 UnlockSemaphoreInfo(cache_info->file_semaphore);
6010 case DistributedCache:
6018 LockSemaphoreInfo(cache_info->file_semaphore);
6019 region=nexus_info->region;
6020 if ((cache_info->columns != nexus_info->region.width) ||
6021 (extent > MagickMaxBufferExtent))
6028 for (y=0; y < (ssize_t) rows; y++)
6031 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6032 if (count != (MagickOffsetType) length)
6034 p+=nexus_info->region.width;
6037 UnlockSemaphoreInfo(cache_info->file_semaphore);
6043 if (y < (ssize_t) rows)
6045 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6046 cache_info->cache_filename);
6047 return(MagickFalse);
6049 if ((cache_info->debug != MagickFalse) &&
6050 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6051 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6052 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6053 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6054 nexus_info->region.x,(
double) nexus_info->region.y);