43#include "magick/studio.h"
44#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
47#include "magick/cache-private.h"
48#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/colorspace-private.h"
51#include "magick/composite-private.h"
52#include "magick/distribute-cache-private.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/geometry.h"
56#include "magick/list.h"
57#include "magick/log.h"
58#include "magick/magick.h"
59#include "magick/memory_.h"
60#include "magick/memory-private.h"
61#include "magick/nt-base-private.h"
62#include "magick/option.h"
63#include "magick/pixel.h"
64#include "magick/pixel-accessor.h"
65#include "magick/pixel-private.h"
66#include "magick/policy.h"
67#include "magick/quantum.h"
68#include "magick/random_.h"
69#include "magick/registry.h"
70#include "magick/resource_.h"
71#include "magick/semaphore.h"
72#include "magick/splay-tree.h"
73#include "magick/string_.h"
74#include "magick/string-private.h"
75#include "magick/thread-private.h"
76#include "magick/timer-private.h"
77#include "magick/utility.h"
78#include "magick/utility-private.h"
79#if defined(MAGICKCORE_ZLIB_DELEGATE)
86#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
87#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
88 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
103#if defined(__cplusplus) || defined(c_plusplus)
111static const IndexPacket
112 *GetVirtualIndexesFromCache(
const Image *);
115 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
117 *GetVirtualPixelsCache(
const Image *);
119static MagickBooleanType
120 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,
122 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
125 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
137 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
139 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
141 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
142 const ssize_t,
const ssize_t,
const size_t,
const size_t,
146#if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
151#if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
164#if defined(MAGICKCORE_OPENCL_SUPPORT)
171 for (i=0; i < (ssize_t) info->event_count; i++)
172 clEnv->library->clReleaseEvent(info->events[i]);
173 info->events=(cl_event *) RelinquishMagickMemory(info->events);
174 DestroySemaphoreInfo(&info->events_semaphore);
175 if (info->buffer != (cl_mem) NULL)
177 clEnv->library->clReleaseMemObject(info->buffer);
178 info->buffer=(cl_mem) NULL;
183static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
184 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
199 magick_unreferenced(event);
200 magick_unreferenced(event_command_exec_status);
202 clEnv=GetDefaultOpenCLEnv();
203 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
211 status=clEnv->library->clGetEventInfo(info->events[i],
212 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
213 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
215 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
216 &RelinquishPixelCachePixelsDelayed,info);
221 RelinquishMagickResource(MemoryResource,info->length);
222 (void) RelinquishOpenCLCacheInfo(clEnv,info);
223 (void) RelinquishAlignedMemory(pixels);
226static MagickBooleanType RelinquishOpenCLBuffer(
232 assert(cache_info != (
CacheInfo *) NULL);
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
240 cl_uint *event_count)
249 events=(cl_event *) NULL;
250 LockSemaphoreInfo(opencl_info->events_semaphore);
251 *event_count=opencl_info->event_count;
252 if (*event_count > 0)
254 events=(cl_event *) AcquireQuantumMemory(*event_count,
sizeof(*events));
255 if (events == (cl_event *) NULL)
259 for (i=0; i < opencl_info->event_count; i++)
260 events[i]=opencl_info->events[i];
263 UnlockSemaphoreInfo(opencl_info->events_semaphore);
268#if defined(MAGICKCORE_OPENCL_SUPPORT)
294extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
297 *magick_restrict cache_info;
302 assert(image != (
const Image *) NULL);
303 assert(event != (cl_event) NULL);
306 clEnv=GetDefaultOpenCLEnv();
307 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
309 clEnv->library->clWaitForEvents(1,&event);
312 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
313 if (cache_info->opencl->events == (cl_event *) NULL)
315 cache_info->opencl->events=(cl_event *) AcquireMagickMemory(
sizeof(
316 *cache_info->opencl->events));
317 cache_info->opencl->event_count=1;
320 cache_info->opencl->events=(cl_event *) ResizeQuantumMemory(
321 cache_info->opencl->events,++cache_info->opencl->event_count,
322 sizeof(*cache_info->opencl->events));
323 if (cache_info->opencl->events == (cl_event *) NULL)
324 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
325 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
326 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
352MagickExport Cache AcquirePixelCache(
const size_t number_threads)
355 *magick_restrict cache_info;
360 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
362 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
363 (void) memset(cache_info,0,
sizeof(*cache_info));
364 cache_info->type=UndefinedCache;
365 cache_info->mode=IOMode;
366 cache_info->disk_mode=IOMode;
367 cache_info->colorspace=sRGBColorspace;
368 cache_info->channels=4;
369 cache_info->file=(-1);
370 cache_info->id=GetMagickThreadId();
371 cache_info->number_threads=number_threads;
372 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
373 cache_info->number_threads=GetOpenMPMaximumThreads();
374 if (cache_info->number_threads == 0)
375 cache_info->number_threads=1;
376 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
377 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
378 if (value != (
const char *) NULL)
380 cache_info->synchronize=IsStringTrue(value);
381 value=DestroyString(value);
383 value=GetPolicyValue(
"cache:synchronize");
384 if (value != (
const char *) NULL)
386 cache_info->synchronize=IsStringTrue(value);
387 value=DestroyString(value);
389 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
390 (MagickSizeType) MAGICK_SSIZE_MAX);
391 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
392 (MagickSizeType) MAGICK_SSIZE_MAX);
393 cache_info->semaphore=AllocateSemaphoreInfo();
394 cache_info->reference_count=1;
395 cache_info->file_semaphore=AllocateSemaphoreInfo();
396 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
397 cache_info->signature=MagickCoreSignature;
398 return((Cache ) cache_info);
423MagickExport
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
426 **magick_restrict nexus_info;
431 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
432 number_threads,
sizeof(*nexus_info)));
434 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
435 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
436 2*
sizeof(**nexus_info));
438 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
439 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
440 for (i=0; i < (ssize_t) (2*number_threads); i++)
442 nexus_info[i]=(*nexus_info+i);
443 if (i < (ssize_t) number_threads)
444 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
445 nexus_info[i]->signature=MagickCoreSignature;
478MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
482 *magick_restrict cache_info;
484 assert(image != (
const Image *) NULL);
485 assert(image->signature == MagickCoreSignature);
487 assert(exception->signature == MagickCoreSignature);
488 assert(image->cache != (Cache) NULL);
490 assert(cache_info->signature == MagickCoreSignature);
493 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
494 return((
const void *) NULL);
495 *length=cache_info->length;
496 return((
const void *) cache_info->pixels);
517MagickExport MagickBooleanType CacheComponentGenesis(
void)
520 cache_semaphore=AllocateSemaphoreInfo();
542MagickExport
void CacheComponentTerminus(
void)
545 ActivateSemaphoreInfo(&cache_semaphore);
547 DestroySemaphoreInfo(&cache_semaphore);
579static MagickBooleanType ClipPixelCacheNexus(
Image *image,
583 *magick_restrict cache_info;
589 *magick_restrict nexus_indexes,
590 *magick_restrict indexes;
596 **magick_restrict clip_nexus;
608 if (IsEventLogging() != MagickFalse)
609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
610 if ((image->clip_mask == (
Image *) NULL) ||
611 (image->storage_class == PseudoClass))
613 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
616 if (cache_info == (Cache) NULL)
618 clip_nexus=AcquirePixelCacheNexus(1);
619 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
620 nexus_info->region.width,nexus_info->region.height,
621 nexus_info->virtual_nexus,exception);
622 indexes=nexus_info->virtual_nexus->indexes;
623 q=nexus_info->pixels;
624 nexus_indexes=nexus_info->indexes;
625 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
626 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
627 nexus_info->region.height,clip_nexus[0],exception);
632 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
637 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
642 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
643 if (fabs(mask_alpha) >= MagickEpsilon)
645 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
646 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
647 GetPixelOpacity(q)));
648 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
649 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
650 GetPixelOpacity(q)));
651 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
652 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
653 GetPixelOpacity(q)));
654 SetPixelOpacity(q,GetPixelOpacity(p));
655 if (cache_info->active_index_channel != MagickFalse)
656 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
664 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
690MagickExport Cache ClonePixelCache(
const Cache cache)
693 *magick_restrict clone_info;
696 *magick_restrict cache_info;
698 assert(cache != NULL);
700 assert(cache_info->signature == MagickCoreSignature);
701 if (IsEventLogging() != MagickFalse)
702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
703 cache_info->filename);
704 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
705 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
706 return((Cache ) clone_info);
734MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
737 *magick_restrict cache_info,
738 *magick_restrict source_info;
740 assert(clone != (Cache) NULL);
742 assert(source_info->signature == MagickCoreSignature);
743 if (IsEventLogging() != MagickFalse)
744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
745 source_info->filename);
746 assert(cache != (Cache) NULL);
748 assert(cache_info->signature == MagickCoreSignature);
749 source_info->methods=cache_info->methods;
781static MagickBooleanType ClonePixelCacheOnDisk(
802 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
803 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
805 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
806 (lseek(clone_info->file,0,SEEK_SET) < 0))
808 quantum=(size_t) MagickMaxBufferExtent;
809 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
811#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
812 if (cache_info->length < 0x7ffff000)
814 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
815 (
size_t) cache_info->length);
816 if (count == (ssize_t) cache_info->length)
818 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
819 (lseek(clone_info->file,0,SEEK_SET) < 0))
823 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
825 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
826 if (buffer == (
unsigned char *) NULL)
827 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
829 while ((count=read(cache_info->file,buffer,quantum)) > 0)
834 number_bytes=write(clone_info->file,buffer,(
size_t) count);
835 if (number_bytes != count)
837 extent+=(size_t) number_bytes;
839 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
840 if (extent != cache_info->length)
845static MagickBooleanType ClonePixelCacheRepository(
849#define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
850#define cache_number_threads(source,destination,chunk,multithreaded) \
851 num_threads((multithreaded) == 0 ? 1 : \
852 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
853 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
854 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
855 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
861 **magick_restrict cache_nexus,
862 **magick_restrict clone_nexus;
870 assert(cache_info != (
CacheInfo *) NULL);
871 assert(clone_info != (
CacheInfo *) NULL);
873 if (cache_info->type == PingCache)
875 if ((cache_info->storage_class == clone_info->storage_class) &&
876 (cache_info->colorspace == clone_info->colorspace) &&
877 (cache_info->channels == clone_info->channels) &&
878 (cache_info->columns == clone_info->columns) &&
879 (cache_info->rows == clone_info->rows) &&
880 (cache_info->active_index_channel == clone_info->active_index_channel))
885 if (((cache_info->type == MemoryCache) ||
886 (cache_info->type == MapCache)) &&
887 ((clone_info->type == MemoryCache) ||
888 (clone_info->type == MapCache)))
890 (void) memcpy(clone_info->pixels,cache_info->pixels,
891 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
892 if ((cache_info->active_index_channel != MagickFalse) &&
893 (clone_info->active_index_channel != MagickFalse))
894 (void) memcpy(clone_info->indexes,cache_info->indexes,
895 cache_info->columns*cache_info->rows*
896 sizeof(*cache_info->indexes));
899 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
900 return(ClonePixelCacheOnDisk(cache_info,clone_info));
905 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
906 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
907 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
908 sizeof(*cache_info->pixels);
910#if defined(MAGICKCORE_OPENMP_SUPPORT)
911 #pragma omp parallel for schedule(static) shared(status) \
912 cache_number_threads(cache_info,clone_info,cache_info->rows,4)
914 for (y=0; y < (ssize_t) cache_info->rows; y++)
917 id = GetOpenMPThreadId();
922 if (status == MagickFalse)
924 if (y >= (ssize_t) clone_info->rows)
926 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
927 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
930 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
931 if (status == MagickFalse)
933 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
934 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
937 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
938 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
939 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
941 if ((cache_info->active_index_channel != MagickFalse) &&
942 (clone_info->active_index_channel != MagickFalse))
947 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
948 sizeof(*cache_info->indexes);
949#if defined(MAGICKCORE_OPENMP_SUPPORT)
950 #pragma omp parallel for schedule(static) shared(status) \
951 cache_number_threads(cache_info,clone_info,cache_info->rows,4)
953 for (y=0; y < (ssize_t) cache_info->rows; y++)
956 id = GetOpenMPThreadId();
961 if (status == MagickFalse)
963 if (y >= (ssize_t) clone_info->rows)
965 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
966 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
969 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
970 if (status == MagickFalse)
972 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
973 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
976 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
977 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
980 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
981 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
982 if (cache_info->debug != MagickFalse)
985 message[MaxTextExtent];
987 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
988 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
989 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
990 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1017static void DestroyImagePixelCache(
Image *image)
1019 assert(image != (
Image *) NULL);
1020 assert(image->signature == MagickCoreSignature);
1021 if (IsEventLogging() != MagickFalse)
1022 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1023 if (image->cache != (
void *) NULL)
1024 image->cache=DestroyPixelCache(image->cache);
1049MagickExport
void DestroyImagePixels(
Image *image)
1052 *magick_restrict cache_info;
1054 assert(image != (
const Image *) NULL);
1055 assert(image->signature == MagickCoreSignature);
1056 if (IsEventLogging() != MagickFalse)
1057 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1058 assert(image->cache != (Cache) NULL);
1060 assert(cache_info->signature == MagickCoreSignature);
1061 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1063 cache_info->methods.destroy_pixel_handler(image);
1066 image->cache=DestroyPixelCache(image->cache);
1092static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1098 if (cache_info->file != -1)
1100 status=close(cache_info->file);
1101 cache_info->file=(-1);
1102 RelinquishMagickResource(FileResource,1);
1104 return(status == -1 ? MagickFalse : MagickTrue);
1107static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1109 switch (cache_info->type)
1113 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1114#if defined(MAGICKCORE_OPENCL_SUPPORT)
1115 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1121 if (cache_info->mapped == MagickFalse)
1122 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1123 cache_info->pixels);
1126 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1129 RelinquishMagickResource(MemoryResource,cache_info->length);
1134 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1136 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1137 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1138 *cache_info->cache_filename=
'\0';
1139 RelinquishMagickResource(MapResource,cache_info->length);
1144 if (cache_info->file != -1)
1145 (void) ClosePixelCacheOnDisk(cache_info);
1146 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1147 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1148 *cache_info->cache_filename=
'\0';
1149 RelinquishMagickResource(DiskResource,cache_info->length);
1152 case DistributedCache:
1154 *cache_info->cache_filename=
'\0';
1156 cache_info->server_info);
1162 cache_info->type=UndefinedCache;
1163 cache_info->mapped=MagickFalse;
1164 cache_info->indexes=(IndexPacket *) NULL;
1167MagickExport Cache DestroyPixelCache(Cache cache)
1170 *magick_restrict cache_info;
1172 assert(cache != (Cache) NULL);
1174 assert(cache_info->signature == MagickCoreSignature);
1175 if (IsEventLogging() != MagickFalse)
1176 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1177 cache_info->filename);
1178 LockSemaphoreInfo(cache_info->semaphore);
1179 cache_info->reference_count--;
1180 if (cache_info->reference_count != 0)
1182 UnlockSemaphoreInfo(cache_info->semaphore);
1183 return((Cache) NULL);
1185 UnlockSemaphoreInfo(cache_info->semaphore);
1186 if (cache_info->debug != MagickFalse)
1189 message[MaxTextExtent];
1191 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1192 cache_info->filename);
1193 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1195 RelinquishPixelCachePixels(cache_info);
1198 cache_info->server_info);
1199 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1200 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1201 cache_info->number_threads);
1202 if (cache_info->random_info != (
RandomInfo *) NULL)
1203 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1205 DestroySemaphoreInfo(&cache_info->file_semaphore);
1207 DestroySemaphoreInfo(&cache_info->semaphore);
1208 cache_info->signature=(~MagickCoreSignature);
1209 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1240static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1242 if (nexus_info->mapped == MagickFalse)
1243 (void) RelinquishAlignedMemory(nexus_info->cache);
1245 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1248 nexus_info->indexes=(IndexPacket *) NULL;
1249 nexus_info->length=0;
1250 nexus_info->mapped=MagickFalse;
1254 const size_t number_threads)
1259 assert(nexus_info != (
NexusInfo **) NULL);
1260 for (i=0; i < (ssize_t) (2*number_threads); i++)
1263 RelinquishCacheNexusPixels(nexus_info[i]);
1264 nexus_info[i]->signature=(~MagickCoreSignature);
1266 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1267 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1294static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1297 *magick_restrict cache_info;
1300 id = GetOpenMPThreadId();
1302 assert(image != (
const Image *) NULL);
1303 assert(image->signature == MagickCoreSignature);
1304 assert(image->cache != (Cache) NULL);
1306 assert(cache_info->signature == MagickCoreSignature);
1307 assert(
id < (
int) cache_info->number_threads);
1308 return(cache_info->nexus_info[
id]->indexes);
1336MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1339 *magick_restrict cache_info;
1342 id = GetOpenMPThreadId();
1344 assert(image != (
const Image *) NULL);
1345 assert(image->signature == MagickCoreSignature);
1346 assert(image->cache != (Cache) NULL);
1348 assert(cache_info->signature == MagickCoreSignature);
1349 if (cache_info->methods.get_authentic_indexes_from_handler !=
1350 (GetAuthenticIndexesFromHandler) NULL)
1351 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1352 assert(
id < (
int) cache_info->number_threads);
1353 return(cache_info->nexus_info[
id]->indexes);
1356#if defined(MAGICKCORE_OPENCL_SUPPORT)
1380MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1384 *magick_restrict cache_info;
1395 assert(image != (
const Image *) NULL);
1397 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1399 SyncImagePixelCache((
Image *) image,exception);
1402 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1403 return((cl_mem) NULL);
1404 LockSemaphoreInfo(cache_info->semaphore);
1405 clEnv=GetDefaultOpenCLEnv();
1408 assert(cache_info->pixels != NULL);
1409 context=GetOpenCLContext(clEnv);
1411 sizeof(*cache_info->opencl));
1412 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1413 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1414 cache_info->opencl->length=cache_info->length;
1415 cache_info->opencl->pixels=cache_info->pixels;
1416 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1417 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1418 if (status != CL_SUCCESS)
1419 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1422 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1423 UnlockSemaphoreInfo(cache_info->semaphore);
1425 return((cl_mem) NULL);
1426 return(cache_info->opencl->buffer);
1466 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1470 *magick_restrict cache_info;
1473 *magick_restrict pixels;
1478 assert(image != (
Image *) NULL);
1479 assert(image->signature == MagickCoreSignature);
1480 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1481 nexus_info,exception);
1485 assert(cache_info->signature == MagickCoreSignature);
1486 if (nexus_info->authentic_pixel_cache != MagickFalse)
1488 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1490 if (cache_info->active_index_channel != MagickFalse)
1491 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1522 *magick_restrict cache_info;
1525 id = GetOpenMPThreadId();
1527 assert(image != (
const Image *) NULL);
1528 assert(image->signature == MagickCoreSignature);
1529 assert(image->cache != (Cache) NULL);
1531 assert(cache_info->signature == MagickCoreSignature);
1532 assert(
id < (
int) cache_info->number_threads);
1533 return(cache_info->nexus_info[
id]->pixels);
1562 *magick_restrict cache_info;
1565 id = GetOpenMPThreadId();
1567 assert(image != (
const Image *) NULL);
1568 assert(image->signature == MagickCoreSignature);
1569 assert(image->cache != (Cache) NULL);
1571 assert(cache_info->signature == MagickCoreSignature);
1572 if (cache_info->methods.get_authentic_pixels_from_handler !=
1573 (GetAuthenticPixelsFromHandler) NULL)
1574 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1575 assert(
id < (
int) cache_info->number_threads);
1576 return(cache_info->nexus_info[
id]->pixels);
1626 const ssize_t y,
const size_t columns,
const size_t rows,
1630 *magick_restrict cache_info;
1633 id = GetOpenMPThreadId();
1635 assert(image != (
Image *) NULL);
1636 assert(image->signature == MagickCoreSignature);
1637 assert(image->cache != (Cache) NULL);
1639 assert(cache_info->signature == MagickCoreSignature);
1640 if (cache_info->methods.get_authentic_pixels_handler !=
1641 (GetAuthenticPixelsHandler) NULL)
1642 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1644 assert(
id < (
int) cache_info->number_threads);
1645 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1646 cache_info->nexus_info[
id],exception));
1681 const ssize_t y,
const size_t columns,
const size_t rows,
1685 *magick_restrict cache_info;
1688 id = GetOpenMPThreadId();
1690 assert(image != (
const Image *) NULL);
1691 assert(image->signature == MagickCoreSignature);
1692 assert(image->cache != (Cache) NULL);
1694 if (cache_info == (Cache) NULL)
1696 assert(cache_info->signature == MagickCoreSignature);
1697 assert(
id < (
int) cache_info->number_threads);
1698 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1699 cache_info->nexus_info[
id],exception));
1725MagickExport MagickSizeType GetImageExtent(
const Image *image)
1728 *magick_restrict cache_info;
1731 id = GetOpenMPThreadId();
1733 assert(image != (
Image *) NULL);
1734 assert(image->signature == MagickCoreSignature);
1735 if (IsEventLogging() != MagickFalse)
1736 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1737 assert(image->cache != (Cache) NULL);
1739 assert(cache_info->signature == MagickCoreSignature);
1740 assert(
id < (
int) cache_info->number_threads);
1741 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1744#if defined(MAGICKCORE_OPENCL_SUPPORT)
1772extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1773 cl_uint *event_count)
1776 *magick_restrict cache_info;
1781 assert(image != (
const Image *) NULL);
1782 assert(event_count != (cl_uint *) NULL);
1785 events=(cl_event *) NULL;
1787 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1822static inline MagickBooleanType ValidatePixelCacheMorphology(
1823 const Image *magick_restrict image)
1826 *magick_restrict cache_info;
1832 if ((image->storage_class != cache_info->storage_class) ||
1833 (image->colorspace != cache_info->colorspace) ||
1834 (image->channels != cache_info->channels) ||
1835 (image->columns != cache_info->columns) ||
1836 (image->rows != cache_info->rows) ||
1837 (cache_info->nexus_info == (
NexusInfo **) NULL))
1838 return(MagickFalse);
1842static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1846 *magick_restrict cache_info;
1850 status = MagickTrue;
1852 static MagickSizeType
1853 cpu_throttle = MagickResourceInfinity,
1856 if (IsImageTTLExpired(image) != MagickFalse)
1861 (void) ThrowMagickException(exception,GetMagickModule(),
1862 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1863 return((Cache) NULL);
1865 if (cpu_throttle == MagickResourceInfinity)
1866 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1867 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1868 MagickDelay(cpu_throttle);
1869 LockSemaphoreInfo(image->semaphore);
1870 assert(image->cache != (Cache) NULL);
1872#if defined(MAGICKCORE_OPENCL_SUPPORT)
1873 CopyOpenCLBuffer(cache_info);
1875 destroy=MagickFalse;
1876 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1878 LockSemaphoreInfo(cache_info->semaphore);
1879 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1890 clone_image=(*image);
1891 clone_image.semaphore=AllocateSemaphoreInfo();
1892 clone_image.reference_count=1;
1893 clone_image.cache=ClonePixelCache(cache_info);
1894 clone_info=(
CacheInfo *) clone_image.cache;
1895 status=OpenPixelCache(&clone_image,IOMode,exception);
1896 if (status == MagickFalse)
1897 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1900 if (clone != MagickFalse)
1901 status=ClonePixelCacheRepository(clone_info,cache_info,
1903 if (status == MagickFalse)
1904 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1908 image->cache=clone_info;
1911 DestroySemaphoreInfo(&clone_image.semaphore);
1913 UnlockSemaphoreInfo(cache_info->semaphore);
1915 if (destroy != MagickFalse)
1916 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1917 if (status != MagickFalse)
1922 if (image->type != UndefinedType)
1923 image->type=UndefinedType;
1924 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1926 status=OpenPixelCache(image,IOMode,exception);
1928 if (cache_info->file != -1)
1929 (void) ClosePixelCacheOnDisk(cache_info);
1932 UnlockSemaphoreInfo(image->semaphore);
1933 if (status == MagickFalse)
1934 return((Cache) NULL);
1935 return(image->cache);
1962MagickExport CacheType GetPixelCacheType(
const Image *image)
1964 return(GetImagePixelCacheType(image));
1967MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1970 *magick_restrict cache_info;
1972 assert(image != (
Image *) NULL);
1973 assert(image->signature == MagickCoreSignature);
1974 assert(image->cache != (Cache) NULL);
1976 assert(cache_info->signature == MagickCoreSignature);
1977 return(cache_info->type);
2010MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2014 *magick_restrict cache_info;
2017 *magick_restrict pixels;
2019 assert(image != (
Image *) NULL);
2020 assert(image->signature == MagickCoreSignature);
2021 assert(image->cache != (Cache) NULL);
2023 assert(cache_info->signature == MagickCoreSignature);
2024 *pixel=image->background_color;
2025 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2026 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2027 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2029 return(MagickFalse);
2065static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2069 *magick_restrict cache_info;
2072 id = GetOpenMPThreadId();
2075 *magick_restrict pixels;
2077 assert(image != (
const Image *) NULL);
2078 assert(image->signature == MagickCoreSignature);
2079 assert(image->cache != (Cache) NULL);
2081 assert(cache_info->signature == MagickCoreSignature);
2082 *pixel=image->background_color;
2083 assert(
id < (
int) cache_info->number_threads);
2084 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2085 cache_info->nexus_info[
id],exception);
2087 return(MagickFalse);
2124MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2129 *magick_restrict cache_info;
2132 id = GetOpenMPThreadId();
2135 *magick_restrict indexes;
2138 *magick_restrict pixels;
2140 assert(image != (
const Image *) NULL);
2141 assert(image->signature == MagickCoreSignature);
2142 assert(image->cache != (Cache) NULL);
2144 assert(cache_info->signature == MagickCoreSignature);
2145 assert(
id < (
int) cache_info->number_threads);
2146 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2147 1UL,1UL,cache_info->nexus_info[
id],exception);
2148 GetMagickPixelPacket(image,pixel);
2150 return(MagickFalse);
2151 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2152 SetMagickPixelPacket(image,pixels,indexes,pixel);
2191MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2192 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2196 *magick_restrict cache_info;
2199 id = GetOpenMPThreadId();
2202 *magick_restrict pixels;
2204 assert(image != (
const Image *) NULL);
2205 assert(image->signature == MagickCoreSignature);
2206 assert(image->cache != (Cache) NULL);
2208 assert(cache_info->signature == MagickCoreSignature);
2209 *pixel=image->background_color;
2210 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2211 (GetOneVirtualPixelFromHandler) NULL)
2212 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2213 virtual_pixel_method,x,y,pixel,exception));
2214 assert(
id < (
int) cache_info->number_threads);
2215 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2216 cache_info->nexus_info[
id],exception);
2218 return(MagickFalse);
2254MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2258 *magick_restrict cache_info;
2261 id = GetOpenMPThreadId();
2264 *magick_restrict pixels;
2266 assert(image != (
const Image *) NULL);
2267 assert(image->signature == MagickCoreSignature);
2268 assert(image->cache != (Cache) NULL);
2270 assert(cache_info->signature == MagickCoreSignature);
2271 *pixel=image->background_color;
2272 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2273 (GetOneVirtualPixelFromHandler) NULL)
2274 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2275 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2276 assert(
id < (
int) cache_info->number_threads);
2277 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2278 1UL,1UL,cache_info->nexus_info[
id],exception);
2280 return(MagickFalse);
2319static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2320 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2324 *magick_restrict cache_info;
2327 id = GetOpenMPThreadId();
2330 *magick_restrict pixels;
2332 assert(image != (
const Image *) NULL);
2333 assert(image->signature == MagickCoreSignature);
2334 assert(image->cache != (Cache) NULL);
2336 assert(cache_info->signature == MagickCoreSignature);
2337 assert(
id < (
int) cache_info->number_threads);
2338 *pixel=image->background_color;
2339 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2340 cache_info->nexus_info[
id],exception);
2342 return(MagickFalse);
2372MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2375 *magick_restrict cache_info;
2377 assert(cache != (Cache) NULL);
2379 assert(cache_info->signature == MagickCoreSignature);
2380 if (IsEventLogging() != MagickFalse)
2381 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2382 cache_info->filename);
2383 return(cache_info->channels);
2408MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2411 *magick_restrict cache_info;
2413 assert(cache != (Cache) NULL);
2415 assert(cache_info->signature == MagickCoreSignature);
2416 if (IsEventLogging() != MagickFalse)
2417 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2418 cache_info->filename);
2419 return(cache_info->colorspace);
2445MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2448 *magick_restrict cache_info;
2450 assert(image != (
const Image *) NULL);
2451 assert(image->signature == MagickCoreSignature);
2452 assert(image->cache != (Cache) NULL);
2454 assert(cache_info->signature == MagickCoreSignature);
2455 return(cache_info->cache_filename);
2480MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2483 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2484 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2485 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2486 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2487 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2488 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2489 cache_methods->get_authentic_indexes_from_handler=
2490 GetAuthenticIndexesFromCache;
2491 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2492 cache_methods->get_one_authentic_pixel_from_handler=
2493 GetOneAuthenticPixelFromCache;
2494 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2495 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2496 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2523MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2527 *magick_restrict cache_info;
2532 assert(cache != NULL);
2534 assert(cache_info->signature == MagickCoreSignature);
2535 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2537 return((MagickSizeType) cache_info->columns*cache_info->rows);
2568MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2572 *magick_restrict cache_info;
2574 assert(image != (
const Image *) NULL);
2575 assert(image->signature == MagickCoreSignature);
2576 assert(image->cache != (Cache) NULL);
2577 assert(length != (MagickSizeType *) NULL);
2579 assert(exception->signature == MagickCoreSignature);
2581 assert(cache_info->signature == MagickCoreSignature);
2583 *length=cache_info->length;
2584 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2585 return((
void *) NULL);
2586 return((
void *) cache_info->pixels);
2613MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2616 *magick_restrict cache_info;
2618 assert(cache != (Cache) NULL);
2620 assert(cache_info->signature == MagickCoreSignature);
2621 if (IsEventLogging() != MagickFalse)
2622 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2623 cache_info->filename);
2624 return(cache_info->storage_class);
2654MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2657 assert(image != (
Image *) NULL);
2658 assert(image->signature == MagickCoreSignature);
2659 if (IsEventLogging() != MagickFalse)
2660 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2662 if (GetImagePixelCacheType(image) == DiskCache)
2691MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2694 *magick_restrict cache_info;
2696 assert(image != (
Image *) NULL);
2697 assert(image->signature == MagickCoreSignature);
2698 assert(image->cache != (Cache) NULL);
2700 assert(cache_info->signature == MagickCoreSignature);
2701 return(cache_info->virtual_pixel_method);
2727static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2730 *magick_restrict cache_info;
2733 id = GetOpenMPThreadId();
2735 assert(image != (
const Image *) NULL);
2736 assert(image->signature == MagickCoreSignature);
2737 assert(image->cache != (Cache) NULL);
2739 assert(cache_info->signature == MagickCoreSignature);
2740 assert(
id < (
int) cache_info->number_threads);
2741 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2770MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2774 *magick_restrict cache_info;
2776 assert(cache != (Cache) NULL);
2778 assert(cache_info->signature == MagickCoreSignature);
2779 if (cache_info->storage_class == UndefinedClass)
2780 return((IndexPacket *) NULL);
2781 return(nexus_info->indexes);
2809MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2812 *magick_restrict cache_info;
2815 id = GetOpenMPThreadId();
2817 assert(image != (
const Image *) NULL);
2818 assert(image->signature == MagickCoreSignature);
2819 assert(image->cache != (Cache) NULL);
2821 assert(cache_info->signature == MagickCoreSignature);
2822 if (cache_info->methods.get_virtual_indexes_from_handler !=
2823 (GetVirtualIndexesFromHandler) NULL)
2828 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2829 if (indexes != (IndexPacket *) NULL)
2832 assert(
id < (
int) cache_info->number_threads);
2833 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2876 0, 48, 12, 60, 3, 51, 15, 63,
2877 32, 16, 44, 28, 35, 19, 47, 31,
2878 8, 56, 4, 52, 11, 59, 7, 55,
2879 40, 24, 36, 20, 43, 27, 39, 23,
2880 2, 50, 14, 62, 1, 49, 13, 61,
2881 34, 18, 46, 30, 33, 17, 45, 29,
2882 10, 58, 6, 54, 9, 57, 5, 53,
2883 42, 26, 38, 22, 41, 25, 37, 21
2886static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2891 index=x+DitherMatrix[x & 0x07]-32L;
2894 if (index >= (ssize_t) columns)
2895 return((ssize_t) columns-1L);
2899static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2904 index=y+DitherMatrix[y & 0x07]-32L;
2907 if (index >= (ssize_t) rows)
2908 return((ssize_t) rows-1L);
2912static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2916 if (x >= (ssize_t) columns)
2917 return((ssize_t) (columns-1));
2921static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2925 if (y >= (ssize_t) rows)
2926 return((ssize_t) (rows-1));
2930static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2933 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2934 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2935 return(MagickFalse);
2939static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2941 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2944static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2946 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2949static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2950 const size_t extent)
2955 modulo.quotient=offset;
2959 modulo.quotient=offset/((ssize_t) extent);
2960 modulo.remainder=offset % ((ssize_t) extent);
2962 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2965 modulo.remainder+=((ssize_t) extent);
2970MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2971 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2972 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2976 *magick_restrict cache_info;
2979 *magick_restrict virtual_indexes;
2986 *magick_restrict indexes;
2996 *magick_restrict virtual_nexus;
2999 *magick_restrict pixels,
3010 assert(image != (
const Image *) NULL);
3011 assert(image->signature == MagickCoreSignature);
3012 assert(image->cache != (Cache) NULL);
3014 assert(cache_info->signature == MagickCoreSignature);
3015 if (cache_info->type == UndefinedCache)
3017#if defined(MAGICKCORE_OPENCL_SUPPORT)
3018 CopyOpenCLBuffer(cache_info);
3020 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3021 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3022 MagickTrue : MagickFalse,nexus_info,exception);
3025 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3027 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3028 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3030 offset+=nexus_info->region.x;
3031 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3032 nexus_info->region.width-1L;
3033 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3034 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3035 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3036 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3044 if (nexus_info->authentic_pixel_cache != MagickFalse)
3046 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3047 if (status == MagickFalse)
3049 if ((cache_info->storage_class == PseudoClass) ||
3050 (cache_info->colorspace == CMYKColorspace))
3052 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3053 if (status == MagickFalse)
3061 virtual_nexus=nexus_info->virtual_nexus;
3063 indexes=nexus_info->indexes;
3064 switch (virtual_pixel_method)
3066 case BlackVirtualPixelMethod:
3068 SetPixelRed(&virtual_pixel,0);
3069 SetPixelGreen(&virtual_pixel,0);
3070 SetPixelBlue(&virtual_pixel,0);
3071 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3074 case GrayVirtualPixelMethod:
3076 SetPixelRed(&virtual_pixel,QuantumRange/2);
3077 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3078 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3079 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3082 case TransparentVirtualPixelMethod:
3084 SetPixelRed(&virtual_pixel,0);
3085 SetPixelGreen(&virtual_pixel,0);
3086 SetPixelBlue(&virtual_pixel,0);
3087 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3090 case MaskVirtualPixelMethod:
3091 case WhiteVirtualPixelMethod:
3093 SetPixelRed(&virtual_pixel,QuantumRange);
3094 SetPixelGreen(&virtual_pixel,QuantumRange);
3095 SetPixelBlue(&virtual_pixel,QuantumRange);
3096 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3101 virtual_pixel=image->background_color;
3105 virtual_index=(IndexPacket) 0;
3106 for (v=0; v < (ssize_t) rows; v++)
3112 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3113 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3114 y_offset=EdgeY(y_offset,cache_info->rows);
3115 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3121 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3122 (ssize_t) columns-u);
3123 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3124 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3134 length=(MagickSizeType) 1;
3135 switch (virtual_pixel_method)
3137 case BackgroundVirtualPixelMethod:
3138 case ConstantVirtualPixelMethod:
3139 case BlackVirtualPixelMethod:
3140 case GrayVirtualPixelMethod:
3141 case TransparentVirtualPixelMethod:
3142 case MaskVirtualPixelMethod:
3143 case WhiteVirtualPixelMethod:
3146 virtual_indexes=(&virtual_index);
3149 case EdgeVirtualPixelMethod:
3152 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3153 EdgeX(x_offset,cache_info->columns),
3154 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3156 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3160 case RandomVirtualPixelMethod:
3162 if (cache_info->random_info == (
RandomInfo *) NULL)
3163 cache_info->random_info=AcquireRandomInfo();
3164 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3165 RandomX(cache_info->random_info,cache_info->columns),
3166 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3167 virtual_nexus,exception);
3168 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3172 case DitherVirtualPixelMethod:
3174 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3175 DitherX(x_offset,cache_info->columns),
3176 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3178 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3182 case TileVirtualPixelMethod:
3184 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3185 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3186 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3187 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3189 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3193 case MirrorVirtualPixelMethod:
3195 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3196 if ((x_modulo.quotient & 0x01) == 1L)
3197 x_modulo.remainder=(ssize_t) cache_info->columns-
3198 x_modulo.remainder-1L;
3199 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3200 if ((y_modulo.quotient & 0x01) == 1L)
3201 y_modulo.remainder=(ssize_t) cache_info->rows-
3202 y_modulo.remainder-1L;
3203 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3204 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3206 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3210 case CheckerTileVirtualPixelMethod:
3212 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3213 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3214 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3217 virtual_indexes=(&virtual_index);
3220 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3221 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3223 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3227 case HorizontalTileVirtualPixelMethod:
3229 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3232 virtual_indexes=(&virtual_index);
3235 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3236 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3237 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3238 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3240 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3244 case VerticalTileVirtualPixelMethod:
3246 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3249 virtual_indexes=(&virtual_index);
3252 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3253 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3254 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3255 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3257 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3261 case HorizontalTileEdgeVirtualPixelMethod:
3263 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3264 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3265 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3266 virtual_nexus,exception);
3267 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3271 case VerticalTileEdgeVirtualPixelMethod:
3273 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3274 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3275 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3276 virtual_nexus,exception);
3277 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3285 if ((indexes != (IndexPacket *) NULL) &&
3286 (virtual_indexes != (
const IndexPacket *) NULL))
3287 *indexes++=(*virtual_indexes);
3293 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3294 (
size_t) length,1UL,virtual_nexus,exception);
3297 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3298 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3299 q+=(ptrdiff_t) length;
3300 if ((indexes != (IndexPacket *) NULL) &&
3301 (virtual_indexes != (
const IndexPacket *) NULL))
3303 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3304 sizeof(*virtual_indexes));
3308 if (u < (ssize_t) columns)
3314 if (v < (ssize_t) rows)
3354 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3355 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3358 *magick_restrict cache_info;
3361 id = GetOpenMPThreadId();
3363 assert(image != (
const Image *) NULL);
3364 assert(image->signature == MagickCoreSignature);
3365 assert(image->cache != (Cache) NULL);
3367 assert(cache_info->signature == MagickCoreSignature);
3368 assert(
id < (
int) cache_info->number_threads);
3369 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3370 cache_info->nexus_info[
id],exception));
3399 *magick_restrict cache_info;
3402 id = GetOpenMPThreadId();
3404 assert(image != (
const Image *) NULL);
3405 assert(image->signature == MagickCoreSignature);
3406 assert(image->cache != (Cache) NULL);
3408 assert(cache_info->signature == MagickCoreSignature);
3409 if (cache_info->methods.get_virtual_pixels_handler !=
3410 (GetVirtualPixelsHandler) NULL)
3411 return(cache_info->methods.get_virtual_pixels_handler(image));
3412 assert(
id < (
int) cache_info->number_threads);
3413 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3465 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3469 *magick_restrict cache_info;
3472 id = GetOpenMPThreadId();
3474 assert(image != (
const Image *) NULL);
3475 assert(image->signature == MagickCoreSignature);
3476 assert(image->cache != (Cache) NULL);
3478 assert(cache_info->signature == MagickCoreSignature);
3479 if (cache_info->methods.get_virtual_pixel_handler !=
3480 (GetVirtualPixelHandler) NULL)
3481 return(cache_info->methods.get_virtual_pixel_handler(image,
3482 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3483 assert(
id < (
int) cache_info->number_threads);
3484 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3485 columns,rows,cache_info->nexus_info[
id],exception));
3514 *magick_restrict cache_info;
3517 id = GetOpenMPThreadId();
3519 assert(image != (
const Image *) NULL);
3520 assert(image->signature == MagickCoreSignature);
3521 assert(image->cache != (Cache) NULL);
3523 assert(cache_info->signature == MagickCoreSignature);
3524 assert(
id < (
int) cache_info->number_threads);
3525 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3554MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3558 *magick_restrict cache_info;
3560 assert(cache != (Cache) NULL);
3562 assert(cache_info->signature == MagickCoreSignature);
3563 if (cache_info->storage_class == UndefinedClass)
3605 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3610 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3611 gamma=PerceptibleReciprocal(gamma);
3612 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3613 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3614 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3615 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3616 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3619static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3623 *magick_restrict cache_info;
3629 *magick_restrict nexus_indexes,
3630 *magick_restrict indexes;
3640 **magick_restrict mask_nexus;
3652 if (IsEventLogging() != MagickFalse)
3653 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3654 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3656 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3659 if (cache_info == (Cache) NULL)
3660 return(MagickFalse);
3661 mask_nexus=AcquirePixelCacheNexus(1);
3662 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3663 nexus_info->virtual_nexus,exception);
3664 indexes=nexus_info->virtual_nexus->indexes;
3665 q=nexus_info->pixels;
3666 nexus_indexes=nexus_info->indexes;
3667 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3668 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3669 nexus_info->region.height,mask_nexus[0],&image->exception);
3672 return(MagickFalse);
3674 GetMagickPixelPacket(image,&alpha);
3675 GetMagickPixelPacket(image,&beta);
3676 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3681 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3683 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3684 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3685 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3686 alpha.opacity,&beta);
3687 SetPixelRed(q,ClampToQuantum(beta.red));
3688 SetPixelGreen(q,ClampToQuantum(beta.green));
3689 SetPixelBlue(q,ClampToQuantum(beta.blue));
3690 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3691 if (cache_info->active_index_channel != MagickFalse)
3692 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3699 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3734static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3743 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3745 if (*cache_info->cache_filename ==
'\0')
3746 file=AcquireUniqueFileResource(cache_info->cache_filename);
3752 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3757 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3758 O_BINARY | O_EXCL,S_MODE);
3760 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3766 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3769 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3774 return(MagickFalse);
3775 (void) AcquireMagickResource(FileResource,1);
3776 if (cache_info->file != -1)
3777 (void) ClosePixelCacheOnDisk(cache_info);
3778 cache_info->file=file;
3779 cache_info->disk_mode=mode;
3783static inline MagickOffsetType WritePixelCacheRegion(
3784 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3785 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3793#if !defined(MAGICKCORE_HAVE_PWRITE)
3794 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3795 return((MagickOffsetType) -1);
3797 for (i=0; i < (MagickOffsetType) length; i+=count)
3799#if !defined(MAGICKCORE_HAVE_PWRITE)
3800 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3801 (MagickSizeType) i,MagickMaxBufferExtent));
3803 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3804 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3816static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3819 *magick_restrict cache_info;
3825 if (cache_info->debug != MagickFalse)
3828 format[MaxTextExtent],
3829 message[MaxTextExtent];
3831 (void) FormatMagickSize(length,MagickFalse,format);
3832 (void) FormatLocaleString(message,MaxTextExtent,
3833 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3834 cache_info->cache_filename,cache_info->file,format);
3835 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3837 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3839 return(MagickFalse);
3840 if ((MagickSizeType) offset < length)
3846 extent=(MagickOffsetType) length-1;
3847 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3850 return(MagickFalse);
3851#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3852 if (cache_info->synchronize != MagickFalse)
3853 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3854 return(MagickFalse);
3857 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3859 return(MagickFalse);
3863static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3867 *magick_restrict cache_info,
3871 format[MaxTextExtent],
3872 message[MaxTextExtent];
3889 assert(image != (
const Image *) NULL);
3890 assert(image->signature == MagickCoreSignature);
3891 assert(image->cache != (Cache) NULL);
3892 if (IsEventLogging() != MagickFalse)
3893 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3894 if (cache_anonymous_memory < 0)
3902 cache_anonymous_memory=0;
3903 value=GetPolicyValue(
"pixel-cache-memory");
3904 if (value == (
char *) NULL)
3905 value=GetPolicyValue(
"cache:memory-map");
3906 if (LocaleCompare(value,
"anonymous") == 0)
3908#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3909 cache_anonymous_memory=1;
3911 (void) ThrowMagickException(exception,GetMagickModule(),
3912 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3913 "'%s' (policy requires anonymous memory mapping)",image->filename);
3916 value=DestroyString(value);
3918 if ((image->columns == 0) || (image->rows == 0))
3919 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3921 assert(cache_info->signature == MagickCoreSignature);
3922 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3923 ((MagickSizeType) image->rows > cache_info->height_limit))
3924 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3926 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3928 length=GetImageListLength(image);
3929 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3930 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3933 source_info=(*cache_info);
3934 source_info.file=(-1);
3935 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3936 image->filename,(
double) image->scene);
3937 cache_info->storage_class=image->storage_class;
3938 cache_info->colorspace=image->colorspace;
3939 cache_info->rows=image->rows;
3940 cache_info->columns=image->columns;
3941 cache_info->channels=image->channels;
3942 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3943 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3944 cache_info->mode=mode;
3945 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3947 if (cache_info->active_index_channel != MagickFalse)
3948 packet_size+=
sizeof(IndexPacket);
3949 length=number_pixels*packet_size;
3950 columns=(size_t) (length/cache_info->rows/packet_size);
3951 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3952 ((ssize_t) cache_info->rows < 0))
3953 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3955 cache_info->length=length;
3956 if (image->ping != MagickFalse)
3958 cache_info->type=PingCache;
3961 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3962 cache_info->columns*cache_info->rows);
3963 if (cache_info->mode == PersistMode)
3965 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3966 if ((status != MagickFalse) &&
3967 (length == (MagickSizeType) ((
size_t) length)) &&
3968 ((cache_info->type == UndefinedCache) ||
3969 (cache_info->type == MemoryCache)))
3971 status=AcquireMagickResource(MemoryResource,cache_info->length);
3972 if (status != MagickFalse)
3975 if (cache_anonymous_memory <= 0)
3977 cache_info->mapped=MagickFalse;
3978 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3979 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3983 cache_info->mapped=MagickTrue;
3984 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3985 cache_info->length);
3989 cache_info->mapped=source_info.mapped;
3990 cache_info->pixels=source_info.pixels;
3997 cache_info->colorspace=image->colorspace;
3998 cache_info->type=MemoryCache;
3999 cache_info->indexes=(IndexPacket *) NULL;
4000 if (cache_info->active_index_channel != MagickFalse)
4001 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4003 if ((source_info.storage_class != UndefinedClass) &&
4006 status&=ClonePixelCacheRepository(cache_info,&source_info,
4008 RelinquishPixelCachePixels(&source_info);
4010 if (cache_info->debug != MagickFalse)
4012 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4013 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4015 (void) FormatLocaleString(message,MaxTextExtent,
4016 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4017 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4018 type,(
double) cache_info->columns,(
double) cache_info->rows,
4020 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4023 cache_info->storage_class=image->storage_class;
4026 if ((source_info.storage_class != UndefinedClass) &&
4028 RelinquishPixelCachePixels(&source_info);
4029 cache_info->type=UndefinedCache;
4030 return(MagickFalse);
4036 status=AcquireMagickResource(DiskResource,cache_info->length);
4037 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4039 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4047 server_info=AcquireDistributeCacheInfo(exception);
4050 status=OpenDistributePixelCache(server_info,image);
4051 if (status == MagickFalse)
4053 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4054 GetDistributeCacheHostname(server_info));
4055 server_info=DestroyDistributeCacheInfo(server_info);
4063 cache_info->type=DistributedCache;
4064 cache_info->storage_class=image->storage_class;
4065 cache_info->colorspace=image->colorspace;
4066 cache_info->server_info=server_info;
4067 (void) FormatLocaleString(cache_info->cache_filename,
4068 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4071 cache_info->server_info));
4072 if ((source_info.storage_class != UndefinedClass) &&
4075 status=ClonePixelCacheRepository(cache_info,&source_info,
4077 RelinquishPixelCachePixels(&source_info);
4079 if (cache_info->debug != MagickFalse)
4081 (void) FormatMagickSize(cache_info->length,MagickFalse,
4083 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4085 (void) FormatLocaleString(message,MaxTextExtent,
4086 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4087 cache_info->cache_filename,GetDistributeCacheFile(
4089 (
double) cache_info->columns,(
double) cache_info->rows,
4091 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4096 if ((source_info.storage_class != UndefinedClass) &&
4098 RelinquishPixelCachePixels(&source_info);
4099 cache_info->type=UndefinedCache;
4100 return(MagickFalse);
4105 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4106 RelinquishPixelCachePixels(&source_info);
4107 cache_info->type=UndefinedCache;
4108 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4109 "CacheResourcesExhausted",
"`%s'",image->filename);
4110 return(MagickFalse);
4115 if (status == MagickFalse)
4117 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4118 RelinquishPixelCachePixels(&source_info);
4119 cache_info->type=UndefinedCache;
4120 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4121 "CacheResourcesExhausted",
"`%s'",image->filename);
4122 return(MagickFalse);
4124 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4125 (cache_info->mode != PersistMode))
4127 (void) ClosePixelCacheOnDisk(cache_info);
4128 *cache_info->cache_filename=
'\0';
4130 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4132 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4133 RelinquishPixelCachePixels(&source_info);
4134 cache_info->type=UndefinedCache;
4135 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4137 return(MagickFalse);
4139 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4140 cache_info->length);
4141 if (status == MagickFalse)
4143 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4144 RelinquishPixelCachePixels(&source_info);
4145 cache_info->type=UndefinedCache;
4146 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4148 return(MagickFalse);
4150 cache_info->storage_class=image->storage_class;
4151 cache_info->colorspace=image->colorspace;
4152 cache_info->type=DiskCache;
4153 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4154 if (length == (MagickSizeType) ((
size_t) length))
4156 status=AcquireMagickResource(MapResource,cache_info->length);
4157 if (status != MagickFalse)
4159 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4160 cache_info->offset,(
size_t) cache_info->length);
4163 cache_info->mapped=source_info.mapped;
4164 cache_info->pixels=source_info.pixels;
4165 RelinquishMagickResource(MapResource,cache_info->length);
4172 (void) ClosePixelCacheOnDisk(cache_info);
4173 cache_info->type=MapCache;
4174 cache_info->mapped=MagickTrue;
4175 cache_info->indexes=(IndexPacket *) NULL;
4176 if (cache_info->active_index_channel != MagickFalse)
4177 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4179 if ((source_info.storage_class != UndefinedClass) &&
4182 status=ClonePixelCacheRepository(cache_info,&source_info,
4184 RelinquishPixelCachePixels(&source_info);
4186 if (cache_info->debug != MagickFalse)
4188 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4189 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4191 (void) FormatLocaleString(message,MaxTextExtent,
4192 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4193 cache_info->filename,cache_info->cache_filename,
4194 cache_info->file,type,(
double) cache_info->columns,
4195 (
double) cache_info->rows,format);
4196 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4201 if ((source_info.storage_class != UndefinedClass) &&
4203 RelinquishPixelCachePixels(&source_info);
4204 cache_info->type=UndefinedCache;
4205 return(MagickFalse);
4212 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4214 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4215 RelinquishPixelCachePixels(&source_info);
4217 if (cache_info->debug != MagickFalse)
4219 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4220 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4222 (void) FormatLocaleString(message,MaxTextExtent,
4223 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4224 cache_info->cache_filename,cache_info->file,type,(
double)
4225 cache_info->columns,(
double) cache_info->rows,format);
4226 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4230 cache_info->type=UndefinedCache;
4231 return(MagickFalse);
4273MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4274 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4278 *magick_restrict cache_info,
4279 *magick_restrict clone_info;
4287 assert(image != (
Image *) NULL);
4288 assert(image->signature == MagickCoreSignature);
4289 if (IsEventLogging() != MagickFalse)
4290 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4291 assert(image->cache != (
void *) NULL);
4292 assert(filename != (
const char *) NULL);
4293 assert(offset != (MagickOffsetType *) NULL);
4294 page_size=GetMagickPageSize();
4296 assert(cache_info->signature == MagickCoreSignature);
4297#if defined(MAGICKCORE_OPENCL_SUPPORT)
4298 CopyOpenCLBuffer(cache_info);
4300 if (attach != MagickFalse)
4305 if (cache_info->debug != MagickFalse)
4306 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4307 "attach persistent cache");
4308 (void) CopyMagickString(cache_info->cache_filename,filename,
4310 cache_info->type=MapCache;
4311 cache_info->offset=(*offset);
4312 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4313 return(MagickFalse);
4314 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4315 ((MagickOffsetType) cache_info->length % page_size));
4321 status=AcquireMagickResource(DiskResource,cache_info->length);
4322 if (status == MagickFalse)
4324 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4325 "CacheResourcesExhausted",
"`%s'",image->filename);
4326 return(MagickFalse);
4328 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4329 clone_info->type=DiskCache;
4330 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4331 clone_info->file=(-1);
4332 clone_info->storage_class=cache_info->storage_class;
4333 clone_info->colorspace=cache_info->colorspace;
4334 clone_info->columns=cache_info->columns;
4335 clone_info->rows=cache_info->rows;
4336 clone_info->active_index_channel=cache_info->active_index_channel;
4337 clone_info->mode=PersistMode;
4338 clone_info->length=cache_info->length;
4339 clone_info->channels=cache_info->channels;
4340 clone_info->offset=(*offset);
4341 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4342 if (status != MagickFalse)
4343 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4344 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4345 ((MagickOffsetType) cache_info->length % page_size));
4346 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4389 const ssize_t y,
const size_t columns,
const size_t rows,
4390 const MagickBooleanType clone,
NexusInfo *nexus_info,
4393 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4398 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4402 *magick_restrict cache_info;
4411 *magick_restrict pixels;
4416 assert(image != (
const Image *) NULL);
4417 assert(image->signature == MagickCoreSignature);
4418 assert(image->cache != (Cache) NULL);
4419 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4420 if (cache_info == (Cache) NULL)
4422 assert(cache_info->signature == MagickCoreSignature);
4423 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4424 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4425 (y >= (ssize_t) cache_info->rows))
4427 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4428 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4431 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4433 offset=y*(MagickOffsetType) cache_info->columns+x;
4436 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4437 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4438 (MagickOffsetType) columns-1;
4439 if ((MagickSizeType) offset >= number_pixels)
4444 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4445 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4446 MagickTrue : MagickFalse,nexus_info,exception);
4484 const ssize_t y,
const size_t columns,
const size_t rows,
4488 *magick_restrict cache_info;
4491 id = GetOpenMPThreadId();
4493 assert(image != (
const Image *) NULL);
4494 assert(image->signature == MagickCoreSignature);
4495 assert(image->cache != (Cache) NULL);
4497 assert(cache_info->signature == MagickCoreSignature);
4498 assert(
id < (
int) cache_info->number_threads);
4499 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4500 cache_info->nexus_info[
id],exception));
4559MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4560 const ssize_t y,
const size_t columns,
const size_t rows,
4564 *magick_restrict cache_info;
4567 id = GetOpenMPThreadId();
4569 assert(image != (
Image *) NULL);
4570 assert(image->signature == MagickCoreSignature);
4571 assert(image->cache != (Cache) NULL);
4573 assert(cache_info->signature == MagickCoreSignature);
4574 if (cache_info->methods.queue_authentic_pixels_handler !=
4575 (QueueAuthenticPixelsHandler) NULL)
4576 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4578 assert(
id < (
int) cache_info->number_threads);
4579 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4580 cache_info->nexus_info[
id],exception));
4612static inline MagickOffsetType ReadPixelCacheRegion(
4613 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4614 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4622#if !defined(MAGICKCORE_HAVE_PREAD)
4623 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4624 return((MagickOffsetType) -1);
4626 for (i=0; i < (MagickOffsetType) length; i+=count)
4628#if !defined(MAGICKCORE_HAVE_PREAD)
4629 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4630 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4632 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4633 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4645static MagickBooleanType ReadPixelCacheIndexes(
4666 if (cache_info->active_index_channel == MagickFalse)
4667 return(MagickFalse);
4668 if (nexus_info->authentic_pixel_cache != MagickFalse)
4670 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4671 return(MagickFalse);
4672 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4673 nexus_info->region.x;
4674 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4675 rows=nexus_info->region.height;
4677 q=nexus_info->indexes;
4679 switch (cache_info->type)
4690 if ((cache_info->columns == nexus_info->region.width) &&
4691 (extent == (MagickSizeType) ((
size_t) extent)))
4696 p=cache_info->indexes+offset;
4697 for (y=0; y < (ssize_t) rows; y++)
4699 (void) memcpy(q,p,(
size_t) length);
4700 p+=(ptrdiff_t) cache_info->columns;
4701 q+=(ptrdiff_t) nexus_info->region.width;
4710 LockSemaphoreInfo(cache_info->file_semaphore);
4711 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4713 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4714 cache_info->cache_filename);
4715 UnlockSemaphoreInfo(cache_info->file_semaphore);
4716 return(MagickFalse);
4718 if ((cache_info->columns == nexus_info->region.width) &&
4719 (extent <= MagickMaxBufferExtent))
4724 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4725 for (y=0; y < (ssize_t) rows; y++)
4727 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4728 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4729 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4730 if (count < (MagickOffsetType) length)
4732 offset+=(MagickOffsetType) cache_info->columns;
4733 q+=(ptrdiff_t) nexus_info->region.width;
4735 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4736 (void) ClosePixelCacheOnDisk(cache_info);
4737 UnlockSemaphoreInfo(cache_info->file_semaphore);
4740 case DistributedCache:
4748 LockSemaphoreInfo(cache_info->file_semaphore);
4749 region=nexus_info->region;
4750 if ((cache_info->columns != nexus_info->region.width) ||
4751 (extent > MagickMaxBufferExtent))
4758 for (y=0; y < (ssize_t) rows; y++)
4761 cache_info->server_info,®ion,length,(
unsigned char *) q);
4762 if (count != (MagickOffsetType) length)
4764 q+=(ptrdiff_t) nexus_info->region.width;
4767 UnlockSemaphoreInfo(cache_info->file_semaphore);
4773 if (y < (ssize_t) rows)
4775 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4776 cache_info->cache_filename);
4777 return(MagickFalse);
4779 if ((cache_info->debug != MagickFalse) &&
4780 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4781 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4782 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4783 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4784 nexus_info->region.x,(
double) nexus_info->region.y);
4816static MagickBooleanType ReadPixelCachePixels(
4837 if (nexus_info->authentic_pixel_cache != MagickFalse)
4839 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4840 return(MagickFalse);
4841 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4842 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4843 return(MagickFalse);
4844 offset+=nexus_info->region.x;
4845 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4846 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4847 return(MagickFalse);
4848 rows=nexus_info->region.height;
4850 if ((extent == 0) || ((extent/length) != rows))
4851 return(MagickFalse);
4852 q=nexus_info->pixels;
4854 switch (cache_info->type)
4865 if ((cache_info->columns == nexus_info->region.width) &&
4866 (extent == (MagickSizeType) ((
size_t) extent)))
4871 p=cache_info->pixels+offset;
4872 for (y=0; y < (ssize_t) rows; y++)
4874 (void) memcpy(q,p,(
size_t) length);
4875 p+=(ptrdiff_t) cache_info->columns;
4876 q+=(ptrdiff_t) nexus_info->region.width;
4885 LockSemaphoreInfo(cache_info->file_semaphore);
4886 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4888 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4889 cache_info->cache_filename);
4890 UnlockSemaphoreInfo(cache_info->file_semaphore);
4891 return(MagickFalse);
4893 if ((cache_info->columns == nexus_info->region.width) &&
4894 (extent <= MagickMaxBufferExtent))
4899 for (y=0; y < (ssize_t) rows; y++)
4901 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4902 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4903 if (count < (MagickOffsetType) length)
4905 offset+=(MagickOffsetType) cache_info->columns;
4906 q+=(ptrdiff_t) nexus_info->region.width;
4908 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4909 (void) ClosePixelCacheOnDisk(cache_info);
4910 UnlockSemaphoreInfo(cache_info->file_semaphore);
4913 case DistributedCache:
4921 LockSemaphoreInfo(cache_info->file_semaphore);
4922 region=nexus_info->region;
4923 if ((cache_info->columns != nexus_info->region.width) ||
4924 (extent > MagickMaxBufferExtent))
4931 for (y=0; y < (ssize_t) rows; y++)
4934 cache_info->server_info,®ion,length,(
unsigned char *) q);
4935 if (count != (MagickOffsetType) length)
4937 q+=(ptrdiff_t) nexus_info->region.width;
4940 UnlockSemaphoreInfo(cache_info->file_semaphore);
4946 if (y < (ssize_t) rows)
4948 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4949 cache_info->cache_filename);
4950 return(MagickFalse);
4952 if ((cache_info->debug != MagickFalse) &&
4953 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4954 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4955 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4956 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4957 nexus_info->region.x,(
double) nexus_info->region.y);
4984MagickExport Cache ReferencePixelCache(Cache cache)
4987 *magick_restrict cache_info;
4989 assert(cache != (Cache *) NULL);
4991 assert(cache_info->signature == MagickCoreSignature);
4992 LockSemaphoreInfo(cache_info->semaphore);
4993 cache_info->reference_count++;
4994 UnlockSemaphoreInfo(cache_info->semaphore);
5016MagickPrivate
void ResetCacheAnonymousMemory(
void)
5018 cache_anonymous_memory=0;
5045MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5048 *magick_restrict cache_info;
5050 GetOneAuthenticPixelFromHandler
5051 get_one_authentic_pixel_from_handler;
5053 GetOneVirtualPixelFromHandler
5054 get_one_virtual_pixel_from_handler;
5059 assert(cache != (Cache) NULL);
5062 assert(cache_info->signature == MagickCoreSignature);
5063 if (IsEventLogging() != MagickFalse)
5064 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5065 cache_info->filename);
5066 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5067 cache_info->methods.get_virtual_pixel_handler=
5068 cache_methods->get_virtual_pixel_handler;
5069 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5070 cache_info->methods.destroy_pixel_handler=
5071 cache_methods->destroy_pixel_handler;
5072 if (cache_methods->get_virtual_indexes_from_handler !=
5073 (GetVirtualIndexesFromHandler) NULL)
5074 cache_info->methods.get_virtual_indexes_from_handler=
5075 cache_methods->get_virtual_indexes_from_handler;
5076 if (cache_methods->get_authentic_pixels_handler !=
5077 (GetAuthenticPixelsHandler) NULL)
5078 cache_info->methods.get_authentic_pixels_handler=
5079 cache_methods->get_authentic_pixels_handler;
5080 if (cache_methods->queue_authentic_pixels_handler !=
5081 (QueueAuthenticPixelsHandler) NULL)
5082 cache_info->methods.queue_authentic_pixels_handler=
5083 cache_methods->queue_authentic_pixels_handler;
5084 if (cache_methods->sync_authentic_pixels_handler !=
5085 (SyncAuthenticPixelsHandler) NULL)
5086 cache_info->methods.sync_authentic_pixels_handler=
5087 cache_methods->sync_authentic_pixels_handler;
5088 if (cache_methods->get_authentic_pixels_from_handler !=
5089 (GetAuthenticPixelsFromHandler) NULL)
5090 cache_info->methods.get_authentic_pixels_from_handler=
5091 cache_methods->get_authentic_pixels_from_handler;
5092 if (cache_methods->get_authentic_indexes_from_handler !=
5093 (GetAuthenticIndexesFromHandler) NULL)
5094 cache_info->methods.get_authentic_indexes_from_handler=
5095 cache_methods->get_authentic_indexes_from_handler;
5096 get_one_virtual_pixel_from_handler=
5097 cache_info->methods.get_one_virtual_pixel_from_handler;
5098 if (get_one_virtual_pixel_from_handler !=
5099 (GetOneVirtualPixelFromHandler) NULL)
5100 cache_info->methods.get_one_virtual_pixel_from_handler=
5101 cache_methods->get_one_virtual_pixel_from_handler;
5102 get_one_authentic_pixel_from_handler=
5103 cache_methods->get_one_authentic_pixel_from_handler;
5104 if (get_one_authentic_pixel_from_handler !=
5105 (GetOneAuthenticPixelFromHandler) NULL)
5106 cache_info->methods.get_one_authentic_pixel_from_handler=
5107 cache_methods->get_one_authentic_pixel_from_handler;
5148static inline MagickBooleanType AcquireCacheNexusPixels(
5149 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5152 if (length != (MagickSizeType) ((
size_t) length))
5154 (void) ThrowMagickException(exception,GetMagickModule(),
5155 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5156 cache_info->filename);
5157 return(MagickFalse);
5159 nexus_info->length=0;
5160 nexus_info->mapped=MagickFalse;
5161 if (cache_anonymous_memory <= 0)
5163 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5164 AcquireAlignedMemory(1,(
size_t) length));
5166 (void) memset(nexus_info->cache,0,(
size_t) length);
5170 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5172 nexus_info->mapped=MagickTrue;
5176 (void) ThrowMagickException(exception,GetMagickModule(),
5177 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5178 cache_info->filename);
5179 return(MagickFalse);
5181 nexus_info->length=length;
5185static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5188 if (nexus_info->length < CACHE_LINE_SIZE)
5190 if (mode == ReadMode)
5192 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5196 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5199static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5202 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5203 return(MagickFalse);
5204 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5205 return(MagickFalse);
5210 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5211 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5212 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5222 assert(cache_info != (
const CacheInfo *) NULL);
5223 assert(cache_info->signature == MagickCoreSignature);
5224 if (cache_info->type == UndefinedCache)
5226 assert(nexus_info->signature == MagickCoreSignature);
5227 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5228 if ((width == 0) || (height == 0))
5230 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5231 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5234 if (((MagickSizeType) width > cache_info->width_limit) ||
5235 ((MagickSizeType) height > cache_info->height_limit))
5237 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5238 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5241 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5242 (ValidatePixelOffset(y,height) == MagickFalse))
5244 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5245 "InvalidPixel",
"`%s'",cache_info->filename);
5248 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5249 (buffered == MagickFalse))
5251 if (((x >= 0) && (y >= 0) &&
5252 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5253 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5254 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5262 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5264 offset=y*(MagickOffsetType) cache_info->columns+x;
5265 nexus_info->pixels=cache_info->pixels+offset;
5266 nexus_info->indexes=(IndexPacket *) NULL;
5267 if (cache_info->active_index_channel != MagickFalse)
5268 nexus_info->indexes=cache_info->indexes+offset;
5269 nexus_info->region.width=width;
5270 nexus_info->region.height=height;
5271 nexus_info->region.x=x;
5272 nexus_info->region.y=y;
5273 nexus_info->authentic_pixel_cache=MagickTrue;
5274 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5275 return(nexus_info->pixels);
5281 number_pixels=(MagickSizeType) width*height;
5282 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5284 if (cache_info->active_index_channel != MagickFalse)
5285 length+=number_pixels*
sizeof(IndexPacket);
5288 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5290 if (nexus_info->length < length)
5292 RelinquishCacheNexusPixels(nexus_info);
5293 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5295 if (status == MagickFalse)
5297 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5300 nexus_info->pixels=nexus_info->cache;
5301 nexus_info->indexes=(IndexPacket *) NULL;
5302 if (cache_info->active_index_channel != MagickFalse)
5303 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5304 nexus_info->region.width=width;
5305 nexus_info->region.height=height;
5306 nexus_info->region.x=x;
5307 nexus_info->region.y=y;
5308 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5309 MagickTrue : MagickFalse;
5310 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5311 return(nexus_info->pixels);
5342static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5343 const Quantum opacity)
5346 *magick_restrict image_view;
5354 assert(image != (
Image *) NULL);
5355 assert(image->signature == MagickCoreSignature);
5356 if (IsEventLogging() != MagickFalse)
5357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5358 assert(image->cache != (Cache) NULL);
5359 image->matte=MagickTrue;
5361 image_view=AcquireVirtualCacheView(image,&image->exception);
5362#if defined(MAGICKCORE_OPENMP_SUPPORT)
5363 #pragma omp parallel for schedule(static) shared(status) \
5364 magick_number_threads(image,image,image->rows,2)
5366 for (y=0; y < (ssize_t) image->rows; y++)
5374 if (status == MagickFalse)
5376 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5383 for (x=0; x < (ssize_t) image->columns; x++)
5388 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5390 image_view=DestroyCacheView(image_view);
5394MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5395 const VirtualPixelMethod virtual_pixel_method)
5398 *magick_restrict cache_info;
5403 assert(image != (
Image *) NULL);
5404 assert(image->signature == MagickCoreSignature);
5405 if (IsEventLogging() != MagickFalse)
5406 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5407 assert(image->cache != (Cache) NULL);
5409 assert(cache_info->signature == MagickCoreSignature);
5410 method=cache_info->virtual_pixel_method;
5411 cache_info->virtual_pixel_method=virtual_pixel_method;
5412 if ((image->columns != 0) && (image->rows != 0))
5413 switch (virtual_pixel_method)
5415 case BackgroundVirtualPixelMethod:
5417 if ((image->background_color.opacity != OpaqueOpacity) &&
5418 (image->matte == MagickFalse))
5419 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5420 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5421 (IsGrayColorspace(image->colorspace) != MagickFalse))
5422 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5425 case TransparentVirtualPixelMethod:
5427 if (image->matte == MagickFalse)
5428 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5437#if defined(MAGICKCORE_OPENCL_SUPPORT)
5461static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5466 assert(cache_info != (
CacheInfo *)NULL);
5467 if ((cache_info->type != MemoryCache) ||
5473 LockSemaphoreInfo(cache_info->semaphore);
5482 clEnv=GetDefaultOpenCLEnv();
5483 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5484 if (events != (cl_event *) NULL)
5498 context=GetOpenCLContext(clEnv);
5499 queue=AcquireOpenCLCommandQueue(clEnv);
5500 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5501 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5502 cache_info->length,event_count,events,NULL,&status);
5503 assert(pixels == cache_info->pixels);
5504 events=(cl_event *) RelinquishMagickMemory(events);
5505 RelinquishOpenCLCommandQueue(clEnv,queue);
5507 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5509 UnlockSemaphoreInfo(cache_info->semaphore);
5512MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5515 *magick_restrict cache_info;
5517 assert(image != (
Image *)NULL);
5519 CopyOpenCLBuffer(cache_info);
5552MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5556 *magick_restrict cache_info;
5564 assert(image != (
Image *) NULL);
5565 assert(image->signature == MagickCoreSignature);
5566 if (image->cache == (Cache) NULL)
5567 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5569 assert(cache_info->signature == MagickCoreSignature);
5570 if (cache_info->type == UndefinedCache)
5571 return(MagickFalse);
5572 if ((image->storage_class == DirectClass) &&
5573 (image->clip_mask != (
Image *) NULL) &&
5574 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5575 return(MagickFalse);
5576 if ((image->storage_class == DirectClass) &&
5577 (image->mask != (
Image *) NULL) &&
5578 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5579 return(MagickFalse);
5580 if (nexus_info->authentic_pixel_cache != MagickFalse)
5582 if (image->taint == MagickFalse)
5583 image->taint=MagickTrue;
5586 assert(cache_info->signature == MagickCoreSignature);
5587 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5588 if ((cache_info->active_index_channel != MagickFalse) &&
5589 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5590 return(MagickFalse);
5591 if ((status != MagickFalse) && (image->taint == MagickFalse))
5592 image->taint=MagickTrue;
5623static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5627 *magick_restrict cache_info;
5630 id = GetOpenMPThreadId();
5635 assert(image != (
Image *) NULL);
5636 assert(image->signature == MagickCoreSignature);
5637 assert(image->cache != (Cache) NULL);
5639 assert(cache_info->signature == MagickCoreSignature);
5640 assert(
id < (
int) cache_info->number_threads);
5641 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5673MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5677 *magick_restrict cache_info;
5680 id = GetOpenMPThreadId();
5685 assert(image != (
Image *) NULL);
5686 assert(image->signature == MagickCoreSignature);
5687 assert(image->cache != (Cache) NULL);
5689 assert(cache_info->signature == MagickCoreSignature);
5690 if (cache_info->methods.sync_authentic_pixels_handler !=
5691 (SyncAuthenticPixelsHandler) NULL)
5692 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5693 assert(
id < (
int) cache_info->number_threads);
5694 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5726MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5730 *magick_restrict cache_info;
5732 assert(image != (
Image *) NULL);
5734 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5735 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5766static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5786 if (cache_info->active_index_channel == MagickFalse)
5787 return(MagickFalse);
5788 if (nexus_info->authentic_pixel_cache != MagickFalse)
5790 if (nexus_info->indexes == (IndexPacket *) NULL)
5791 return(MagickFalse);
5792 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5793 return(MagickFalse);
5794 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5795 nexus_info->region.x;
5796 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5797 rows=nexus_info->region.height;
5798 extent=(MagickSizeType) length*rows;
5799 p=nexus_info->indexes;
5801 switch (cache_info->type)
5812 if ((cache_info->columns == nexus_info->region.width) &&
5813 (extent == (MagickSizeType) ((
size_t) extent)))
5818 q=cache_info->indexes+offset;
5819 for (y=0; y < (ssize_t) rows; y++)
5821 (void) memcpy(q,p,(
size_t) length);
5822 p+=(ptrdiff_t) nexus_info->region.width;
5823 q+=(ptrdiff_t) cache_info->columns;
5832 LockSemaphoreInfo(cache_info->file_semaphore);
5833 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5835 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5836 cache_info->cache_filename);
5837 UnlockSemaphoreInfo(cache_info->file_semaphore);
5838 return(MagickFalse);
5840 if ((cache_info->columns == nexus_info->region.width) &&
5841 (extent <= MagickMaxBufferExtent))
5846 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5847 for (y=0; y < (ssize_t) rows; y++)
5849 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5850 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5851 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5853 if (count < (MagickOffsetType) length)
5855 p+=(ptrdiff_t) nexus_info->region.width;
5856 offset+=(MagickOffsetType) cache_info->columns;
5858 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5859 (void) ClosePixelCacheOnDisk(cache_info);
5860 UnlockSemaphoreInfo(cache_info->file_semaphore);
5863 case DistributedCache:
5871 LockSemaphoreInfo(cache_info->file_semaphore);
5872 region=nexus_info->region;
5873 if ((cache_info->columns != nexus_info->region.width) ||
5874 (extent > MagickMaxBufferExtent))
5881 for (y=0; y < (ssize_t) rows; y++)
5884 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5885 if (count != (MagickOffsetType) length)
5887 p+=(ptrdiff_t) nexus_info->region.width;
5890 UnlockSemaphoreInfo(cache_info->file_semaphore);
5896 if (y < (ssize_t) rows)
5898 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5899 cache_info->cache_filename);
5900 return(MagickFalse);
5902 if ((cache_info->debug != MagickFalse) &&
5903 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5904 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5905 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5906 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5907 nexus_info->region.x,(
double) nexus_info->region.y);
5939static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5959 if (nexus_info->authentic_pixel_cache != MagickFalse)
5961 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5962 return(MagickFalse);
5963 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5964 nexus_info->region.x;
5965 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5966 rows=nexus_info->region.height;
5968 p=nexus_info->pixels;
5970 switch (cache_info->type)
5981 if ((cache_info->columns == nexus_info->region.width) &&
5982 (extent == (MagickSizeType) ((
size_t) extent)))
5987 q=cache_info->pixels+offset;
5988 for (y=0; y < (ssize_t) rows; y++)
5990 (void) memcpy(q,p,(
size_t) length);
5991 p+=(ptrdiff_t) nexus_info->region.width;
5992 q+=(ptrdiff_t) cache_info->columns;
6001 LockSemaphoreInfo(cache_info->file_semaphore);
6002 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6004 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6005 cache_info->cache_filename);
6006 UnlockSemaphoreInfo(cache_info->file_semaphore);
6007 return(MagickFalse);
6009 if ((cache_info->columns == nexus_info->region.width) &&
6010 (extent <= MagickMaxBufferExtent))
6015 for (y=0; y < (ssize_t) rows; y++)
6017 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6018 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6019 if (count < (MagickOffsetType) length)
6021 p+=(ptrdiff_t) nexus_info->region.width;
6022 offset+=(MagickOffsetType) cache_info->columns;
6024 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6025 (void) ClosePixelCacheOnDisk(cache_info);
6026 UnlockSemaphoreInfo(cache_info->file_semaphore);
6029 case DistributedCache:
6037 LockSemaphoreInfo(cache_info->file_semaphore);
6038 region=nexus_info->region;
6039 if ((cache_info->columns != nexus_info->region.width) ||
6040 (extent > MagickMaxBufferExtent))
6047 for (y=0; y < (ssize_t) rows; y++)
6050 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6051 if (count != (MagickOffsetType) length)
6053 p+=(ptrdiff_t) nexus_info->region.width;
6056 UnlockSemaphoreInfo(cache_info->file_semaphore);
6062 if (y < (ssize_t) rows)
6064 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6065 cache_info->cache_filename);
6066 return(MagickFalse);
6068 if ((cache_info->debug != MagickFalse) &&
6069 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6070 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6071 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6072 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6073 nexus_info->region.x,(
double) nexus_info->region.y);