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 (((
double) image->ttl > 0) &&
1858 (difftime(GetMagickTime(),image->timestamp) > (
double) image->ttl))
1860 (void) ThrowMagickException(exception,GetMagickModule(),
1861 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1862 return((Cache) NULL);
1864 if (cpu_throttle == MagickResourceInfinity)
1865 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1866 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1867 MagickDelay(cpu_throttle);
1868 LockSemaphoreInfo(image->semaphore);
1869 assert(image->cache != (Cache) NULL);
1871 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1872 CopyOpenCLBuffer(cache_info);
1874 destroy=MagickFalse;
1875 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1877 LockSemaphoreInfo(cache_info->semaphore);
1878 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1889 clone_image=(*image);
1890 clone_image.semaphore=AllocateSemaphoreInfo();
1891 clone_image.reference_count=1;
1892 clone_image.cache=ClonePixelCache(cache_info);
1893 clone_info=(
CacheInfo *) clone_image.cache;
1894 status=OpenPixelCache(&clone_image,IOMode,exception);
1895 if (status == MagickFalse)
1896 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1899 if (clone != MagickFalse)
1900 status=ClonePixelCacheRepository(clone_info,cache_info,
1902 if (status == MagickFalse)
1903 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1907 image->cache=clone_info;
1910 DestroySemaphoreInfo(&clone_image.semaphore);
1912 UnlockSemaphoreInfo(cache_info->semaphore);
1914 if (destroy != MagickFalse)
1915 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1916 if (status != MagickFalse)
1921 if (image->type != UndefinedType)
1922 image->type=UndefinedType;
1923 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1925 status=OpenPixelCache(image,IOMode,exception);
1927 if (cache_info->file != -1)
1928 (void) ClosePixelCacheOnDisk(cache_info);
1931 UnlockSemaphoreInfo(image->semaphore);
1932 if (status == MagickFalse)
1933 return((Cache) NULL);
1934 return(image->cache);
1961 MagickExport CacheType GetPixelCacheType(
const Image *image)
1963 return(GetImagePixelCacheType(image));
1966 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1969 *magick_restrict cache_info;
1971 assert(image != (
Image *) NULL);
1972 assert(image->signature == MagickCoreSignature);
1973 assert(image->cache != (Cache) NULL);
1975 assert(cache_info->signature == MagickCoreSignature);
1976 return(cache_info->type);
2009 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2013 *magick_restrict cache_info;
2016 *magick_restrict pixels;
2018 assert(image != (
Image *) NULL);
2019 assert(image->signature == MagickCoreSignature);
2020 assert(image->cache != (Cache) NULL);
2022 assert(cache_info->signature == MagickCoreSignature);
2023 *pixel=image->background_color;
2024 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2025 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2026 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2028 return(MagickFalse);
2064 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2068 *magick_restrict cache_info;
2071 id = GetOpenMPThreadId();
2074 *magick_restrict pixels;
2076 assert(image != (
const Image *) NULL);
2077 assert(image->signature == MagickCoreSignature);
2078 assert(image->cache != (Cache) NULL);
2080 assert(cache_info->signature == MagickCoreSignature);
2081 *pixel=image->background_color;
2082 assert(
id < (
int) cache_info->number_threads);
2083 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2084 cache_info->nexus_info[
id],exception);
2086 return(MagickFalse);
2123 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2128 *magick_restrict cache_info;
2131 id = GetOpenMPThreadId();
2134 *magick_restrict indexes;
2137 *magick_restrict pixels;
2139 assert(image != (
const Image *) NULL);
2140 assert(image->signature == MagickCoreSignature);
2141 assert(image->cache != (Cache) NULL);
2143 assert(cache_info->signature == MagickCoreSignature);
2144 assert(
id < (
int) cache_info->number_threads);
2145 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2146 1UL,1UL,cache_info->nexus_info[
id],exception);
2147 GetMagickPixelPacket(image,pixel);
2149 return(MagickFalse);
2150 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2151 SetMagickPixelPacket(image,pixels,indexes,pixel);
2190 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2191 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2195 *magick_restrict cache_info;
2198 id = GetOpenMPThreadId();
2201 *magick_restrict pixels;
2203 assert(image != (
const Image *) NULL);
2204 assert(image->signature == MagickCoreSignature);
2205 assert(image->cache != (Cache) NULL);
2207 assert(cache_info->signature == MagickCoreSignature);
2208 *pixel=image->background_color;
2209 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2210 (GetOneVirtualPixelFromHandler) NULL)
2211 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2212 virtual_pixel_method,x,y,pixel,exception));
2213 assert(
id < (
int) cache_info->number_threads);
2214 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2215 cache_info->nexus_info[
id],exception);
2217 return(MagickFalse);
2253 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2257 *magick_restrict cache_info;
2260 id = GetOpenMPThreadId();
2263 *magick_restrict pixels;
2265 assert(image != (
const Image *) NULL);
2266 assert(image->signature == MagickCoreSignature);
2267 assert(image->cache != (Cache) NULL);
2269 assert(cache_info->signature == MagickCoreSignature);
2270 *pixel=image->background_color;
2271 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2272 (GetOneVirtualPixelFromHandler) NULL)
2273 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2274 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2275 assert(
id < (
int) cache_info->number_threads);
2276 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2277 1UL,1UL,cache_info->nexus_info[
id],exception);
2279 return(MagickFalse);
2318 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2319 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2323 *magick_restrict cache_info;
2326 id = GetOpenMPThreadId();
2329 *magick_restrict pixels;
2331 assert(image != (
const Image *) NULL);
2332 assert(image->signature == MagickCoreSignature);
2333 assert(image->cache != (Cache) NULL);
2335 assert(cache_info->signature == MagickCoreSignature);
2336 assert(
id < (
int) cache_info->number_threads);
2337 *pixel=image->background_color;
2338 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2339 cache_info->nexus_info[
id],exception);
2341 return(MagickFalse);
2371 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2374 *magick_restrict cache_info;
2376 assert(cache != (Cache) NULL);
2378 assert(cache_info->signature == MagickCoreSignature);
2379 if (IsEventLogging() != MagickFalse)
2380 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2381 cache_info->filename);
2382 return(cache_info->channels);
2407 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2410 *magick_restrict cache_info;
2412 assert(cache != (Cache) NULL);
2414 assert(cache_info->signature == MagickCoreSignature);
2415 if (IsEventLogging() != MagickFalse)
2416 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2417 cache_info->filename);
2418 return(cache_info->colorspace);
2444 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2447 *magick_restrict cache_info;
2449 assert(image != (
const Image *) NULL);
2450 assert(image->signature == MagickCoreSignature);
2451 assert(image->cache != (Cache) NULL);
2453 assert(cache_info->signature == MagickCoreSignature);
2454 return(cache_info->cache_filename);
2479 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2482 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2483 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2484 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2485 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2486 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2487 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2488 cache_methods->get_authentic_indexes_from_handler=
2489 GetAuthenticIndexesFromCache;
2490 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2491 cache_methods->get_one_authentic_pixel_from_handler=
2492 GetOneAuthenticPixelFromCache;
2493 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2494 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2495 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2522 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2526 *magick_restrict cache_info;
2531 assert(cache != NULL);
2533 assert(cache_info->signature == MagickCoreSignature);
2534 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2536 return((MagickSizeType) cache_info->columns*cache_info->rows);
2567 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2571 *magick_restrict cache_info;
2573 assert(image != (
const Image *) NULL);
2574 assert(image->signature == MagickCoreSignature);
2575 assert(image->cache != (Cache) NULL);
2576 assert(length != (MagickSizeType *) NULL);
2578 assert(exception->signature == MagickCoreSignature);
2580 assert(cache_info->signature == MagickCoreSignature);
2582 *length=cache_info->length;
2583 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2584 return((
void *) NULL);
2585 return((
void *) cache_info->pixels);
2612 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2615 *magick_restrict cache_info;
2617 assert(cache != (Cache) NULL);
2619 assert(cache_info->signature == MagickCoreSignature);
2620 if (IsEventLogging() != MagickFalse)
2621 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2622 cache_info->filename);
2623 return(cache_info->storage_class);
2653 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2656 assert(image != (
Image *) NULL);
2657 assert(image->signature == MagickCoreSignature);
2658 if (IsEventLogging() != MagickFalse)
2659 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2661 if (GetImagePixelCacheType(image) == DiskCache)
2690 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2693 *magick_restrict cache_info;
2695 assert(image != (
Image *) NULL);
2696 assert(image->signature == MagickCoreSignature);
2697 assert(image->cache != (Cache) NULL);
2699 assert(cache_info->signature == MagickCoreSignature);
2700 return(cache_info->virtual_pixel_method);
2726 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2729 *magick_restrict cache_info;
2732 id = GetOpenMPThreadId();
2734 assert(image != (
const Image *) NULL);
2735 assert(image->signature == MagickCoreSignature);
2736 assert(image->cache != (Cache) NULL);
2738 assert(cache_info->signature == MagickCoreSignature);
2739 assert(
id < (
int) cache_info->number_threads);
2740 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2769 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2773 *magick_restrict cache_info;
2775 assert(cache != (Cache) NULL);
2777 assert(cache_info->signature == MagickCoreSignature);
2778 if (cache_info->storage_class == UndefinedClass)
2779 return((IndexPacket *) NULL);
2780 return(nexus_info->indexes);
2808 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2811 *magick_restrict cache_info;
2814 id = GetOpenMPThreadId();
2816 assert(image != (
const Image *) NULL);
2817 assert(image->signature == MagickCoreSignature);
2818 assert(image->cache != (Cache) NULL);
2820 assert(cache_info->signature == MagickCoreSignature);
2821 if (cache_info->methods.get_virtual_indexes_from_handler !=
2822 (GetVirtualIndexesFromHandler) NULL)
2827 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2828 if (indexes != (IndexPacket *) NULL)
2831 assert(
id < (
int) cache_info->number_threads);
2832 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2875 0, 48, 12, 60, 3, 51, 15, 63,
2876 32, 16, 44, 28, 35, 19, 47, 31,
2877 8, 56, 4, 52, 11, 59, 7, 55,
2878 40, 24, 36, 20, 43, 27, 39, 23,
2879 2, 50, 14, 62, 1, 49, 13, 61,
2880 34, 18, 46, 30, 33, 17, 45, 29,
2881 10, 58, 6, 54, 9, 57, 5, 53,
2882 42, 26, 38, 22, 41, 25, 37, 21
2885 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2890 index=x+DitherMatrix[x & 0x07]-32L;
2893 if (index >= (ssize_t) columns)
2894 return((ssize_t) columns-1L);
2898 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2903 index=y+DitherMatrix[y & 0x07]-32L;
2906 if (index >= (ssize_t) rows)
2907 return((ssize_t) rows-1L);
2911 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2915 if (x >= (ssize_t) columns)
2916 return((ssize_t) (columns-1));
2920 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2924 if (y >= (ssize_t) rows)
2925 return((ssize_t) (rows-1));
2929 static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2932 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2933 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2934 return(MagickFalse);
2938 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2940 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2943 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2945 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2948 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2949 const size_t extent)
2954 modulo.quotient=offset;
2958 modulo.quotient=offset/((ssize_t) extent);
2959 modulo.remainder=offset % ((ssize_t) extent);
2961 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2964 modulo.remainder+=((ssize_t) extent);
2969 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2970 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2971 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2975 *magick_restrict cache_info;
2978 *magick_restrict virtual_indexes;
2985 *magick_restrict indexes;
2995 *magick_restrict virtual_nexus;
2998 *magick_restrict pixels,
3009 assert(image != (
const Image *) NULL);
3010 assert(image->signature == MagickCoreSignature);
3011 assert(image->cache != (Cache) NULL);
3013 assert(cache_info->signature == MagickCoreSignature);
3014 if (cache_info->type == UndefinedCache)
3016 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3017 CopyOpenCLBuffer(cache_info);
3019 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3020 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3021 MagickTrue : MagickFalse,nexus_info,exception);
3024 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3026 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3027 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3029 offset+=nexus_info->region.x;
3030 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3031 nexus_info->region.width-1L;
3032 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3033 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3034 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3035 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3043 if (nexus_info->authentic_pixel_cache != MagickFalse)
3045 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3046 if (status == MagickFalse)
3048 if ((cache_info->storage_class == PseudoClass) ||
3049 (cache_info->colorspace == CMYKColorspace))
3051 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3052 if (status == MagickFalse)
3060 virtual_nexus=nexus_info->virtual_nexus;
3062 indexes=nexus_info->indexes;
3063 switch (virtual_pixel_method)
3065 case BlackVirtualPixelMethod:
3067 SetPixelRed(&virtual_pixel,0);
3068 SetPixelGreen(&virtual_pixel,0);
3069 SetPixelBlue(&virtual_pixel,0);
3070 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3073 case GrayVirtualPixelMethod:
3075 SetPixelRed(&virtual_pixel,QuantumRange/2);
3076 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3077 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3078 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3081 case TransparentVirtualPixelMethod:
3083 SetPixelRed(&virtual_pixel,0);
3084 SetPixelGreen(&virtual_pixel,0);
3085 SetPixelBlue(&virtual_pixel,0);
3086 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3089 case MaskVirtualPixelMethod:
3090 case WhiteVirtualPixelMethod:
3092 SetPixelRed(&virtual_pixel,QuantumRange);
3093 SetPixelGreen(&virtual_pixel,QuantumRange);
3094 SetPixelBlue(&virtual_pixel,QuantumRange);
3095 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3100 virtual_pixel=image->background_color;
3104 virtual_index=(IndexPacket) 0;
3105 for (v=0; v < (ssize_t) rows; v++)
3111 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3112 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3113 y_offset=EdgeY(y_offset,cache_info->rows);
3114 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3120 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3121 (ssize_t) columns-u);
3122 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3123 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3133 length=(MagickSizeType) 1;
3134 switch (virtual_pixel_method)
3136 case BackgroundVirtualPixelMethod:
3137 case ConstantVirtualPixelMethod:
3138 case BlackVirtualPixelMethod:
3139 case GrayVirtualPixelMethod:
3140 case TransparentVirtualPixelMethod:
3141 case MaskVirtualPixelMethod:
3142 case WhiteVirtualPixelMethod:
3145 virtual_indexes=(&virtual_index);
3148 case EdgeVirtualPixelMethod:
3151 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3152 EdgeX(x_offset,cache_info->columns),
3153 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3155 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3159 case RandomVirtualPixelMethod:
3161 if (cache_info->random_info == (
RandomInfo *) NULL)
3162 cache_info->random_info=AcquireRandomInfo();
3163 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3164 RandomX(cache_info->random_info,cache_info->columns),
3165 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3166 virtual_nexus,exception);
3167 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3171 case DitherVirtualPixelMethod:
3173 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3174 DitherX(x_offset,cache_info->columns),
3175 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3177 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3181 case TileVirtualPixelMethod:
3183 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3184 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3185 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3186 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3188 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3192 case MirrorVirtualPixelMethod:
3194 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3195 if ((x_modulo.quotient & 0x01) == 1L)
3196 x_modulo.remainder=(ssize_t) cache_info->columns-
3197 x_modulo.remainder-1L;
3198 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3199 if ((y_modulo.quotient & 0x01) == 1L)
3200 y_modulo.remainder=(ssize_t) cache_info->rows-
3201 y_modulo.remainder-1L;
3202 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3203 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3205 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3209 case CheckerTileVirtualPixelMethod:
3211 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3212 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3213 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3216 virtual_indexes=(&virtual_index);
3219 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3220 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3222 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3226 case HorizontalTileVirtualPixelMethod:
3228 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3231 virtual_indexes=(&virtual_index);
3234 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3235 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3236 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3237 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3239 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3243 case VerticalTileVirtualPixelMethod:
3245 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3248 virtual_indexes=(&virtual_index);
3251 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3252 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3253 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3254 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3256 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3260 case HorizontalTileEdgeVirtualPixelMethod:
3262 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3263 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3264 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3265 virtual_nexus,exception);
3266 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3270 case VerticalTileEdgeVirtualPixelMethod:
3272 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3273 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3274 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3275 virtual_nexus,exception);
3276 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3284 if ((indexes != (IndexPacket *) NULL) &&
3285 (virtual_indexes != (
const IndexPacket *) NULL))
3286 *indexes++=(*virtual_indexes);
3292 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3293 (
size_t) length,1UL,virtual_nexus,exception);
3296 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3297 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3299 if ((indexes != (IndexPacket *) NULL) &&
3300 (virtual_indexes != (
const IndexPacket *) NULL))
3302 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3303 sizeof(*virtual_indexes));
3307 if (u < (ssize_t) columns)
3313 if (v < (ssize_t) rows)
3353 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3354 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3357 *magick_restrict cache_info;
3360 id = GetOpenMPThreadId();
3362 assert(image != (
const Image *) NULL);
3363 assert(image->signature == MagickCoreSignature);
3364 assert(image->cache != (Cache) NULL);
3366 assert(cache_info->signature == MagickCoreSignature);
3367 assert(
id < (
int) cache_info->number_threads);
3368 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3369 cache_info->nexus_info[
id],exception));
3398 *magick_restrict cache_info;
3401 id = GetOpenMPThreadId();
3403 assert(image != (
const Image *) NULL);
3404 assert(image->signature == MagickCoreSignature);
3405 assert(image->cache != (Cache) NULL);
3407 assert(cache_info->signature == MagickCoreSignature);
3408 if (cache_info->methods.get_virtual_pixels_handler !=
3409 (GetVirtualPixelsHandler) NULL)
3410 return(cache_info->methods.get_virtual_pixels_handler(image));
3411 assert(
id < (
int) cache_info->number_threads);
3412 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3464 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3468 *magick_restrict cache_info;
3471 id = GetOpenMPThreadId();
3473 assert(image != (
const Image *) NULL);
3474 assert(image->signature == MagickCoreSignature);
3475 assert(image->cache != (Cache) NULL);
3477 assert(cache_info->signature == MagickCoreSignature);
3478 if (cache_info->methods.get_virtual_pixel_handler !=
3479 (GetVirtualPixelHandler) NULL)
3480 return(cache_info->methods.get_virtual_pixel_handler(image,
3481 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3482 assert(
id < (
int) cache_info->number_threads);
3483 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3484 columns,rows,cache_info->nexus_info[
id],exception));
3513 *magick_restrict cache_info;
3516 id = GetOpenMPThreadId();
3518 assert(image != (
const Image *) NULL);
3519 assert(image->signature == MagickCoreSignature);
3520 assert(image->cache != (Cache) NULL);
3522 assert(cache_info->signature == MagickCoreSignature);
3523 assert(
id < (
int) cache_info->number_threads);
3524 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3553 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3557 *magick_restrict cache_info;
3559 assert(cache != (Cache) NULL);
3561 assert(cache_info->signature == MagickCoreSignature);
3562 if (cache_info->storage_class == UndefinedClass)
3604 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3609 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3610 gamma=PerceptibleReciprocal(gamma);
3611 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3612 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3613 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3614 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3615 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3618 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3622 *magick_restrict cache_info;
3628 *magick_restrict nexus_indexes,
3629 *magick_restrict indexes;
3639 **magick_restrict mask_nexus;
3651 if (IsEventLogging() != MagickFalse)
3652 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3653 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3655 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3658 if (cache_info == (Cache) NULL)
3659 return(MagickFalse);
3660 mask_nexus=AcquirePixelCacheNexus(1);
3661 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3662 nexus_info->virtual_nexus,exception);
3663 indexes=nexus_info->virtual_nexus->indexes;
3664 q=nexus_info->pixels;
3665 nexus_indexes=nexus_info->indexes;
3666 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3667 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3668 nexus_info->region.height,mask_nexus[0],&image->exception);
3671 return(MagickFalse);
3673 GetMagickPixelPacket(image,&alpha);
3674 GetMagickPixelPacket(image,&beta);
3675 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3680 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3682 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3683 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3684 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3685 alpha.opacity,&beta);
3686 SetPixelRed(q,ClampToQuantum(beta.red));
3687 SetPixelGreen(q,ClampToQuantum(beta.green));
3688 SetPixelBlue(q,ClampToQuantum(beta.blue));
3689 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3690 if (cache_info->active_index_channel != MagickFalse)
3691 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3698 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3733 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3742 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3744 if (*cache_info->cache_filename ==
'\0')
3745 file=AcquireUniqueFileResource(cache_info->cache_filename);
3751 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3756 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3757 O_BINARY | O_EXCL,S_MODE);
3759 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3765 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3768 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3773 return(MagickFalse);
3774 (void) AcquireMagickResource(FileResource,1);
3775 if (cache_info->file != -1)
3776 (void) ClosePixelCacheOnDisk(cache_info);
3777 cache_info->file=file;
3778 cache_info->disk_mode=mode;
3782 static inline MagickOffsetType WritePixelCacheRegion(
3783 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3784 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3792 #if !defined(MAGICKCORE_HAVE_PWRITE)
3793 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3794 return((MagickOffsetType) -1);
3796 for (i=0; i < (MagickOffsetType) length; i+=count)
3798 #if !defined(MAGICKCORE_HAVE_PWRITE)
3799 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3800 (MagickSizeType) i,MAGICK_SSIZE_MAX));
3802 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3803 (MagickSizeType) i,MAGICK_SSIZE_MAX),offset+i);
3815 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3818 *magick_restrict cache_info;
3824 if (cache_info->debug != MagickFalse)
3827 format[MaxTextExtent],
3828 message[MaxTextExtent];
3830 (void) FormatMagickSize(length,MagickFalse,format);
3831 (void) FormatLocaleString(message,MaxTextExtent,
3832 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3833 cache_info->cache_filename,cache_info->file,format);
3834 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3836 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3838 return(MagickFalse);
3839 if ((MagickSizeType) offset < length)
3845 extent=(MagickOffsetType) length-1;
3846 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3849 return(MagickFalse);
3850 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3851 if (cache_info->synchronize != MagickFalse)
3852 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3853 return(MagickFalse);
3856 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3858 return(MagickFalse);
3862 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3866 *magick_restrict cache_info,
3870 format[MaxTextExtent],
3871 message[MaxTextExtent];
3888 assert(image != (
const Image *) NULL);
3889 assert(image->signature == MagickCoreSignature);
3890 assert(image->cache != (Cache) NULL);
3891 if (IsEventLogging() != MagickFalse)
3892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3893 if (cache_anonymous_memory < 0)
3901 cache_anonymous_memory=0;
3902 value=GetPolicyValue(
"pixel-cache-memory");
3903 if (value == (
char *) NULL)
3904 value=GetPolicyValue(
"cache:memory-map");
3905 if (LocaleCompare(value,
"anonymous") == 0)
3907 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3908 cache_anonymous_memory=1;
3910 (void) ThrowMagickException(exception,GetMagickModule(),
3911 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3912 "'%s' (policy requires anonymous memory mapping)",image->filename);
3915 value=DestroyString(value);
3917 if ((image->columns == 0) || (image->rows == 0))
3918 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3920 assert(cache_info->signature == MagickCoreSignature);
3921 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3922 ((MagickSizeType) image->rows > cache_info->height_limit))
3923 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3925 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3927 length=GetImageListLength(image);
3928 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3929 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3932 source_info=(*cache_info);
3933 source_info.file=(-1);
3934 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3935 image->filename,(
double) image->scene);
3936 cache_info->storage_class=image->storage_class;
3937 cache_info->colorspace=image->colorspace;
3938 cache_info->rows=image->rows;
3939 cache_info->columns=image->columns;
3940 cache_info->channels=image->channels;
3941 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3942 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3943 cache_info->mode=mode;
3944 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3946 if (cache_info->active_index_channel != MagickFalse)
3947 packet_size+=
sizeof(IndexPacket);
3948 length=number_pixels*packet_size;
3949 columns=(size_t) (length/cache_info->rows/packet_size);
3950 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3951 ((ssize_t) cache_info->rows < 0))
3952 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3954 cache_info->length=length;
3955 if (image->ping != MagickFalse)
3957 cache_info->type=PingCache;
3960 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3961 cache_info->columns*cache_info->rows);
3962 if (cache_info->mode == PersistMode)
3964 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3965 if ((status != MagickFalse) &&
3966 (length == (MagickSizeType) ((
size_t) length)) &&
3967 ((cache_info->type == UndefinedCache) ||
3968 (cache_info->type == MemoryCache)))
3970 status=AcquireMagickResource(MemoryResource,cache_info->length);
3971 if (status != MagickFalse)
3974 if (cache_anonymous_memory <= 0)
3976 cache_info->mapped=MagickFalse;
3977 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3978 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3982 cache_info->mapped=MagickTrue;
3983 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3984 cache_info->length);
3988 cache_info->mapped=source_info.mapped;
3989 cache_info->pixels=source_info.pixels;
3996 cache_info->colorspace=image->colorspace;
3997 cache_info->type=MemoryCache;
3998 cache_info->indexes=(IndexPacket *) NULL;
3999 if (cache_info->active_index_channel != MagickFalse)
4000 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4002 if ((source_info.storage_class != UndefinedClass) &&
4005 status&=ClonePixelCacheRepository(cache_info,&source_info,
4007 RelinquishPixelCachePixels(&source_info);
4009 if (cache_info->debug != MagickFalse)
4011 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4012 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4014 (void) FormatLocaleString(message,MaxTextExtent,
4015 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4016 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4017 type,(
double) cache_info->columns,(double) cache_info->rows,
4019 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4022 cache_info->storage_class=image->storage_class;
4025 cache_info->type=UndefinedCache;
4026 return(MagickFalse);
4032 status=AcquireMagickResource(DiskResource,cache_info->length);
4033 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4035 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4043 server_info=AcquireDistributeCacheInfo(exception);
4046 status=OpenDistributePixelCache(server_info,image);
4047 if (status == MagickFalse)
4049 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4050 GetDistributeCacheHostname(server_info));
4051 server_info=DestroyDistributeCacheInfo(server_info);
4059 cache_info->type=DistributedCache;
4060 cache_info->storage_class=image->storage_class;
4061 cache_info->colorspace=image->colorspace;
4062 cache_info->server_info=server_info;
4063 (void) FormatLocaleString(cache_info->cache_filename,
4064 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4067 cache_info->server_info));
4068 if ((source_info.storage_class != UndefinedClass) &&
4071 status=ClonePixelCacheRepository(cache_info,&source_info,
4073 RelinquishPixelCachePixels(&source_info);
4075 if (cache_info->debug != MagickFalse)
4077 (void) FormatMagickSize(cache_info->length,MagickFalse,
4079 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4081 (void) FormatLocaleString(message,MaxTextExtent,
4082 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4083 cache_info->cache_filename,GetDistributeCacheFile(
4085 (double) cache_info->columns,(
double) cache_info->rows,
4087 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4092 cache_info->type=UndefinedCache;
4093 return(MagickFalse);
4098 cache_info->type=UndefinedCache;
4099 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4100 "CacheResourcesExhausted",
"`%s'",image->filename);
4101 return(MagickFalse);
4106 if (status == MagickFalse)
4108 cache_info->type=UndefinedCache;
4109 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4110 "CacheResourcesExhausted",
"`%s'",image->filename);
4111 return(MagickFalse);
4113 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4114 (cache_info->mode != PersistMode))
4116 (void) ClosePixelCacheOnDisk(cache_info);
4117 *cache_info->cache_filename=
'\0';
4119 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4121 cache_info->type=UndefinedCache;
4122 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4124 return(MagickFalse);
4126 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4127 cache_info->length);
4128 if (status == MagickFalse)
4130 cache_info->type=UndefinedCache;
4131 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4133 return(MagickFalse);
4135 cache_info->storage_class=image->storage_class;
4136 cache_info->colorspace=image->colorspace;
4137 cache_info->type=DiskCache;
4138 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4139 if (length == (MagickSizeType) ((size_t) length))
4141 status=AcquireMagickResource(MapResource,cache_info->length);
4142 if (status != MagickFalse)
4144 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4145 cache_info->offset,(
size_t) cache_info->length);
4148 cache_info->mapped=source_info.mapped;
4149 cache_info->pixels=source_info.pixels;
4150 RelinquishMagickResource(MapResource,cache_info->length);
4157 (void) ClosePixelCacheOnDisk(cache_info);
4158 cache_info->type=MapCache;
4159 cache_info->mapped=MagickTrue;
4160 cache_info->indexes=(IndexPacket *) NULL;
4161 if (cache_info->active_index_channel != MagickFalse)
4162 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4164 if ((source_info.storage_class != UndefinedClass) &&
4167 status=ClonePixelCacheRepository(cache_info,&source_info,
4169 RelinquishPixelCachePixels(&source_info);
4171 if (cache_info->debug != MagickFalse)
4173 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4174 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4176 (void) FormatLocaleString(message,MaxTextExtent,
4177 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4178 cache_info->filename,cache_info->cache_filename,
4179 cache_info->file,type,(
double) cache_info->columns,
4180 (double) cache_info->rows,format);
4181 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4186 cache_info->type=UndefinedCache;
4187 return(MagickFalse);
4194 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4196 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4197 RelinquishPixelCachePixels(&source_info);
4199 if (cache_info->debug != MagickFalse)
4201 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4202 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4204 (void) FormatLocaleString(message,MaxTextExtent,
4205 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4206 cache_info->cache_filename,cache_info->file,type,(
double)
4207 cache_info->columns,(double) cache_info->rows,format);
4208 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4212 cache_info->type=UndefinedCache;
4213 return(MagickFalse);
4255 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4256 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4260 *magick_restrict cache_info,
4261 *magick_restrict clone_info;
4269 assert(image != (
Image *) NULL);
4270 assert(image->signature == MagickCoreSignature);
4271 if (IsEventLogging() != MagickFalse)
4272 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4273 assert(image->cache != (
void *) NULL);
4274 assert(filename != (
const char *) NULL);
4275 assert(offset != (MagickOffsetType *) NULL);
4276 page_size=GetMagickPageSize();
4278 assert(cache_info->signature == MagickCoreSignature);
4279 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4280 CopyOpenCLBuffer(cache_info);
4282 if (attach != MagickFalse)
4287 if (cache_info->debug != MagickFalse)
4288 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4289 "attach persistent cache");
4290 (void) CopyMagickString(cache_info->cache_filename,filename,
4292 cache_info->type=MapCache;
4293 cache_info->offset=(*offset);
4294 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4295 return(MagickFalse);
4296 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4297 ((MagickOffsetType) cache_info->length % page_size));
4303 status=AcquireMagickResource(DiskResource,cache_info->length);
4304 if (status == MagickFalse)
4306 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4307 "CacheResourcesExhausted",
"`%s'",image->filename);
4308 return(MagickFalse);
4310 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4311 clone_info->type=DiskCache;
4312 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4313 clone_info->file=(-1);
4314 clone_info->storage_class=cache_info->storage_class;
4315 clone_info->colorspace=cache_info->colorspace;
4316 clone_info->columns=cache_info->columns;
4317 clone_info->rows=cache_info->rows;
4318 clone_info->active_index_channel=cache_info->active_index_channel;
4319 clone_info->mode=PersistMode;
4320 clone_info->length=cache_info->length;
4321 clone_info->channels=cache_info->channels;
4322 clone_info->offset=(*offset);
4323 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4324 if (status != MagickFalse)
4325 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4326 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4327 ((MagickOffsetType) cache_info->length % page_size));
4328 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4370 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4371 const ssize_t y,
const size_t columns,
const size_t rows,
4372 const MagickBooleanType clone,
NexusInfo *nexus_info,
4375 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4380 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4384 *magick_restrict cache_info;
4393 *magick_restrict pixels;
4398 assert(image != (
const Image *) NULL);
4399 assert(image->signature == MagickCoreSignature);
4400 assert(image->cache != (Cache) NULL);
4401 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4402 if (cache_info == (Cache) NULL)
4404 assert(cache_info->signature == MagickCoreSignature);
4405 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4406 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4407 (y >= (ssize_t) cache_info->rows))
4409 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4410 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4413 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4415 offset=y*(MagickOffsetType) cache_info->columns+x;
4418 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4419 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4420 (MagickOffsetType) columns-1;
4421 if ((MagickSizeType) offset >= number_pixels)
4426 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4427 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4428 MagickTrue : MagickFalse,nexus_info,exception);
4465 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4466 const ssize_t y,
const size_t columns,
const size_t rows,
4470 *magick_restrict cache_info;
4473 id = GetOpenMPThreadId();
4475 assert(image != (
const Image *) NULL);
4476 assert(image->signature == MagickCoreSignature);
4477 assert(image->cache != (Cache) NULL);
4479 assert(cache_info->signature == MagickCoreSignature);
4480 assert(
id < (
int) cache_info->number_threads);
4481 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4482 cache_info->nexus_info[
id],exception));
4541 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4542 const ssize_t y,
const size_t columns,
const size_t rows,
4546 *magick_restrict cache_info;
4549 id = GetOpenMPThreadId();
4551 assert(image != (
Image *) NULL);
4552 assert(image->signature == MagickCoreSignature);
4553 assert(image->cache != (Cache) NULL);
4555 assert(cache_info->signature == MagickCoreSignature);
4556 if (cache_info->methods.queue_authentic_pixels_handler !=
4557 (QueueAuthenticPixelsHandler) NULL)
4558 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4560 assert(
id < (
int) cache_info->number_threads);
4561 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4562 cache_info->nexus_info[
id],exception));
4594 static inline MagickOffsetType ReadPixelCacheRegion(
4595 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4596 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4604 #if !defined(MAGICKCORE_HAVE_PREAD)
4605 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4606 return((MagickOffsetType) -1);
4608 for (i=0; i < (MagickOffsetType) length; i+=count)
4610 #if !defined(MAGICKCORE_HAVE_PREAD)
4611 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4612 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX));
4614 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4615 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX),offset+i);
4627 static MagickBooleanType ReadPixelCacheIndexes(
4648 if (cache_info->active_index_channel == MagickFalse)
4649 return(MagickFalse);
4650 if (nexus_info->authentic_pixel_cache != MagickFalse)
4652 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4653 return(MagickFalse);
4654 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4655 nexus_info->region.x;
4656 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4657 rows=nexus_info->region.height;
4659 q=nexus_info->indexes;
4661 switch (cache_info->type)
4672 if ((cache_info->columns == nexus_info->region.width) &&
4673 (extent == (MagickSizeType) ((
size_t) extent)))
4678 p=cache_info->indexes+offset;
4679 for (y=0; y < (ssize_t) rows; y++)
4681 (void) memcpy(q,p,(
size_t) length);
4682 p+=cache_info->columns;
4683 q+=nexus_info->region.width;
4692 LockSemaphoreInfo(cache_info->file_semaphore);
4693 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4695 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4696 cache_info->cache_filename);
4697 UnlockSemaphoreInfo(cache_info->file_semaphore);
4698 return(MagickFalse);
4700 if ((cache_info->columns == nexus_info->region.width) &&
4701 (extent <= MagickMaxBufferExtent))
4706 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4707 for (y=0; y < (ssize_t) rows; y++)
4709 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4710 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4711 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4712 if (count < (MagickOffsetType) length)
4714 offset+=(MagickOffsetType) cache_info->columns;
4715 q+=nexus_info->region.width;
4717 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4718 (
void) ClosePixelCacheOnDisk(cache_info);
4719 UnlockSemaphoreInfo(cache_info->file_semaphore);
4722 case DistributedCache:
4730 LockSemaphoreInfo(cache_info->file_semaphore);
4731 region=nexus_info->region;
4732 if ((cache_info->columns != nexus_info->region.width) ||
4733 (extent > MagickMaxBufferExtent))
4740 for (y=0; y < (ssize_t) rows; y++)
4743 cache_info->server_info,®ion,length,(
unsigned char *) q);
4744 if (count != (MagickOffsetType) length)
4746 q+=nexus_info->region.width;
4749 UnlockSemaphoreInfo(cache_info->file_semaphore);
4755 if (y < (ssize_t) rows)
4757 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4758 cache_info->cache_filename);
4759 return(MagickFalse);
4761 if ((cache_info->debug != MagickFalse) &&
4762 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4763 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4764 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4765 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4766 nexus_info->region.x,(
double) nexus_info->region.y);
4798 static MagickBooleanType ReadPixelCachePixels(
4819 if (nexus_info->authentic_pixel_cache != MagickFalse)
4821 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4822 return(MagickFalse);
4823 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4824 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4825 return(MagickFalse);
4826 offset+=nexus_info->region.x;
4827 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4828 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4829 return(MagickFalse);
4830 rows=nexus_info->region.height;
4832 if ((extent == 0) || ((extent/length) != rows))
4833 return(MagickFalse);
4834 q=nexus_info->pixels;
4836 switch (cache_info->type)
4847 if ((cache_info->columns == nexus_info->region.width) &&
4848 (extent == (MagickSizeType) ((
size_t) extent)))
4853 p=cache_info->pixels+offset;
4854 for (y=0; y < (ssize_t) rows; y++)
4856 (void) memcpy(q,p,(
size_t) length);
4857 p+=cache_info->columns;
4858 q+=nexus_info->region.width;
4867 LockSemaphoreInfo(cache_info->file_semaphore);
4868 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4870 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4871 cache_info->cache_filename);
4872 UnlockSemaphoreInfo(cache_info->file_semaphore);
4873 return(MagickFalse);
4875 if ((cache_info->columns == nexus_info->region.width) &&
4876 (extent <= MagickMaxBufferExtent))
4881 for (y=0; y < (ssize_t) rows; y++)
4883 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4884 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4885 if (count < (MagickOffsetType) length)
4887 offset+=(MagickOffsetType) cache_info->columns;
4888 q+=nexus_info->region.width;
4890 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4891 (
void) ClosePixelCacheOnDisk(cache_info);
4892 UnlockSemaphoreInfo(cache_info->file_semaphore);
4895 case DistributedCache:
4903 LockSemaphoreInfo(cache_info->file_semaphore);
4904 region=nexus_info->region;
4905 if ((cache_info->columns != nexus_info->region.width) ||
4906 (extent > MagickMaxBufferExtent))
4913 for (y=0; y < (ssize_t) rows; y++)
4916 cache_info->server_info,®ion,length,(
unsigned char *) q);
4917 if (count != (MagickOffsetType) length)
4919 q+=nexus_info->region.width;
4922 UnlockSemaphoreInfo(cache_info->file_semaphore);
4928 if (y < (ssize_t) rows)
4930 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4931 cache_info->cache_filename);
4932 return(MagickFalse);
4934 if ((cache_info->debug != MagickFalse) &&
4935 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4936 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4937 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4938 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4939 nexus_info->region.x,(
double) nexus_info->region.y);
4966 MagickExport Cache ReferencePixelCache(Cache cache)
4969 *magick_restrict cache_info;
4971 assert(cache != (Cache *) NULL);
4973 assert(cache_info->signature == MagickCoreSignature);
4974 LockSemaphoreInfo(cache_info->semaphore);
4975 cache_info->reference_count++;
4976 UnlockSemaphoreInfo(cache_info->semaphore);
4998 MagickPrivate
void ResetCacheAnonymousMemory(
void)
5000 cache_anonymous_memory=0;
5027 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5030 *magick_restrict cache_info;
5032 GetOneAuthenticPixelFromHandler
5033 get_one_authentic_pixel_from_handler;
5035 GetOneVirtualPixelFromHandler
5036 get_one_virtual_pixel_from_handler;
5041 assert(cache != (Cache) NULL);
5044 assert(cache_info->signature == MagickCoreSignature);
5045 if (IsEventLogging() != MagickFalse)
5046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5047 cache_info->filename);
5048 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5049 cache_info->methods.get_virtual_pixel_handler=
5050 cache_methods->get_virtual_pixel_handler;
5051 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5052 cache_info->methods.destroy_pixel_handler=
5053 cache_methods->destroy_pixel_handler;
5054 if (cache_methods->get_virtual_indexes_from_handler !=
5055 (GetVirtualIndexesFromHandler) NULL)
5056 cache_info->methods.get_virtual_indexes_from_handler=
5057 cache_methods->get_virtual_indexes_from_handler;
5058 if (cache_methods->get_authentic_pixels_handler !=
5059 (GetAuthenticPixelsHandler) NULL)
5060 cache_info->methods.get_authentic_pixels_handler=
5061 cache_methods->get_authentic_pixels_handler;
5062 if (cache_methods->queue_authentic_pixels_handler !=
5063 (QueueAuthenticPixelsHandler) NULL)
5064 cache_info->methods.queue_authentic_pixels_handler=
5065 cache_methods->queue_authentic_pixels_handler;
5066 if (cache_methods->sync_authentic_pixels_handler !=
5067 (SyncAuthenticPixelsHandler) NULL)
5068 cache_info->methods.sync_authentic_pixels_handler=
5069 cache_methods->sync_authentic_pixels_handler;
5070 if (cache_methods->get_authentic_pixels_from_handler !=
5071 (GetAuthenticPixelsFromHandler) NULL)
5072 cache_info->methods.get_authentic_pixels_from_handler=
5073 cache_methods->get_authentic_pixels_from_handler;
5074 if (cache_methods->get_authentic_indexes_from_handler !=
5075 (GetAuthenticIndexesFromHandler) NULL)
5076 cache_info->methods.get_authentic_indexes_from_handler=
5077 cache_methods->get_authentic_indexes_from_handler;
5078 get_one_virtual_pixel_from_handler=
5079 cache_info->methods.get_one_virtual_pixel_from_handler;
5080 if (get_one_virtual_pixel_from_handler !=
5081 (GetOneVirtualPixelFromHandler) NULL)
5082 cache_info->methods.get_one_virtual_pixel_from_handler=
5083 cache_methods->get_one_virtual_pixel_from_handler;
5084 get_one_authentic_pixel_from_handler=
5085 cache_methods->get_one_authentic_pixel_from_handler;
5086 if (get_one_authentic_pixel_from_handler !=
5087 (GetOneAuthenticPixelFromHandler) NULL)
5088 cache_info->methods.get_one_authentic_pixel_from_handler=
5089 cache_methods->get_one_authentic_pixel_from_handler;
5130 static inline MagickBooleanType AcquireCacheNexusPixels(
5131 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5134 if (length != (MagickSizeType) ((
size_t) length))
5136 (void) ThrowMagickException(exception,GetMagickModule(),
5137 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5138 cache_info->filename);
5139 return(MagickFalse);
5141 nexus_info->length=0;
5142 nexus_info->mapped=MagickFalse;
5143 if (cache_anonymous_memory <= 0)
5145 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5146 AcquireAlignedMemory(1,(
size_t) length));
5148 (
void) memset(nexus_info->cache,0,(
size_t) length);
5152 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5154 nexus_info->mapped=MagickTrue;
5158 (void) ThrowMagickException(exception,GetMagickModule(),
5159 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5160 cache_info->filename);
5161 return(MagickFalse);
5163 nexus_info->length=length;
5167 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5170 if (nexus_info->length < CACHE_LINE_SIZE)
5172 if (mode == ReadMode)
5174 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5178 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5181 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5184 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5185 return(MagickFalse);
5186 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5187 return(MagickFalse);
5192 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5193 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5194 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5204 assert(cache_info != (
const CacheInfo *) NULL);
5205 assert(cache_info->signature == MagickCoreSignature);
5206 if (cache_info->type == UndefinedCache)
5208 assert(nexus_info->signature == MagickCoreSignature);
5209 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5210 if ((width == 0) || (height == 0))
5212 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5213 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5216 if (((MagickSizeType) width > cache_info->width_limit) ||
5217 ((MagickSizeType) height > cache_info->height_limit))
5219 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5220 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5223 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5224 (ValidatePixelOffset(y,height) == MagickFalse))
5226 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5227 "InvalidPixel",
"`%s'",cache_info->filename);
5230 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5231 (buffered == MagickFalse))
5233 if (((x >= 0) && (y >= 0) &&
5234 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5235 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5236 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5244 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5246 offset=y*(MagickOffsetType) cache_info->columns+x;
5247 nexus_info->pixels=cache_info->pixels+offset;
5248 nexus_info->indexes=(IndexPacket *) NULL;
5249 if (cache_info->active_index_channel != MagickFalse)
5250 nexus_info->indexes=cache_info->indexes+offset;
5251 nexus_info->region.width=width;
5252 nexus_info->region.height=height;
5253 nexus_info->region.x=x;
5254 nexus_info->region.y=y;
5255 nexus_info->authentic_pixel_cache=MagickTrue;
5256 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5257 return(nexus_info->pixels);
5263 number_pixels=(MagickSizeType) width*height;
5264 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5266 if (cache_info->active_index_channel != MagickFalse)
5267 length+=number_pixels*
sizeof(IndexPacket);
5270 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5272 if (nexus_info->length < length)
5274 RelinquishCacheNexusPixels(nexus_info);
5275 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5277 if (status == MagickFalse)
5279 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5282 nexus_info->pixels=nexus_info->cache;
5283 nexus_info->indexes=(IndexPacket *) NULL;
5284 if (cache_info->active_index_channel != MagickFalse)
5285 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5286 nexus_info->region.width=width;
5287 nexus_info->region.height=height;
5288 nexus_info->region.x=x;
5289 nexus_info->region.y=y;
5290 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5291 MagickTrue : MagickFalse;
5292 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5293 return(nexus_info->pixels);
5324 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5325 const Quantum opacity)
5328 *magick_restrict image_view;
5336 assert(image != (
Image *) NULL);
5337 assert(image->signature == MagickCoreSignature);
5338 if (IsEventLogging() != MagickFalse)
5339 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5340 assert(image->cache != (Cache) NULL);
5341 image->matte=MagickTrue;
5343 image_view=AcquireVirtualCacheView(image,&image->exception);
5344 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5345 #pragma omp parallel for schedule(static) shared(status) \
5346 magick_number_threads(image,image,image->rows,1)
5348 for (y=0; y < (ssize_t) image->rows; y++)
5356 if (status == MagickFalse)
5358 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5365 for (x=0; x < (ssize_t) image->columns; x++)
5370 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5372 image_view=DestroyCacheView(image_view);
5376 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5377 const VirtualPixelMethod virtual_pixel_method)
5380 *magick_restrict cache_info;
5385 assert(image != (
Image *) NULL);
5386 assert(image->signature == MagickCoreSignature);
5387 if (IsEventLogging() != MagickFalse)
5388 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5389 assert(image->cache != (Cache) NULL);
5391 assert(cache_info->signature == MagickCoreSignature);
5392 method=cache_info->virtual_pixel_method;
5393 cache_info->virtual_pixel_method=virtual_pixel_method;
5394 if ((image->columns != 0) && (image->rows != 0))
5395 switch (virtual_pixel_method)
5397 case BackgroundVirtualPixelMethod:
5399 if ((image->background_color.opacity != OpaqueOpacity) &&
5400 (image->matte == MagickFalse))
5401 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5402 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5403 (IsGrayColorspace(image->colorspace) != MagickFalse))
5404 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5407 case TransparentVirtualPixelMethod:
5409 if (image->matte == MagickFalse)
5410 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5419 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5443 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5448 assert(cache_info != (
CacheInfo *)NULL);
5449 if ((cache_info->type != MemoryCache) ||
5455 LockSemaphoreInfo(cache_info->semaphore);
5464 clEnv=GetDefaultOpenCLEnv();
5465 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5466 if (events != (cl_event *) NULL)
5480 context=GetOpenCLContext(clEnv);
5481 queue=AcquireOpenCLCommandQueue(clEnv);
5482 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5483 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5484 cache_info->length,event_count,events,NULL,&status);
5485 assert(pixels == cache_info->pixels);
5486 events=(cl_event *) RelinquishMagickMemory(events);
5487 RelinquishOpenCLCommandQueue(clEnv,queue);
5489 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5491 UnlockSemaphoreInfo(cache_info->semaphore);
5494 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5497 *magick_restrict cache_info;
5499 assert(image != (
Image *)NULL);
5501 CopyOpenCLBuffer(cache_info);
5534 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5538 *magick_restrict cache_info;
5546 assert(image != (
Image *) NULL);
5547 assert(image->signature == MagickCoreSignature);
5548 if (image->cache == (Cache) NULL)
5549 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5551 assert(cache_info->signature == MagickCoreSignature);
5552 if (cache_info->type == UndefinedCache)
5553 return(MagickFalse);
5554 if ((image->storage_class == DirectClass) &&
5555 (image->clip_mask != (
Image *) NULL) &&
5556 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5557 return(MagickFalse);
5558 if ((image->storage_class == DirectClass) &&
5559 (image->mask != (
Image *) NULL) &&
5560 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5561 return(MagickFalse);
5562 if (nexus_info->authentic_pixel_cache != MagickFalse)
5564 if (image->taint == MagickFalse)
5565 image->taint=MagickTrue;
5568 assert(cache_info->signature == MagickCoreSignature);
5569 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5570 if ((cache_info->active_index_channel != MagickFalse) &&
5571 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5572 return(MagickFalse);
5573 if ((status != MagickFalse) && (image->taint == MagickFalse))
5574 image->taint=MagickTrue;
5605 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5609 *magick_restrict cache_info;
5612 id = GetOpenMPThreadId();
5617 assert(image != (
Image *) NULL);
5618 assert(image->signature == MagickCoreSignature);
5619 assert(image->cache != (Cache) NULL);
5621 assert(cache_info->signature == MagickCoreSignature);
5622 assert(
id < (
int) cache_info->number_threads);
5623 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5655 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5659 *magick_restrict cache_info;
5662 id = GetOpenMPThreadId();
5667 assert(image != (
Image *) NULL);
5668 assert(image->signature == MagickCoreSignature);
5669 assert(image->cache != (Cache) NULL);
5671 assert(cache_info->signature == MagickCoreSignature);
5672 if (cache_info->methods.sync_authentic_pixels_handler !=
5673 (SyncAuthenticPixelsHandler) NULL)
5674 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5675 assert(
id < (
int) cache_info->number_threads);
5676 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5708 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5712 *magick_restrict cache_info;
5714 assert(image != (
Image *) NULL);
5716 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5717 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5748 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5768 if (cache_info->active_index_channel == MagickFalse)
5769 return(MagickFalse);
5770 if (nexus_info->authentic_pixel_cache != MagickFalse)
5772 if (nexus_info->indexes == (IndexPacket *) NULL)
5773 return(MagickFalse);
5774 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5775 return(MagickFalse);
5776 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5777 nexus_info->region.x;
5778 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5779 rows=nexus_info->region.height;
5780 extent=(MagickSizeType) length*rows;
5781 p=nexus_info->indexes;
5783 switch (cache_info->type)
5794 if ((cache_info->columns == nexus_info->region.width) &&
5795 (extent == (MagickSizeType) ((
size_t) extent)))
5800 q=cache_info->indexes+offset;
5801 for (y=0; y < (ssize_t) rows; y++)
5803 (void) memcpy(q,p,(
size_t) length);
5804 p+=nexus_info->region.width;
5805 q+=cache_info->columns;
5814 LockSemaphoreInfo(cache_info->file_semaphore);
5815 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5817 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5818 cache_info->cache_filename);
5819 UnlockSemaphoreInfo(cache_info->file_semaphore);
5820 return(MagickFalse);
5822 if ((cache_info->columns == nexus_info->region.width) &&
5823 (extent <= MagickMaxBufferExtent))
5828 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5829 for (y=0; y < (ssize_t) rows; y++)
5831 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5832 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5833 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5835 if (count < (MagickOffsetType) length)
5837 p+=nexus_info->region.width;
5838 offset+=(MagickOffsetType) cache_info->columns;
5840 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5841 (
void) ClosePixelCacheOnDisk(cache_info);
5842 UnlockSemaphoreInfo(cache_info->file_semaphore);
5845 case DistributedCache:
5853 LockSemaphoreInfo(cache_info->file_semaphore);
5854 region=nexus_info->region;
5855 if ((cache_info->columns != nexus_info->region.width) ||
5856 (extent > MagickMaxBufferExtent))
5863 for (y=0; y < (ssize_t) rows; y++)
5866 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5867 if (count != (MagickOffsetType) length)
5869 p+=nexus_info->region.width;
5872 UnlockSemaphoreInfo(cache_info->file_semaphore);
5878 if (y < (ssize_t) rows)
5880 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5881 cache_info->cache_filename);
5882 return(MagickFalse);
5884 if ((cache_info->debug != MagickFalse) &&
5885 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5886 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5887 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5888 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5889 nexus_info->region.x,(
double) nexus_info->region.y);
5921 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5941 if (nexus_info->authentic_pixel_cache != MagickFalse)
5943 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5944 return(MagickFalse);
5945 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5946 nexus_info->region.x;
5947 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5948 rows=nexus_info->region.height;
5950 p=nexus_info->pixels;
5952 switch (cache_info->type)
5963 if ((cache_info->columns == nexus_info->region.width) &&
5964 (extent == (MagickSizeType) ((
size_t) extent)))
5969 q=cache_info->pixels+offset;
5970 for (y=0; y < (ssize_t) rows; y++)
5972 (void) memcpy(q,p,(
size_t) length);
5973 p+=nexus_info->region.width;
5974 q+=cache_info->columns;
5983 LockSemaphoreInfo(cache_info->file_semaphore);
5984 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5986 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5987 cache_info->cache_filename);
5988 UnlockSemaphoreInfo(cache_info->file_semaphore);
5989 return(MagickFalse);
5991 if ((cache_info->columns == nexus_info->region.width) &&
5992 (extent <= MagickMaxBufferExtent))
5997 for (y=0; y < (ssize_t) rows; y++)
5999 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6000 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6001 if (count < (MagickOffsetType) length)
6003 p+=nexus_info->region.width;
6004 offset+=(MagickOffsetType) cache_info->columns;
6006 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6007 (
void) ClosePixelCacheOnDisk(cache_info);
6008 UnlockSemaphoreInfo(cache_info->file_semaphore);
6011 case DistributedCache:
6019 LockSemaphoreInfo(cache_info->file_semaphore);
6020 region=nexus_info->region;
6021 if ((cache_info->columns != nexus_info->region.width) ||
6022 (extent > MagickMaxBufferExtent))
6029 for (y=0; y < (ssize_t) rows; y++)
6032 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6033 if (count != (MagickOffsetType) length)
6035 p+=nexus_info->region.width;
6038 UnlockSemaphoreInfo(cache_info->file_semaphore);
6044 if (y < (ssize_t) rows)
6046 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6047 cache_info->cache_filename);
6048 return(MagickFalse);
6050 if ((cache_info->debug != MagickFalse) &&
6051 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6052 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6053 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6054 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6055 nexus_info->region.x,(
double) nexus_info->region.y);