43 #include "magick/studio.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/cache.h"
47 #include "magick/cache-private.h"
48 #include "magick/color-private.h"
49 #include "magick/colorspace.h"
50 #include "magick/colorspace-private.h"
51 #include "magick/composite-private.h"
52 #include "magick/distribute-cache-private.h"
53 #include "magick/exception.h"
54 #include "magick/exception-private.h"
55 #include "magick/geometry.h"
56 #include "magick/list.h"
57 #include "magick/log.h"
58 #include "magick/magick.h"
59 #include "magick/memory_.h"
60 #include "magick/memory-private.h"
61 #include "magick/nt-base-private.h"
62 #include "magick/option.h"
63 #include "magick/pixel.h"
64 #include "magick/pixel-accessor.h"
65 #include "magick/pixel-private.h"
66 #include "magick/policy.h"
67 #include "magick/quantum.h"
68 #include "magick/random_.h"
69 #include "magick/registry.h"
70 #include "magick/resource_.h"
71 #include "magick/semaphore.h"
72 #include "magick/splay-tree.h"
73 #include "magick/string_.h"
74 #include "magick/string-private.h"
75 #include "magick/thread-private.h"
76 #include "magick/timer-private.h"
77 #include "magick/utility.h"
78 #include "magick/utility-private.h"
79 #if defined(MAGICKCORE_ZLIB_DELEGATE)
86 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
87 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
88 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
103 #if defined(__cplusplus) || defined(c_plusplus)
111 static const IndexPacket
112 *GetVirtualIndexesFromCache(
const Image *);
115 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
117 *GetVirtualPixelsCache(
const Image *);
119 static MagickBooleanType
120 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,
122 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
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;
183 static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
184 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
199 magick_unreferenced(event);
200 magick_unreferenced(event_command_exec_status);
202 clEnv=GetDefaultOpenCLEnv();
203 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
211 status=clEnv->library->clGetEventInfo(info->events[i],
212 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
213 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
215 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
216 &RelinquishPixelCachePixelsDelayed,info);
221 RelinquishMagickResource(MemoryResource,info->length);
222 (void) RelinquishOpenCLCacheInfo(clEnv,info);
223 (void) RelinquishAlignedMemory(pixels);
226 static MagickBooleanType RelinquishOpenCLBuffer(
232 assert(cache_info != (
CacheInfo *) NULL);
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
240 cl_uint *event_count)
249 events=(cl_event *) NULL;
250 LockSemaphoreInfo(opencl_info->events_semaphore);
251 *event_count=opencl_info->event_count;
252 if (*event_count > 0)
254 events=(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)
294 extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
297 *magick_restrict cache_info;
302 assert(image != (
const Image *) NULL);
303 assert(event != (cl_event) NULL);
306 clEnv=GetDefaultOpenCLEnv();
307 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
309 clEnv->library->clWaitForEvents(1,&event);
312 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
313 if (cache_info->opencl->events == (cl_event *) NULL)
315 cache_info->opencl->events=(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);
352 MagickExport 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);
423 MagickExport
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;
478 MagickExport
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);
517 MagickExport MagickBooleanType CacheComponentGenesis(
void)
520 cache_semaphore=AllocateSemaphoreInfo();
542 MagickExport
void CacheComponentTerminus(
void)
545 ActivateSemaphoreInfo(&cache_semaphore);
547 DestroySemaphoreInfo(&cache_semaphore);
579 static 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);
690 MagickExport 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);
734 MagickExport
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;
781 static 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)
845 static inline int GetCacheNumberThreads(
const CacheInfo *source,
846 const CacheInfo *destination,
const size_t chunk,
const int factor)
849 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
851 workload_factor = 64UL << factor;
856 number_threads=(chunk <= workload_factor) ? 1 :
857 (chunk >= (workload_factor << 6)) ? max_threads :
858 1+(chunk-workload_factor)*(max_threads-1)/(((workload_factor << 6))-1);
862 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
863 ((destination->type != MemoryCache) && (destination->type != MapCache)))
864 number_threads=MagickMin(number_threads,4);
865 return((
int) number_threads);
868 static MagickBooleanType ClonePixelCacheRepository(
872 #define cache_number_threads(source,destination,chunk,factor) \
873 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
879 **magick_restrict cache_nexus,
880 **magick_restrict clone_nexus;
888 assert(cache_info != (
CacheInfo *) NULL);
889 assert(clone_info != (
CacheInfo *) NULL);
891 if (cache_info->type == PingCache)
893 if ((cache_info->storage_class == clone_info->storage_class) &&
894 (cache_info->colorspace == clone_info->colorspace) &&
895 (cache_info->channels == clone_info->channels) &&
896 (cache_info->columns == clone_info->columns) &&
897 (cache_info->rows == clone_info->rows) &&
898 (cache_info->active_index_channel == clone_info->active_index_channel))
903 if (((cache_info->type == MemoryCache) ||
904 (cache_info->type == MapCache)) &&
905 ((clone_info->type == MemoryCache) ||
906 (clone_info->type == MapCache)))
908 (void) memcpy(clone_info->pixels,cache_info->pixels,
909 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
910 if ((cache_info->active_index_channel != MagickFalse) &&
911 (clone_info->active_index_channel != MagickFalse))
912 (void) memcpy(clone_info->indexes,cache_info->indexes,
913 cache_info->columns*cache_info->rows*
914 sizeof(*cache_info->indexes));
917 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
918 return(ClonePixelCacheOnDisk(cache_info,clone_info));
923 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
924 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
925 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
926 sizeof(*cache_info->pixels);
928 #if defined(MAGICKCORE_OPENMP_SUPPORT)
929 #pragma omp parallel for schedule(static) shared(status) \
930 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
932 for (y=0; y < (ssize_t) cache_info->rows; y++)
935 id = GetOpenMPThreadId();
940 if (status == MagickFalse)
942 if (y >= (ssize_t) clone_info->rows)
944 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
945 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
948 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
949 if (status == MagickFalse)
951 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
952 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
955 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
956 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
957 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
959 if ((cache_info->active_index_channel != MagickFalse) &&
960 (clone_info->active_index_channel != MagickFalse))
965 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
966 sizeof(*cache_info->indexes);
967 #if defined(MAGICKCORE_OPENMP_SUPPORT)
968 #pragma omp parallel for schedule(static) shared(status) \
969 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
971 for (y=0; y < (ssize_t) cache_info->rows; y++)
974 id = GetOpenMPThreadId();
979 if (status == MagickFalse)
981 if (y >= (ssize_t) clone_info->rows)
983 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
984 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
987 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
988 if (status == MagickFalse)
990 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
991 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
994 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
995 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
998 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
999 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
1000 if (cache_info->debug != MagickFalse)
1003 message[MaxTextExtent];
1005 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
1006 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
1007 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
1008 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1035 static void DestroyImagePixelCache(
Image *image)
1037 assert(image != (
Image *) NULL);
1038 assert(image->signature == MagickCoreSignature);
1039 if (IsEventLogging() != MagickFalse)
1040 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1041 if (image->cache != (
void *) NULL)
1042 image->cache=DestroyPixelCache(image->cache);
1067 MagickExport
void DestroyImagePixels(
Image *image)
1070 *magick_restrict cache_info;
1072 assert(image != (
const Image *) NULL);
1073 assert(image->signature == MagickCoreSignature);
1074 if (IsEventLogging() != MagickFalse)
1075 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1076 assert(image->cache != (Cache) NULL);
1078 assert(cache_info->signature == MagickCoreSignature);
1079 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1081 cache_info->methods.destroy_pixel_handler(image);
1084 image->cache=DestroyPixelCache(image->cache);
1110 static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1116 if (cache_info->file != -1)
1118 status=close_utf8(cache_info->file);
1119 cache_info->file=(-1);
1120 RelinquishMagickResource(FileResource,1);
1122 return(status == -1 ? MagickFalse : MagickTrue);
1125 static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1127 switch (cache_info->type)
1131 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1132 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1133 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1139 if (cache_info->mapped == MagickFalse)
1140 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1141 cache_info->pixels);
1144 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1147 RelinquishMagickResource(MemoryResource,cache_info->length);
1152 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1154 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1155 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1156 *cache_info->cache_filename=
'\0';
1157 RelinquishMagickResource(MapResource,cache_info->length);
1162 if (cache_info->file != -1)
1163 (void) ClosePixelCacheOnDisk(cache_info);
1164 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1165 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1166 *cache_info->cache_filename=
'\0';
1167 RelinquishMagickResource(DiskResource,cache_info->length);
1170 case DistributedCache:
1172 *cache_info->cache_filename=
'\0';
1174 cache_info->server_info);
1180 cache_info->type=UndefinedCache;
1181 cache_info->mapped=MagickFalse;
1182 cache_info->indexes=(IndexPacket *) NULL;
1185 MagickExport Cache DestroyPixelCache(Cache cache)
1188 *magick_restrict cache_info;
1190 assert(cache != (Cache) NULL);
1192 assert(cache_info->signature == MagickCoreSignature);
1193 if (IsEventLogging() != MagickFalse)
1194 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1195 cache_info->filename);
1196 LockSemaphoreInfo(cache_info->semaphore);
1197 cache_info->reference_count--;
1198 if (cache_info->reference_count != 0)
1200 UnlockSemaphoreInfo(cache_info->semaphore);
1201 return((Cache) NULL);
1203 UnlockSemaphoreInfo(cache_info->semaphore);
1204 if (cache_info->debug != MagickFalse)
1207 message[MaxTextExtent];
1209 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1210 cache_info->filename);
1211 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1213 RelinquishPixelCachePixels(cache_info);
1216 cache_info->server_info);
1217 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1218 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1219 cache_info->number_threads);
1220 if (cache_info->random_info != (
RandomInfo *) NULL)
1221 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1223 DestroySemaphoreInfo(&cache_info->file_semaphore);
1225 DestroySemaphoreInfo(&cache_info->semaphore);
1226 cache_info->signature=(~MagickCoreSignature);
1227 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1258 static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1260 if (nexus_info->mapped == MagickFalse)
1261 (void) RelinquishAlignedMemory(nexus_info->cache);
1263 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1266 nexus_info->indexes=(IndexPacket *) NULL;
1267 nexus_info->length=0;
1268 nexus_info->mapped=MagickFalse;
1272 const size_t number_threads)
1277 assert(nexus_info != (
NexusInfo **) NULL);
1278 for (i=0; i < (ssize_t) (2*number_threads); i++)
1281 RelinquishCacheNexusPixels(nexus_info[i]);
1282 nexus_info[i]->signature=(~MagickCoreSignature);
1284 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1285 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1312 static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1315 *magick_restrict cache_info;
1318 id = GetOpenMPThreadId();
1320 assert(image != (
const Image *) NULL);
1321 assert(image->signature == MagickCoreSignature);
1322 assert(image->cache != (Cache) NULL);
1324 assert(cache_info->signature == MagickCoreSignature);
1325 assert(
id < (
int) cache_info->number_threads);
1326 return(cache_info->nexus_info[
id]->indexes);
1354 MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1357 *magick_restrict cache_info;
1360 id = GetOpenMPThreadId();
1362 assert(image != (
const Image *) NULL);
1363 assert(image->signature == MagickCoreSignature);
1364 assert(image->cache != (Cache) NULL);
1366 assert(cache_info->signature == MagickCoreSignature);
1367 if (cache_info->methods.get_authentic_indexes_from_handler !=
1368 (GetAuthenticIndexesFromHandler) NULL)
1369 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1370 assert(
id < (
int) cache_info->number_threads);
1371 return(cache_info->nexus_info[
id]->indexes);
1374 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1398 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1402 *magick_restrict cache_info;
1413 assert(image != (
const Image *) NULL);
1415 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1417 SyncImagePixelCache((
Image *) image,exception);
1420 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1421 return((cl_mem) NULL);
1422 LockSemaphoreInfo(cache_info->semaphore);
1423 clEnv=GetDefaultOpenCLEnv();
1426 assert(cache_info->pixels != NULL);
1427 context=GetOpenCLContext(clEnv);
1429 sizeof(*cache_info->opencl));
1430 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1431 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1432 cache_info->opencl->length=cache_info->length;
1433 cache_info->opencl->pixels=cache_info->pixels;
1434 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1435 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1436 if (status != CL_SUCCESS)
1437 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1440 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1441 UnlockSemaphoreInfo(cache_info->semaphore);
1443 return((cl_mem) NULL);
1444 return(cache_info->opencl->buffer);
1484 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1488 *magick_restrict cache_info;
1491 *magick_restrict pixels;
1496 assert(image != (
Image *) NULL);
1497 assert(image->signature == MagickCoreSignature);
1498 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1499 nexus_info,exception);
1503 assert(cache_info->signature == MagickCoreSignature);
1504 if (nexus_info->authentic_pixel_cache != MagickFalse)
1506 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1508 if (cache_info->active_index_channel != MagickFalse)
1509 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1540 *magick_restrict cache_info;
1543 id = GetOpenMPThreadId();
1545 assert(image != (
const Image *) NULL);
1546 assert(image->signature == MagickCoreSignature);
1547 assert(image->cache != (Cache) NULL);
1549 assert(cache_info->signature == MagickCoreSignature);
1550 assert(
id < (
int) cache_info->number_threads);
1551 return(cache_info->nexus_info[
id]->pixels);
1580 *magick_restrict cache_info;
1583 id = GetOpenMPThreadId();
1585 assert(image != (
const Image *) NULL);
1586 assert(image->signature == MagickCoreSignature);
1587 assert(image->cache != (Cache) NULL);
1589 assert(cache_info->signature == MagickCoreSignature);
1590 if (cache_info->methods.get_authentic_pixels_from_handler !=
1591 (GetAuthenticPixelsFromHandler) NULL)
1592 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1593 assert(
id < (
int) cache_info->number_threads);
1594 return(cache_info->nexus_info[
id]->pixels);
1644 const ssize_t y,
const size_t columns,
const size_t rows,
1648 *magick_restrict cache_info;
1651 id = GetOpenMPThreadId();
1653 assert(image != (
Image *) NULL);
1654 assert(image->signature == MagickCoreSignature);
1655 assert(image->cache != (Cache) NULL);
1657 assert(cache_info->signature == MagickCoreSignature);
1658 if (cache_info->methods.get_authentic_pixels_handler !=
1659 (GetAuthenticPixelsHandler) NULL)
1660 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1662 assert(
id < (
int) cache_info->number_threads);
1663 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1664 cache_info->nexus_info[
id],exception));
1699 const ssize_t y,
const size_t columns,
const size_t rows,
1703 *magick_restrict cache_info;
1706 id = GetOpenMPThreadId();
1708 assert(image != (
const Image *) NULL);
1709 assert(image->signature == MagickCoreSignature);
1710 assert(image->cache != (Cache) NULL);
1712 if (cache_info == (Cache) NULL)
1714 assert(cache_info->signature == MagickCoreSignature);
1715 assert(
id < (
int) cache_info->number_threads);
1716 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1717 cache_info->nexus_info[
id],exception));
1743 MagickExport MagickSizeType GetImageExtent(
const Image *image)
1746 *magick_restrict cache_info;
1749 id = GetOpenMPThreadId();
1751 assert(image != (
Image *) NULL);
1752 assert(image->signature == MagickCoreSignature);
1753 if (IsEventLogging() != MagickFalse)
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1755 assert(image->cache != (Cache) NULL);
1757 assert(cache_info->signature == MagickCoreSignature);
1758 assert(
id < (
int) cache_info->number_threads);
1759 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1762 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1790 extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1791 cl_uint *event_count)
1794 *magick_restrict cache_info;
1799 assert(image != (
const Image *) NULL);
1800 assert(event_count != (cl_uint *) NULL);
1803 events=(cl_event *) NULL;
1805 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1840 static inline MagickBooleanType ValidatePixelCacheMorphology(
1841 const Image *magick_restrict image)
1844 *magick_restrict cache_info;
1850 if ((image->storage_class != cache_info->storage_class) ||
1851 (image->colorspace != cache_info->colorspace) ||
1852 (image->channels != cache_info->channels) ||
1853 (image->columns != cache_info->columns) ||
1854 (image->rows != cache_info->rows) ||
1855 (cache_info->nexus_info == (
NexusInfo **) NULL))
1856 return(MagickFalse);
1860 static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1864 *magick_restrict cache_info;
1868 status = MagickTrue;
1870 static MagickSizeType
1871 cpu_throttle = MagickResourceInfinity,
1874 if (IsImageTTLExpired(image) != MagickFalse)
1879 (void) ThrowMagickException(exception,GetMagickModule(),
1880 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1881 return((Cache) NULL);
1883 if (cpu_throttle == MagickResourceInfinity)
1884 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1885 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1886 MagickDelay(cpu_throttle);
1887 LockSemaphoreInfo(image->semaphore);
1888 assert(image->cache != (Cache) NULL);
1890 #
if defined(MAGICKCORE_OPENCL_SUPPORT)
1891 CopyOpenCLBuffer(cache_info);
1893 destroy=MagickFalse;
1894 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1896 LockSemaphoreInfo(cache_info->semaphore);
1897 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1908 clone_image=(*image);
1909 clone_image.semaphore=AllocateSemaphoreInfo();
1910 clone_image.reference_count=1;
1911 clone_image.cache=ClonePixelCache(cache_info);
1912 clone_info=(
CacheInfo *) clone_image.cache;
1913 status=OpenPixelCache(&clone_image,IOMode,exception);
1914 if (status == MagickFalse)
1915 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1918 if (clone != MagickFalse)
1919 status=ClonePixelCacheRepository(clone_info,cache_info,
1921 if (status == MagickFalse)
1922 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1926 image->cache=clone_info;
1929 DestroySemaphoreInfo(&clone_image.semaphore);
1931 UnlockSemaphoreInfo(cache_info->semaphore);
1933 if (destroy != MagickFalse)
1934 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1935 if (status != MagickFalse)
1940 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1942 status=OpenPixelCache(image,IOMode,exception);
1944 if (cache_info->file != -1)
1945 (void) ClosePixelCacheOnDisk(cache_info);
1948 UnlockSemaphoreInfo(image->semaphore);
1949 if (status == MagickFalse)
1950 return((Cache) NULL);
1951 return(image->cache);
1978 MagickExport CacheType GetPixelCacheType(
const Image *image)
1980 return(GetImagePixelCacheType(image));
1983 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1986 *magick_restrict cache_info;
1988 assert(image != (
Image *) NULL);
1989 assert(image->signature == MagickCoreSignature);
1990 assert(image->cache != (Cache) NULL);
1992 assert(cache_info->signature == MagickCoreSignature);
1993 return(cache_info->type);
2026 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2030 *magick_restrict cache_info;
2033 *magick_restrict pixels;
2035 assert(image != (
Image *) NULL);
2036 assert(image->signature == MagickCoreSignature);
2037 assert(image->cache != (Cache) NULL);
2039 assert(cache_info->signature == MagickCoreSignature);
2040 *pixel=image->background_color;
2041 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2042 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2043 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2045 return(MagickFalse);
2081 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2085 *magick_restrict cache_info;
2088 id = GetOpenMPThreadId();
2091 *magick_restrict pixels;
2093 assert(image != (
const Image *) NULL);
2094 assert(image->signature == MagickCoreSignature);
2095 assert(image->cache != (Cache) NULL);
2097 assert(cache_info->signature == MagickCoreSignature);
2098 *pixel=image->background_color;
2099 assert(
id < (
int) cache_info->number_threads);
2100 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2101 cache_info->nexus_info[
id],exception);
2103 return(MagickFalse);
2140 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2145 *magick_restrict cache_info;
2148 id = GetOpenMPThreadId();
2151 *magick_restrict indexes;
2154 *magick_restrict pixels;
2156 assert(image != (
const Image *) NULL);
2157 assert(image->signature == MagickCoreSignature);
2158 assert(image->cache != (Cache) NULL);
2160 assert(cache_info->signature == MagickCoreSignature);
2161 assert(
id < (
int) cache_info->number_threads);
2162 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2163 1UL,1UL,cache_info->nexus_info[
id],exception);
2164 GetMagickPixelPacket(image,pixel);
2166 return(MagickFalse);
2167 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2168 SetMagickPixelPacket(image,pixels,indexes,pixel);
2207 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2208 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2212 *magick_restrict cache_info;
2215 id = GetOpenMPThreadId();
2218 *magick_restrict pixels;
2220 assert(image != (
const Image *) NULL);
2221 assert(image->signature == MagickCoreSignature);
2222 assert(image->cache != (Cache) NULL);
2224 assert(cache_info->signature == MagickCoreSignature);
2225 *pixel=image->background_color;
2226 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2227 (GetOneVirtualPixelFromHandler) NULL)
2228 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2229 virtual_pixel_method,x,y,pixel,exception));
2230 assert(
id < (
int) cache_info->number_threads);
2231 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2232 cache_info->nexus_info[
id],exception);
2234 return(MagickFalse);
2270 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2274 *magick_restrict cache_info;
2277 id = GetOpenMPThreadId();
2280 *magick_restrict pixels;
2282 assert(image != (
const Image *) NULL);
2283 assert(image->signature == MagickCoreSignature);
2284 assert(image->cache != (Cache) NULL);
2286 assert(cache_info->signature == MagickCoreSignature);
2287 *pixel=image->background_color;
2288 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2289 (GetOneVirtualPixelFromHandler) NULL)
2290 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2291 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2292 assert(
id < (
int) cache_info->number_threads);
2293 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2294 1UL,1UL,cache_info->nexus_info[
id],exception);
2296 return(MagickFalse);
2335 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2336 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2340 *magick_restrict cache_info;
2343 id = GetOpenMPThreadId();
2346 *magick_restrict pixels;
2348 assert(image != (
const Image *) NULL);
2349 assert(image->signature == MagickCoreSignature);
2350 assert(image->cache != (Cache) NULL);
2352 assert(cache_info->signature == MagickCoreSignature);
2353 assert(
id < (
int) cache_info->number_threads);
2354 *pixel=image->background_color;
2355 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2356 cache_info->nexus_info[
id],exception);
2358 return(MagickFalse);
2388 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2391 *magick_restrict cache_info;
2393 assert(cache != (Cache) NULL);
2395 assert(cache_info->signature == MagickCoreSignature);
2396 if (IsEventLogging() != MagickFalse)
2397 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2398 cache_info->filename);
2399 return(cache_info->channels);
2424 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2427 *magick_restrict cache_info;
2429 assert(cache != (Cache) NULL);
2431 assert(cache_info->signature == MagickCoreSignature);
2432 if (IsEventLogging() != MagickFalse)
2433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2434 cache_info->filename);
2435 return(cache_info->colorspace);
2461 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2464 *magick_restrict cache_info;
2466 assert(image != (
const Image *) NULL);
2467 assert(image->signature == MagickCoreSignature);
2468 assert(image->cache != (Cache) NULL);
2470 assert(cache_info->signature == MagickCoreSignature);
2471 return(cache_info->cache_filename);
2496 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2499 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2500 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2501 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2502 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2503 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2504 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2505 cache_methods->get_authentic_indexes_from_handler=
2506 GetAuthenticIndexesFromCache;
2507 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2508 cache_methods->get_one_authentic_pixel_from_handler=
2509 GetOneAuthenticPixelFromCache;
2510 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2511 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2512 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2539 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2543 *magick_restrict cache_info;
2548 assert(cache != NULL);
2550 assert(cache_info->signature == MagickCoreSignature);
2551 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2553 return((MagickSizeType) cache_info->columns*cache_info->rows);
2584 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2588 *magick_restrict cache_info;
2590 assert(image != (
const Image *) NULL);
2591 assert(image->signature == MagickCoreSignature);
2592 assert(image->cache != (Cache) NULL);
2593 assert(length != (MagickSizeType *) NULL);
2595 assert(exception->signature == MagickCoreSignature);
2597 assert(cache_info->signature == MagickCoreSignature);
2599 *length=cache_info->length;
2600 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2601 return((
void *) NULL);
2602 return((
void *) cache_info->pixels);
2629 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2632 *magick_restrict cache_info;
2634 assert(cache != (Cache) NULL);
2636 assert(cache_info->signature == MagickCoreSignature);
2637 if (IsEventLogging() != MagickFalse)
2638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2639 cache_info->filename);
2640 return(cache_info->storage_class);
2670 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2673 assert(image != (
Image *) NULL);
2674 assert(image->signature == MagickCoreSignature);
2675 if (IsEventLogging() != MagickFalse)
2676 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2678 if (GetImagePixelCacheType(image) == DiskCache)
2707 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2710 *magick_restrict cache_info;
2712 assert(image != (
Image *) NULL);
2713 assert(image->signature == MagickCoreSignature);
2714 assert(image->cache != (Cache) NULL);
2716 assert(cache_info->signature == MagickCoreSignature);
2717 return(cache_info->virtual_pixel_method);
2743 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2746 *magick_restrict cache_info;
2749 id = GetOpenMPThreadId();
2751 assert(image != (
const Image *) NULL);
2752 assert(image->signature == MagickCoreSignature);
2753 assert(image->cache != (Cache) NULL);
2755 assert(cache_info->signature == MagickCoreSignature);
2756 assert(
id < (
int) cache_info->number_threads);
2757 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2786 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2790 *magick_restrict cache_info;
2792 assert(cache != (Cache) NULL);
2794 assert(cache_info->signature == MagickCoreSignature);
2795 if (cache_info->storage_class == UndefinedClass)
2796 return((IndexPacket *) NULL);
2797 return(nexus_info->indexes);
2825 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2828 *magick_restrict cache_info;
2831 id = GetOpenMPThreadId();
2833 assert(image != (
const Image *) NULL);
2834 assert(image->signature == MagickCoreSignature);
2835 assert(image->cache != (Cache) NULL);
2837 assert(cache_info->signature == MagickCoreSignature);
2838 if (cache_info->methods.get_virtual_indexes_from_handler !=
2839 (GetVirtualIndexesFromHandler) NULL)
2844 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2845 if (indexes != (IndexPacket *) NULL)
2848 assert(
id < (
int) cache_info->number_threads);
2849 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2892 0, 48, 12, 60, 3, 51, 15, 63,
2893 32, 16, 44, 28, 35, 19, 47, 31,
2894 8, 56, 4, 52, 11, 59, 7, 55,
2895 40, 24, 36, 20, 43, 27, 39, 23,
2896 2, 50, 14, 62, 1, 49, 13, 61,
2897 34, 18, 46, 30, 33, 17, 45, 29,
2898 10, 58, 6, 54, 9, 57, 5, 53,
2899 42, 26, 38, 22, 41, 25, 37, 21
2902 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2907 index=x+DitherMatrix[x & 0x07]-32L;
2910 if (index >= (ssize_t) columns)
2911 return((ssize_t) columns-1L);
2915 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2920 index=y+DitherMatrix[y & 0x07]-32L;
2923 if (index >= (ssize_t) rows)
2924 return((ssize_t) rows-1L);
2928 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2932 if (x >= (ssize_t) columns)
2933 return((ssize_t) (columns-1));
2937 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2941 if (y >= (ssize_t) rows)
2942 return((ssize_t) (rows-1));
2946 static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2949 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2950 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2951 return(MagickFalse);
2955 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2957 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2960 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2962 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2965 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2966 const size_t extent)
2971 modulo.quotient=offset;
2975 modulo.quotient=offset/((ssize_t) extent);
2976 modulo.remainder=offset % ((ssize_t) extent);
2978 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2981 modulo.remainder+=((ssize_t) extent);
2986 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2987 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2988 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2992 *magick_restrict cache_info;
2995 *magick_restrict virtual_indexes;
3002 *magick_restrict indexes;
3012 *magick_restrict virtual_nexus;
3015 *magick_restrict pixels,
3026 assert(image != (
const Image *) NULL);
3027 assert(image->signature == MagickCoreSignature);
3028 assert(image->cache != (Cache) NULL);
3030 assert(cache_info->signature == MagickCoreSignature);
3031 if (cache_info->type == UndefinedCache)
3033 #if defined(MAGICKCORE_OPENCL_SUPPORT)
3034 CopyOpenCLBuffer(cache_info);
3036 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3037 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3038 MagickTrue : MagickFalse,nexus_info,exception);
3041 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3043 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3044 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3046 offset+=nexus_info->region.x;
3047 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3048 nexus_info->region.width-1L;
3049 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3050 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3051 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3052 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3060 if (nexus_info->authentic_pixel_cache != MagickFalse)
3062 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3063 if (status == MagickFalse)
3065 if ((cache_info->storage_class == PseudoClass) ||
3066 (cache_info->colorspace == CMYKColorspace))
3068 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3069 if (status == MagickFalse)
3077 virtual_nexus=nexus_info->virtual_nexus;
3079 indexes=nexus_info->indexes;
3080 switch (virtual_pixel_method)
3082 case BlackVirtualPixelMethod:
3084 SetPixelRed(&virtual_pixel,0);
3085 SetPixelGreen(&virtual_pixel,0);
3086 SetPixelBlue(&virtual_pixel,0);
3087 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3090 case GrayVirtualPixelMethod:
3092 SetPixelRed(&virtual_pixel,QuantumRange/2);
3093 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3094 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3095 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3098 case TransparentVirtualPixelMethod:
3100 SetPixelRed(&virtual_pixel,0);
3101 SetPixelGreen(&virtual_pixel,0);
3102 SetPixelBlue(&virtual_pixel,0);
3103 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3106 case MaskVirtualPixelMethod:
3107 case WhiteVirtualPixelMethod:
3109 SetPixelRed(&virtual_pixel,QuantumRange);
3110 SetPixelGreen(&virtual_pixel,QuantumRange);
3111 SetPixelBlue(&virtual_pixel,QuantumRange);
3112 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3117 virtual_pixel=image->background_color;
3121 virtual_index=(IndexPacket) 0;
3122 for (v=0; v < (ssize_t) rows; v++)
3128 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3129 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3130 y_offset=EdgeY(y_offset,cache_info->rows);
3131 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3137 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3138 (ssize_t) columns-u);
3139 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3140 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3150 length=(MagickSizeType) 1;
3151 switch (virtual_pixel_method)
3153 case BackgroundVirtualPixelMethod:
3154 case ConstantVirtualPixelMethod:
3155 case BlackVirtualPixelMethod:
3156 case GrayVirtualPixelMethod:
3157 case TransparentVirtualPixelMethod:
3158 case MaskVirtualPixelMethod:
3159 case WhiteVirtualPixelMethod:
3162 virtual_indexes=(&virtual_index);
3165 case EdgeVirtualPixelMethod:
3168 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3169 EdgeX(x_offset,cache_info->columns),
3170 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3172 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3176 case RandomVirtualPixelMethod:
3178 if (cache_info->random_info == (
RandomInfo *) NULL)
3179 cache_info->random_info=AcquireRandomInfo();
3180 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3181 RandomX(cache_info->random_info,cache_info->columns),
3182 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3183 virtual_nexus,exception);
3184 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3188 case DitherVirtualPixelMethod:
3190 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3191 DitherX(x_offset,cache_info->columns),
3192 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3194 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3198 case TileVirtualPixelMethod:
3200 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3201 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3202 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3203 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3205 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3209 case MirrorVirtualPixelMethod:
3211 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3212 if ((x_modulo.quotient & 0x01) == 1L)
3213 x_modulo.remainder=(ssize_t) cache_info->columns-
3214 x_modulo.remainder-1L;
3215 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3216 if ((y_modulo.quotient & 0x01) == 1L)
3217 y_modulo.remainder=(ssize_t) cache_info->rows-
3218 y_modulo.remainder-1L;
3219 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3220 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3222 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3226 case CheckerTileVirtualPixelMethod:
3228 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3229 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3230 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3233 virtual_indexes=(&virtual_index);
3236 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3237 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3239 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3243 case HorizontalTileVirtualPixelMethod:
3245 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3248 virtual_indexes=(&virtual_index);
3251 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3252 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3253 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3254 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3256 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3260 case VerticalTileVirtualPixelMethod:
3262 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3265 virtual_indexes=(&virtual_index);
3268 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3269 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3270 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3271 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3273 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3277 case HorizontalTileEdgeVirtualPixelMethod:
3279 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3280 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3281 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3282 virtual_nexus,exception);
3283 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3287 case VerticalTileEdgeVirtualPixelMethod:
3289 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3290 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3291 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3292 virtual_nexus,exception);
3293 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3301 if ((indexes != (IndexPacket *) NULL) &&
3302 (virtual_indexes != (
const IndexPacket *) NULL))
3303 *indexes++=(*virtual_indexes);
3309 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3310 (
size_t) length,1UL,virtual_nexus,exception);
3313 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3314 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3315 q+=(ptrdiff_t) length;
3316 if ((indexes != (IndexPacket *) NULL) &&
3317 (virtual_indexes != (
const IndexPacket *) NULL))
3319 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3320 sizeof(*virtual_indexes));
3324 if (u < (ssize_t) columns)
3330 if (v < (ssize_t) rows)
3370 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3371 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3374 *magick_restrict cache_info;
3377 id = GetOpenMPThreadId();
3379 assert(image != (
const Image *) NULL);
3380 assert(image->signature == MagickCoreSignature);
3381 assert(image->cache != (Cache) NULL);
3383 assert(cache_info->signature == MagickCoreSignature);
3384 assert(
id < (
int) cache_info->number_threads);
3385 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3386 cache_info->nexus_info[
id],exception));
3415 *magick_restrict cache_info;
3418 id = GetOpenMPThreadId();
3420 assert(image != (
const Image *) NULL);
3421 assert(image->signature == MagickCoreSignature);
3422 assert(image->cache != (Cache) NULL);
3424 assert(cache_info->signature == MagickCoreSignature);
3425 if (cache_info->methods.get_virtual_pixels_handler !=
3426 (GetVirtualPixelsHandler) NULL)
3427 return(cache_info->methods.get_virtual_pixels_handler(image));
3428 assert(
id < (
int) cache_info->number_threads);
3429 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3481 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3485 *magick_restrict cache_info;
3488 id = GetOpenMPThreadId();
3490 assert(image != (
const Image *) NULL);
3491 assert(image->signature == MagickCoreSignature);
3492 assert(image->cache != (Cache) NULL);
3494 assert(cache_info->signature == MagickCoreSignature);
3495 if (cache_info->methods.get_virtual_pixel_handler !=
3496 (GetVirtualPixelHandler) NULL)
3497 return(cache_info->methods.get_virtual_pixel_handler(image,
3498 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3499 assert(
id < (
int) cache_info->number_threads);
3500 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3501 columns,rows,cache_info->nexus_info[
id],exception));
3530 *magick_restrict cache_info;
3533 id = GetOpenMPThreadId();
3535 assert(image != (
const Image *) NULL);
3536 assert(image->signature == MagickCoreSignature);
3537 assert(image->cache != (Cache) NULL);
3539 assert(cache_info->signature == MagickCoreSignature);
3540 assert(
id < (
int) cache_info->number_threads);
3541 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3570 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3574 *magick_restrict cache_info;
3576 assert(cache != (Cache) NULL);
3578 assert(cache_info->signature == MagickCoreSignature);
3579 if (cache_info->storage_class == UndefinedClass)
3621 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3626 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3627 gamma=MagickSafeReciprocal(gamma);
3628 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3629 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3630 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3631 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3632 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3635 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3639 *magick_restrict cache_info;
3645 *magick_restrict nexus_indexes,
3646 *magick_restrict indexes;
3656 **magick_restrict mask_nexus;
3668 if (IsEventLogging() != MagickFalse)
3669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3670 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3672 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3675 if (cache_info == (Cache) NULL)
3676 return(MagickFalse);
3677 mask_nexus=AcquirePixelCacheNexus(1);
3678 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3679 nexus_info->virtual_nexus,exception);
3680 indexes=nexus_info->virtual_nexus->indexes;
3681 q=nexus_info->pixels;
3682 nexus_indexes=nexus_info->indexes;
3683 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3684 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3685 nexus_info->region.height,mask_nexus[0],&image->exception);
3688 return(MagickFalse);
3690 GetMagickPixelPacket(image,&alpha);
3691 GetMagickPixelPacket(image,&beta);
3692 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3697 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3699 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3700 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3701 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3702 alpha.opacity,&beta);
3703 SetPixelRed(q,ClampToQuantum(beta.red));
3704 SetPixelGreen(q,ClampToQuantum(beta.green));
3705 SetPixelBlue(q,ClampToQuantum(beta.blue));
3706 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3707 if (cache_info->active_index_channel != MagickFalse)
3708 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3715 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3750 static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3751 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3756 if ((count == 0) || (quantum == 0))
3758 length=count*quantum;
3759 if (quantum != (length/count))
3766 return(MagickFalse);
3769 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3778 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3780 if (*cache_info->cache_filename ==
'\0')
3781 file=AcquireUniqueFileResource(cache_info->cache_filename);
3787 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3792 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3793 O_BINARY | O_EXCL,S_MODE);
3795 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3801 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3804 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3809 return(MagickFalse);
3810 (void) AcquireMagickResource(FileResource,1);
3811 if (cache_info->file != -1)
3812 (void) ClosePixelCacheOnDisk(cache_info);
3813 cache_info->file=file;
3814 cache_info->disk_mode=mode;
3818 static inline MagickOffsetType WritePixelCacheRegion(
3819 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3820 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3828 #if !defined(MAGICKCORE_HAVE_PWRITE)
3829 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3830 return((MagickOffsetType) -1);
3832 for (i=0; i < (MagickOffsetType) length; i+=count)
3834 #if !defined(MAGICKCORE_HAVE_PWRITE)
3835 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3836 (MagickSizeType) i,MagickMaxBufferExtent));
3838 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3839 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3851 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3854 *magick_restrict cache_info;
3860 if (cache_info->debug != MagickFalse)
3863 format[MaxTextExtent],
3864 message[MaxTextExtent];
3866 (void) FormatMagickSize(length,MagickFalse,format);
3867 (void) FormatLocaleString(message,MaxTextExtent,
3868 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3869 cache_info->cache_filename,cache_info->file,format);
3870 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3872 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3874 return(MagickFalse);
3875 if ((MagickSizeType) offset < length)
3881 extent=(MagickOffsetType) length-1;
3882 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3885 return(MagickFalse);
3886 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3887 if (cache_info->synchronize != MagickFalse)
3888 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3889 return(MagickFalse);
3892 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3894 return(MagickFalse);
3898 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3902 *magick_restrict cache_info,
3906 format[MaxTextExtent],
3907 message[MaxTextExtent];
3924 assert(image != (
const Image *) NULL);
3925 assert(image->signature == MagickCoreSignature);
3926 assert(image->cache != (Cache) NULL);
3927 if (IsEventLogging() != MagickFalse)
3928 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3929 if (cache_anonymous_memory < 0)
3937 cache_anonymous_memory=0;
3938 value=GetPolicyValue(
"pixel-cache-memory");
3939 if (value == (
char *) NULL)
3940 value=GetPolicyValue(
"cache:memory-map");
3941 if (LocaleCompare(value,
"anonymous") == 0)
3943 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3944 cache_anonymous_memory=1;
3946 (void) ThrowMagickException(exception,GetMagickModule(),
3947 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3948 "'%s' (policy requires anonymous memory mapping)",image->filename);
3951 value=DestroyString(value);
3953 if ((image->columns == 0) || (image->rows == 0))
3954 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3956 assert(cache_info->signature == MagickCoreSignature);
3957 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3958 ((MagickSizeType) image->rows > cache_info->height_limit))
3959 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3961 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3963 length=GetImageListLength(image);
3964 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3965 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3968 source_info=(*cache_info);
3969 source_info.file=(-1);
3970 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3971 image->filename,(
double) image->scene);
3972 cache_info->storage_class=image->storage_class;
3973 cache_info->colorspace=image->colorspace;
3974 cache_info->rows=image->rows;
3975 cache_info->columns=image->columns;
3976 cache_info->channels=image->channels;
3977 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3978 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3979 cache_info->mode=mode;
3980 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3982 if (cache_info->active_index_channel != MagickFalse)
3983 packet_size+=
sizeof(IndexPacket);
3984 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3986 cache_info->storage_class=UndefinedClass;
3987 cache_info->length=0;
3988 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3991 columns=(size_t) (length/cache_info->rows/packet_size);
3992 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3993 ((ssize_t) cache_info->rows < 0))
3995 cache_info->storage_class=UndefinedClass;
3996 cache_info->length=0;
3997 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
4000 cache_info->length=length;
4001 if (image->ping != MagickFalse)
4003 cache_info->type=PingCache;
4006 status=AcquireMagickResource(AreaResource,(MagickSizeType)
4007 cache_info->columns*cache_info->rows);
4008 if (cache_info->mode == PersistMode)
4010 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4011 if ((status != MagickFalse) &&
4012 (length == (MagickSizeType) ((
size_t) length)) &&
4013 ((cache_info->type == UndefinedCache) ||
4014 (cache_info->type == MemoryCache)))
4016 status=AcquireMagickResource(MemoryResource,cache_info->length);
4017 if (status != MagickFalse)
4020 if (cache_anonymous_memory <= 0)
4022 cache_info->mapped=MagickFalse;
4023 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
4024 AcquireAlignedMemory(1,(
size_t) cache_info->length));
4028 cache_info->mapped=MagickTrue;
4029 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
4030 cache_info->length);
4034 cache_info->mapped=source_info.mapped;
4035 cache_info->pixels=source_info.pixels;
4042 cache_info->colorspace=image->colorspace;
4043 cache_info->type=MemoryCache;
4044 cache_info->indexes=(IndexPacket *) NULL;
4045 if (cache_info->active_index_channel != MagickFalse)
4046 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4048 if ((source_info.storage_class != UndefinedClass) &&
4051 status&=ClonePixelCacheRepository(cache_info,&source_info,
4053 RelinquishPixelCachePixels(&source_info);
4055 if (cache_info->debug != MagickFalse)
4057 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4058 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4060 (void) FormatLocaleString(message,MaxTextExtent,
4061 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4062 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4063 type,(
double) cache_info->columns,(double) cache_info->rows,
4065 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4068 cache_info->storage_class=image->storage_class;
4071 if ((source_info.storage_class != UndefinedClass) &&
4073 RelinquishPixelCachePixels(&source_info);
4074 cache_info->type=UndefinedCache;
4075 return(MagickFalse);
4081 status=AcquireMagickResource(DiskResource,cache_info->length);
4082 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4084 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4092 server_info=AcquireDistributeCacheInfo(exception);
4095 status=OpenDistributePixelCache(server_info,image);
4096 if (status == MagickFalse)
4098 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4099 GetDistributeCacheHostname(server_info));
4100 server_info=DestroyDistributeCacheInfo(server_info);
4108 cache_info->type=DistributedCache;
4109 cache_info->storage_class=image->storage_class;
4110 cache_info->colorspace=image->colorspace;
4111 cache_info->server_info=server_info;
4112 (void) FormatLocaleString(cache_info->cache_filename,
4113 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4116 cache_info->server_info));
4117 if ((source_info.storage_class != UndefinedClass) &&
4120 status=ClonePixelCacheRepository(cache_info,&source_info,
4122 RelinquishPixelCachePixels(&source_info);
4124 if (cache_info->debug != MagickFalse)
4126 (void) FormatMagickSize(cache_info->length,MagickFalse,
4128 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4130 (void) FormatLocaleString(message,MaxTextExtent,
4131 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4132 cache_info->cache_filename,GetDistributeCacheFile(
4134 (double) cache_info->columns,(
double) cache_info->rows,
4136 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4141 if ((source_info.storage_class != UndefinedClass) &&
4143 RelinquishPixelCachePixels(&source_info);
4144 cache_info->type=UndefinedCache;
4145 return(MagickFalse);
4150 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4151 RelinquishPixelCachePixels(&source_info);
4152 cache_info->type=UndefinedCache;
4153 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4154 "CacheResourcesExhausted",
"`%s'",image->filename);
4155 return(MagickFalse);
4160 if (status == MagickFalse)
4162 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4163 RelinquishPixelCachePixels(&source_info);
4164 cache_info->type=UndefinedCache;
4165 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4166 "CacheResourcesExhausted",
"`%s'",image->filename);
4167 return(MagickFalse);
4169 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4170 (cache_info->mode != PersistMode))
4172 (void) ClosePixelCacheOnDisk(cache_info);
4173 *cache_info->cache_filename=
'\0';
4175 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4177 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4178 RelinquishPixelCachePixels(&source_info);
4179 cache_info->type=UndefinedCache;
4180 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4182 return(MagickFalse);
4184 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4185 cache_info->length);
4186 if (status == MagickFalse)
4188 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4189 RelinquishPixelCachePixels(&source_info);
4190 cache_info->type=UndefinedCache;
4191 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4193 return(MagickFalse);
4195 cache_info->storage_class=image->storage_class;
4196 cache_info->colorspace=image->colorspace;
4197 cache_info->type=DiskCache;
4198 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4199 if (length == (MagickSizeType) ((size_t) length))
4201 status=AcquireMagickResource(MapResource,cache_info->length);
4202 if (status != MagickFalse)
4204 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4205 cache_info->offset,(
size_t) cache_info->length);
4208 cache_info->mapped=source_info.mapped;
4209 cache_info->pixels=source_info.pixels;
4210 RelinquishMagickResource(MapResource,cache_info->length);
4217 (void) ClosePixelCacheOnDisk(cache_info);
4218 cache_info->type=MapCache;
4219 cache_info->mapped=MagickTrue;
4220 cache_info->indexes=(IndexPacket *) NULL;
4221 if (cache_info->active_index_channel != MagickFalse)
4222 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4224 if ((source_info.storage_class != UndefinedClass) &&
4227 status=ClonePixelCacheRepository(cache_info,&source_info,
4229 RelinquishPixelCachePixels(&source_info);
4231 if (cache_info->debug != MagickFalse)
4233 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4234 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4236 (void) FormatLocaleString(message,MaxTextExtent,
4237 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4238 cache_info->filename,cache_info->cache_filename,
4239 cache_info->file,type,(
double) cache_info->columns,
4240 (double) cache_info->rows,format);
4241 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4246 if ((source_info.storage_class != UndefinedClass) &&
4248 RelinquishPixelCachePixels(&source_info);
4249 cache_info->type=UndefinedCache;
4250 return(MagickFalse);
4257 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4259 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4260 RelinquishPixelCachePixels(&source_info);
4262 if (cache_info->debug != MagickFalse)
4264 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4265 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4267 (void) FormatLocaleString(message,MaxTextExtent,
4268 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4269 cache_info->cache_filename,cache_info->file,type,(
double)
4270 cache_info->columns,(double) cache_info->rows,format);
4271 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4275 cache_info->type=UndefinedCache;
4276 return(MagickFalse);
4318 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4319 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4323 *magick_restrict cache_info,
4324 *magick_restrict clone_info;
4332 assert(image != (
Image *) NULL);
4333 assert(image->signature == MagickCoreSignature);
4334 if (IsEventLogging() != MagickFalse)
4335 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4336 assert(image->cache != (
void *) NULL);
4337 assert(filename != (
const char *) NULL);
4338 assert(offset != (MagickOffsetType *) NULL);
4339 page_size=GetMagickPageSize();
4341 assert(cache_info->signature == MagickCoreSignature);
4342 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4343 CopyOpenCLBuffer(cache_info);
4345 if (attach != MagickFalse)
4350 if (cache_info->debug != MagickFalse)
4351 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4352 "attach persistent cache");
4353 (void) CopyMagickString(cache_info->cache_filename,filename,
4355 cache_info->type=MapCache;
4356 cache_info->offset=(*offset);
4357 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4358 return(MagickFalse);
4359 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4360 ((MagickOffsetType) cache_info->length % page_size));
4366 status=AcquireMagickResource(DiskResource,cache_info->length);
4367 if (status == MagickFalse)
4369 cache_info->type=UndefinedCache;
4370 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4371 "CacheResourcesExhausted",
"`%s'",image->filename);
4372 return(MagickFalse);
4374 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4375 clone_info->type=DiskCache;
4376 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4377 clone_info->file=(-1);
4378 clone_info->storage_class=cache_info->storage_class;
4379 clone_info->colorspace=cache_info->colorspace;
4380 clone_info->columns=cache_info->columns;
4381 clone_info->rows=cache_info->rows;
4382 clone_info->active_index_channel=cache_info->active_index_channel;
4383 clone_info->mode=PersistMode;
4384 clone_info->length=cache_info->length;
4385 clone_info->channels=cache_info->channels;
4386 clone_info->offset=(*offset);
4387 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4388 if (status != MagickFalse)
4389 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4390 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4391 ((MagickOffsetType) cache_info->length % page_size));
4392 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4434 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4435 const ssize_t y,
const size_t columns,
const size_t rows,
4436 const MagickBooleanType clone,
NexusInfo *nexus_info,
4439 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4444 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4448 *magick_restrict cache_info;
4457 *magick_restrict pixels;
4462 assert(image != (
const Image *) NULL);
4463 assert(image->signature == MagickCoreSignature);
4464 assert(image->cache != (Cache) NULL);
4465 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4466 if (cache_info == (Cache) NULL)
4468 assert(cache_info->signature == MagickCoreSignature);
4469 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4470 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4471 (y >= (ssize_t) cache_info->rows))
4473 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4474 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4477 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4479 offset=y*(MagickOffsetType) cache_info->columns+x;
4482 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4483 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4484 (MagickOffsetType) columns-1;
4485 if ((MagickSizeType) offset >= number_pixels)
4490 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4491 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4492 MagickTrue : MagickFalse,nexus_info,exception);
4529 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4530 const ssize_t y,
const size_t columns,
const size_t rows,
4534 *magick_restrict cache_info;
4537 id = GetOpenMPThreadId();
4539 assert(image != (
const Image *) NULL);
4540 assert(image->signature == MagickCoreSignature);
4541 assert(image->cache != (Cache) NULL);
4543 assert(cache_info->signature == MagickCoreSignature);
4544 assert(
id < (
int) cache_info->number_threads);
4545 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4546 cache_info->nexus_info[
id],exception));
4605 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4606 const ssize_t y,
const size_t columns,
const size_t rows,
4610 *magick_restrict cache_info;
4613 id = GetOpenMPThreadId();
4615 assert(image != (
Image *) NULL);
4616 assert(image->signature == MagickCoreSignature);
4617 assert(image->cache != (Cache) NULL);
4619 assert(cache_info->signature == MagickCoreSignature);
4620 if (cache_info->methods.queue_authentic_pixels_handler !=
4621 (QueueAuthenticPixelsHandler) NULL)
4622 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4624 assert(
id < (
int) cache_info->number_threads);
4625 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4626 cache_info->nexus_info[
id],exception));
4658 static inline MagickOffsetType ReadPixelCacheRegion(
4659 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4660 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4668 #if !defined(MAGICKCORE_HAVE_PREAD)
4669 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4670 return((MagickOffsetType) -1);
4672 for (i=0; i < (MagickOffsetType) length; i+=count)
4674 #if !defined(MAGICKCORE_HAVE_PREAD)
4675 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4676 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4678 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4679 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4691 static MagickBooleanType ReadPixelCacheIndexes(
4712 if (cache_info->active_index_channel == MagickFalse)
4713 return(MagickFalse);
4714 if (nexus_info->authentic_pixel_cache != MagickFalse)
4716 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4717 return(MagickFalse);
4718 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4719 nexus_info->region.x;
4720 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4721 rows=nexus_info->region.height;
4723 q=nexus_info->indexes;
4725 switch (cache_info->type)
4736 if ((cache_info->columns == nexus_info->region.width) &&
4737 (extent == (MagickSizeType) ((
size_t) extent)))
4742 p=cache_info->indexes+offset;
4743 for (y=0; y < (ssize_t) rows; y++)
4745 (void) memcpy(q,p,(
size_t) length);
4746 p+=(ptrdiff_t) cache_info->columns;
4747 q+=(ptrdiff_t) nexus_info->region.width;
4756 LockSemaphoreInfo(cache_info->file_semaphore);
4757 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4759 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4760 cache_info->cache_filename);
4761 UnlockSemaphoreInfo(cache_info->file_semaphore);
4762 return(MagickFalse);
4764 if ((cache_info->columns == nexus_info->region.width) &&
4765 (extent <= MagickMaxBufferExtent))
4770 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4771 for (y=0; y < (ssize_t) rows; y++)
4773 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4774 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4775 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4776 if (count < (MagickOffsetType) length)
4778 offset+=(MagickOffsetType) cache_info->columns;
4779 q+=(ptrdiff_t) nexus_info->region.width;
4781 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4782 (
void) ClosePixelCacheOnDisk(cache_info);
4783 UnlockSemaphoreInfo(cache_info->file_semaphore);
4786 case DistributedCache:
4794 LockSemaphoreInfo(cache_info->file_semaphore);
4795 region=nexus_info->region;
4796 if ((cache_info->columns != nexus_info->region.width) ||
4797 (extent > MagickMaxBufferExtent))
4804 for (y=0; y < (ssize_t) rows; y++)
4807 cache_info->server_info,®ion,length,(
unsigned char *) q);
4808 if (count != (MagickOffsetType) length)
4810 q+=(ptrdiff_t) nexus_info->region.width;
4813 UnlockSemaphoreInfo(cache_info->file_semaphore);
4819 if (y < (ssize_t) rows)
4821 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4822 cache_info->cache_filename);
4823 return(MagickFalse);
4825 if ((cache_info->debug != MagickFalse) &&
4826 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4827 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4828 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4829 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4830 nexus_info->region.x,(
double) nexus_info->region.y);
4862 static MagickBooleanType ReadPixelCachePixels(
4883 if (nexus_info->authentic_pixel_cache != MagickFalse)
4885 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4886 return(MagickFalse);
4887 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4888 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4889 return(MagickFalse);
4890 offset+=nexus_info->region.x;
4891 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4892 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4893 return(MagickFalse);
4894 rows=nexus_info->region.height;
4896 if ((extent == 0) || ((extent/length) != rows))
4897 return(MagickFalse);
4898 q=nexus_info->pixels;
4900 switch (cache_info->type)
4911 if ((cache_info->columns == nexus_info->region.width) &&
4912 (extent == (MagickSizeType) ((
size_t) extent)))
4917 p=cache_info->pixels+offset;
4918 for (y=0; y < (ssize_t) rows; y++)
4920 (void) memcpy(q,p,(
size_t) length);
4921 p+=(ptrdiff_t) cache_info->columns;
4922 q+=(ptrdiff_t) nexus_info->region.width;
4931 LockSemaphoreInfo(cache_info->file_semaphore);
4932 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4934 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4935 cache_info->cache_filename);
4936 UnlockSemaphoreInfo(cache_info->file_semaphore);
4937 return(MagickFalse);
4939 if ((cache_info->columns == nexus_info->region.width) &&
4940 (extent <= MagickMaxBufferExtent))
4945 for (y=0; y < (ssize_t) rows; y++)
4947 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4948 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4949 if (count < (MagickOffsetType) length)
4951 offset+=(MagickOffsetType) cache_info->columns;
4952 q+=(ptrdiff_t) nexus_info->region.width;
4954 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4955 (
void) ClosePixelCacheOnDisk(cache_info);
4956 UnlockSemaphoreInfo(cache_info->file_semaphore);
4959 case DistributedCache:
4967 LockSemaphoreInfo(cache_info->file_semaphore);
4968 region=nexus_info->region;
4969 if ((cache_info->columns != nexus_info->region.width) ||
4970 (extent > MagickMaxBufferExtent))
4977 for (y=0; y < (ssize_t) rows; y++)
4980 cache_info->server_info,®ion,length,(
unsigned char *) q);
4981 if (count != (MagickOffsetType) length)
4983 q+=(ptrdiff_t) nexus_info->region.width;
4986 UnlockSemaphoreInfo(cache_info->file_semaphore);
4992 if (y < (ssize_t) rows)
4994 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4995 cache_info->cache_filename);
4996 return(MagickFalse);
4998 if ((cache_info->debug != MagickFalse) &&
4999 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5000 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5001 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5002 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5003 nexus_info->region.x,(
double) nexus_info->region.y);
5030 MagickExport Cache ReferencePixelCache(Cache cache)
5033 *magick_restrict cache_info;
5035 assert(cache != (Cache *) NULL);
5037 assert(cache_info->signature == MagickCoreSignature);
5038 LockSemaphoreInfo(cache_info->semaphore);
5039 cache_info->reference_count++;
5040 UnlockSemaphoreInfo(cache_info->semaphore);
5062 MagickPrivate
void ResetCacheAnonymousMemory(
void)
5064 cache_anonymous_memory=0;
5091 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5094 *magick_restrict cache_info;
5096 GetOneAuthenticPixelFromHandler
5097 get_one_authentic_pixel_from_handler;
5099 GetOneVirtualPixelFromHandler
5100 get_one_virtual_pixel_from_handler;
5105 assert(cache != (Cache) NULL);
5108 assert(cache_info->signature == MagickCoreSignature);
5109 if (IsEventLogging() != MagickFalse)
5110 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5111 cache_info->filename);
5112 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5113 cache_info->methods.get_virtual_pixel_handler=
5114 cache_methods->get_virtual_pixel_handler;
5115 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5116 cache_info->methods.destroy_pixel_handler=
5117 cache_methods->destroy_pixel_handler;
5118 if (cache_methods->get_virtual_indexes_from_handler !=
5119 (GetVirtualIndexesFromHandler) NULL)
5120 cache_info->methods.get_virtual_indexes_from_handler=
5121 cache_methods->get_virtual_indexes_from_handler;
5122 if (cache_methods->get_authentic_pixels_handler !=
5123 (GetAuthenticPixelsHandler) NULL)
5124 cache_info->methods.get_authentic_pixels_handler=
5125 cache_methods->get_authentic_pixels_handler;
5126 if (cache_methods->queue_authentic_pixels_handler !=
5127 (QueueAuthenticPixelsHandler) NULL)
5128 cache_info->methods.queue_authentic_pixels_handler=
5129 cache_methods->queue_authentic_pixels_handler;
5130 if (cache_methods->sync_authentic_pixels_handler !=
5131 (SyncAuthenticPixelsHandler) NULL)
5132 cache_info->methods.sync_authentic_pixels_handler=
5133 cache_methods->sync_authentic_pixels_handler;
5134 if (cache_methods->get_authentic_pixels_from_handler !=
5135 (GetAuthenticPixelsFromHandler) NULL)
5136 cache_info->methods.get_authentic_pixels_from_handler=
5137 cache_methods->get_authentic_pixels_from_handler;
5138 if (cache_methods->get_authentic_indexes_from_handler !=
5139 (GetAuthenticIndexesFromHandler) NULL)
5140 cache_info->methods.get_authentic_indexes_from_handler=
5141 cache_methods->get_authentic_indexes_from_handler;
5142 get_one_virtual_pixel_from_handler=
5143 cache_info->methods.get_one_virtual_pixel_from_handler;
5144 if (get_one_virtual_pixel_from_handler !=
5145 (GetOneVirtualPixelFromHandler) NULL)
5146 cache_info->methods.get_one_virtual_pixel_from_handler=
5147 cache_methods->get_one_virtual_pixel_from_handler;
5148 get_one_authentic_pixel_from_handler=
5149 cache_methods->get_one_authentic_pixel_from_handler;
5150 if (get_one_authentic_pixel_from_handler !=
5151 (GetOneAuthenticPixelFromHandler) NULL)
5152 cache_info->methods.get_one_authentic_pixel_from_handler=
5153 cache_methods->get_one_authentic_pixel_from_handler;
5194 static inline MagickBooleanType AcquireCacheNexusPixels(
5195 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5198 if (length != (MagickSizeType) ((
size_t) length))
5200 (void) ThrowMagickException(exception,GetMagickModule(),
5201 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5202 cache_info->filename);
5203 return(MagickFalse);
5205 nexus_info->length=0;
5206 nexus_info->mapped=MagickFalse;
5207 if (cache_anonymous_memory <= 0)
5209 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5210 AcquireAlignedMemory(1,(
size_t) length));
5212 (
void) memset(nexus_info->cache,0,(
size_t) length);
5216 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5218 nexus_info->mapped=MagickTrue;
5222 (void) ThrowMagickException(exception,GetMagickModule(),
5223 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5224 cache_info->filename);
5225 return(MagickFalse);
5227 nexus_info->length=length;
5231 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5234 if (nexus_info->length < CACHE_LINE_SIZE)
5236 if (mode == ReadMode)
5238 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5242 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5245 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5248 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5249 return(MagickFalse);
5250 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5251 return(MagickFalse);
5256 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5257 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5258 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5268 assert(cache_info != (
const CacheInfo *) NULL);
5269 assert(cache_info->signature == MagickCoreSignature);
5270 if (cache_info->type == UndefinedCache)
5272 assert(nexus_info->signature == MagickCoreSignature);
5273 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5274 if ((width == 0) || (height == 0))
5276 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5277 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5280 if (((MagickSizeType) width > cache_info->width_limit) ||
5281 ((MagickSizeType) height > cache_info->height_limit))
5283 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5284 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5287 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5288 (ValidatePixelOffset(y,height) == MagickFalse))
5290 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5291 "InvalidPixel",
"`%s'",cache_info->filename);
5294 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5295 (buffered == MagickFalse))
5297 if (((x >= 0) && (y >= 0) &&
5298 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5299 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5300 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5308 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5310 offset=y*(MagickOffsetType) cache_info->columns+x;
5311 nexus_info->pixels=cache_info->pixels+offset;
5312 nexus_info->indexes=(IndexPacket *) NULL;
5313 if (cache_info->active_index_channel != MagickFalse)
5314 nexus_info->indexes=cache_info->indexes+offset;
5315 nexus_info->region.width=width;
5316 nexus_info->region.height=height;
5317 nexus_info->region.x=x;
5318 nexus_info->region.y=y;
5319 nexus_info->authentic_pixel_cache=MagickTrue;
5320 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5321 return(nexus_info->pixels);
5327 number_pixels=(MagickSizeType) width*height;
5328 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5330 if (cache_info->active_index_channel != MagickFalse)
5331 length+=number_pixels*
sizeof(IndexPacket);
5334 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5336 if (nexus_info->length < length)
5338 RelinquishCacheNexusPixels(nexus_info);
5339 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5341 if (status == MagickFalse)
5343 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5346 nexus_info->pixels=nexus_info->cache;
5347 nexus_info->indexes=(IndexPacket *) NULL;
5348 if (cache_info->active_index_channel != MagickFalse)
5349 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5350 nexus_info->region.width=width;
5351 nexus_info->region.height=height;
5352 nexus_info->region.x=x;
5353 nexus_info->region.y=y;
5354 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5355 MagickTrue : MagickFalse;
5356 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5357 return(nexus_info->pixels);
5388 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5389 const Quantum opacity)
5392 *magick_restrict image_view;
5400 assert(image != (
Image *) NULL);
5401 assert(image->signature == MagickCoreSignature);
5402 if (IsEventLogging() != MagickFalse)
5403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5404 assert(image->cache != (Cache) NULL);
5405 image->matte=MagickTrue;
5407 image_view=AcquireVirtualCacheView(image,&image->exception);
5408 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5409 #pragma omp parallel for schedule(static) shared(status) \
5410 magick_number_threads(image,image,image->rows,2)
5412 for (y=0; y < (ssize_t) image->rows; y++)
5420 if (status == MagickFalse)
5422 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5429 for (x=0; x < (ssize_t) image->columns; x++)
5434 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5436 image_view=DestroyCacheView(image_view);
5440 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5441 const VirtualPixelMethod virtual_pixel_method)
5444 *magick_restrict cache_info;
5449 assert(image != (
Image *) NULL);
5450 assert(image->signature == MagickCoreSignature);
5451 if (IsEventLogging() != MagickFalse)
5452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5453 assert(image->cache != (Cache) NULL);
5455 assert(cache_info->signature == MagickCoreSignature);
5456 method=cache_info->virtual_pixel_method;
5457 cache_info->virtual_pixel_method=virtual_pixel_method;
5458 if ((image->columns != 0) && (image->rows != 0))
5459 switch (virtual_pixel_method)
5461 case BackgroundVirtualPixelMethod:
5463 if ((image->background_color.opacity != OpaqueOpacity) &&
5464 (image->matte == MagickFalse))
5465 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5466 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5467 (IsGrayColorspace(image->colorspace) != MagickFalse))
5468 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5471 case TransparentVirtualPixelMethod:
5473 if (image->matte == MagickFalse)
5474 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5483 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5507 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5512 assert(cache_info != (
CacheInfo *)NULL);
5513 if ((cache_info->type != MemoryCache) ||
5519 LockSemaphoreInfo(cache_info->semaphore);
5528 clEnv=GetDefaultOpenCLEnv();
5529 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5530 if (events != (cl_event *) NULL)
5544 context=GetOpenCLContext(clEnv);
5545 queue=AcquireOpenCLCommandQueue(clEnv);
5546 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5547 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5548 cache_info->length,event_count,events,NULL,&status);
5549 assert(pixels == cache_info->pixels);
5550 events=(cl_event *) RelinquishMagickMemory(events);
5551 RelinquishOpenCLCommandQueue(clEnv,queue);
5553 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5555 UnlockSemaphoreInfo(cache_info->semaphore);
5558 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5561 *magick_restrict cache_info;
5563 assert(image != (
Image *)NULL);
5565 CopyOpenCLBuffer(cache_info);
5598 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5602 *magick_restrict cache_info;
5610 assert(image != (
Image *) NULL);
5611 assert(image->signature == MagickCoreSignature);
5612 if (image->cache == (Cache) NULL)
5613 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5615 assert(cache_info->signature == MagickCoreSignature);
5616 if (cache_info->type == UndefinedCache)
5617 return(MagickFalse);
5618 if ((image->storage_class == DirectClass) &&
5619 (image->clip_mask != (
Image *) NULL) &&
5620 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5621 return(MagickFalse);
5622 if ((image->storage_class == DirectClass) &&
5623 (image->mask != (
Image *) NULL) &&
5624 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5625 return(MagickFalse);
5626 if (nexus_info->authentic_pixel_cache != MagickFalse)
5628 if (image->taint == MagickFalse)
5629 image->taint=MagickTrue;
5632 assert(cache_info->signature == MagickCoreSignature);
5633 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5634 if ((cache_info->active_index_channel != MagickFalse) &&
5635 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5636 return(MagickFalse);
5637 if ((status != MagickFalse) && (image->taint == MagickFalse))
5638 image->taint=MagickTrue;
5669 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5673 *magick_restrict cache_info;
5676 id = GetOpenMPThreadId();
5681 assert(image != (
Image *) NULL);
5682 assert(image->signature == MagickCoreSignature);
5683 assert(image->cache != (Cache) NULL);
5685 assert(cache_info->signature == MagickCoreSignature);
5686 assert(
id < (
int) cache_info->number_threads);
5687 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5719 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5723 *magick_restrict cache_info;
5726 id = GetOpenMPThreadId();
5731 assert(image != (
Image *) NULL);
5732 assert(image->signature == MagickCoreSignature);
5733 assert(image->cache != (Cache) NULL);
5735 assert(cache_info->signature == MagickCoreSignature);
5736 if (cache_info->methods.sync_authentic_pixels_handler !=
5737 (SyncAuthenticPixelsHandler) NULL)
5738 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5739 assert(
id < (
int) cache_info->number_threads);
5740 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5772 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5776 *magick_restrict cache_info;
5778 assert(image != (
Image *) NULL);
5780 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5781 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5812 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5832 if (cache_info->active_index_channel == MagickFalse)
5833 return(MagickFalse);
5834 if (nexus_info->authentic_pixel_cache != MagickFalse)
5836 if (nexus_info->indexes == (IndexPacket *) NULL)
5837 return(MagickFalse);
5838 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5839 return(MagickFalse);
5840 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5841 nexus_info->region.x;
5842 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5843 rows=nexus_info->region.height;
5844 extent=(MagickSizeType) length*rows;
5845 p=nexus_info->indexes;
5847 switch (cache_info->type)
5858 if ((cache_info->columns == nexus_info->region.width) &&
5859 (extent == (MagickSizeType) ((
size_t) extent)))
5864 q=cache_info->indexes+offset;
5865 for (y=0; y < (ssize_t) rows; y++)
5867 (void) memcpy(q,p,(
size_t) length);
5868 p+=(ptrdiff_t) nexus_info->region.width;
5869 q+=(ptrdiff_t) cache_info->columns;
5878 LockSemaphoreInfo(cache_info->file_semaphore);
5879 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5881 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5882 cache_info->cache_filename);
5883 UnlockSemaphoreInfo(cache_info->file_semaphore);
5884 return(MagickFalse);
5886 if ((cache_info->columns == nexus_info->region.width) &&
5887 (extent <= MagickMaxBufferExtent))
5892 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5893 for (y=0; y < (ssize_t) rows; y++)
5895 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5896 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5897 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5899 if (count < (MagickOffsetType) length)
5901 p+=(ptrdiff_t) nexus_info->region.width;
5902 offset+=(MagickOffsetType) cache_info->columns;
5904 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5905 (
void) ClosePixelCacheOnDisk(cache_info);
5906 UnlockSemaphoreInfo(cache_info->file_semaphore);
5909 case DistributedCache:
5917 LockSemaphoreInfo(cache_info->file_semaphore);
5918 region=nexus_info->region;
5919 if ((cache_info->columns != nexus_info->region.width) ||
5920 (extent > MagickMaxBufferExtent))
5927 for (y=0; y < (ssize_t) rows; y++)
5930 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5931 if (count != (MagickOffsetType) length)
5933 p+=(ptrdiff_t) nexus_info->region.width;
5936 UnlockSemaphoreInfo(cache_info->file_semaphore);
5942 if (y < (ssize_t) rows)
5944 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5945 cache_info->cache_filename);
5946 return(MagickFalse);
5948 if ((cache_info->debug != MagickFalse) &&
5949 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5950 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5951 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5952 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5953 nexus_info->region.x,(
double) nexus_info->region.y);
5985 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
6005 if (nexus_info->authentic_pixel_cache != MagickFalse)
6007 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
6008 return(MagickFalse);
6009 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
6010 nexus_info->region.x;
6011 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
6012 rows=nexus_info->region.height;
6014 p=nexus_info->pixels;
6016 switch (cache_info->type)
6027 if ((cache_info->columns == nexus_info->region.width) &&
6028 (extent == (MagickSizeType) ((
size_t) extent)))
6033 q=cache_info->pixels+offset;
6034 for (y=0; y < (ssize_t) rows; y++)
6036 (void) memcpy(q,p,(
size_t) length);
6037 p+=(ptrdiff_t) nexus_info->region.width;
6038 q+=(ptrdiff_t) cache_info->columns;
6047 LockSemaphoreInfo(cache_info->file_semaphore);
6048 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6050 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6051 cache_info->cache_filename);
6052 UnlockSemaphoreInfo(cache_info->file_semaphore);
6053 return(MagickFalse);
6055 if ((cache_info->columns == nexus_info->region.width) &&
6056 (extent <= MagickMaxBufferExtent))
6061 for (y=0; y < (ssize_t) rows; y++)
6063 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6064 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6065 if (count < (MagickOffsetType) length)
6067 p+=(ptrdiff_t) nexus_info->region.width;
6068 offset+=(MagickOffsetType) cache_info->columns;
6070 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6071 (
void) ClosePixelCacheOnDisk(cache_info);
6072 UnlockSemaphoreInfo(cache_info->file_semaphore);
6075 case DistributedCache:
6083 LockSemaphoreInfo(cache_info->file_semaphore);
6084 region=nexus_info->region;
6085 if ((cache_info->columns != nexus_info->region.width) ||
6086 (extent > MagickMaxBufferExtent))
6093 for (y=0; y < (ssize_t) rows; y++)
6096 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6097 if (count != (MagickOffsetType) length)
6099 p+=(ptrdiff_t) nexus_info->region.width;
6102 UnlockSemaphoreInfo(cache_info->file_semaphore);
6108 if (y < (ssize_t) rows)
6110 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6111 cache_info->cache_filename);
6112 return(MagickFalse);
6114 if ((cache_info->debug != MagickFalse) &&
6115 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6116 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6117 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6118 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6119 nexus_info->region.x,(
double) nexus_info->region.y);