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 (image->type != UndefinedType)
1941 image->type=UndefinedType;
1942 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1944 status=OpenPixelCache(image,IOMode,exception);
1946 if (cache_info->file != -1)
1947 (void) ClosePixelCacheOnDisk(cache_info);
1950 UnlockSemaphoreInfo(image->semaphore);
1951 if (status == MagickFalse)
1952 return((Cache) NULL);
1953 return(image->cache);
1980 MagickExport CacheType GetPixelCacheType(
const Image *image)
1982 return(GetImagePixelCacheType(image));
1985 MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1988 *magick_restrict cache_info;
1990 assert(image != (
Image *) NULL);
1991 assert(image->signature == MagickCoreSignature);
1992 assert(image->cache != (Cache) NULL);
1994 assert(cache_info->signature == MagickCoreSignature);
1995 return(cache_info->type);
2028 MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2032 *magick_restrict cache_info;
2035 *magick_restrict pixels;
2037 assert(image != (
Image *) NULL);
2038 assert(image->signature == MagickCoreSignature);
2039 assert(image->cache != (Cache) NULL);
2041 assert(cache_info->signature == MagickCoreSignature);
2042 *pixel=image->background_color;
2043 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2044 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2045 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2047 return(MagickFalse);
2083 static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2087 *magick_restrict cache_info;
2090 id = GetOpenMPThreadId();
2093 *magick_restrict pixels;
2095 assert(image != (
const Image *) NULL);
2096 assert(image->signature == MagickCoreSignature);
2097 assert(image->cache != (Cache) NULL);
2099 assert(cache_info->signature == MagickCoreSignature);
2100 *pixel=image->background_color;
2101 assert(
id < (
int) cache_info->number_threads);
2102 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2103 cache_info->nexus_info[
id],exception);
2105 return(MagickFalse);
2142 MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2147 *magick_restrict cache_info;
2150 id = GetOpenMPThreadId();
2153 *magick_restrict indexes;
2156 *magick_restrict pixels;
2158 assert(image != (
const Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(image->cache != (Cache) NULL);
2162 assert(cache_info->signature == MagickCoreSignature);
2163 assert(
id < (
int) cache_info->number_threads);
2164 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2165 1UL,1UL,cache_info->nexus_info[
id],exception);
2166 GetMagickPixelPacket(image,pixel);
2168 return(MagickFalse);
2169 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2170 SetMagickPixelPacket(image,pixels,indexes,pixel);
2209 MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2210 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2214 *magick_restrict cache_info;
2217 id = GetOpenMPThreadId();
2220 *magick_restrict pixels;
2222 assert(image != (
const Image *) NULL);
2223 assert(image->signature == MagickCoreSignature);
2224 assert(image->cache != (Cache) NULL);
2226 assert(cache_info->signature == MagickCoreSignature);
2227 *pixel=image->background_color;
2228 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2229 (GetOneVirtualPixelFromHandler) NULL)
2230 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2231 virtual_pixel_method,x,y,pixel,exception));
2232 assert(
id < (
int) cache_info->number_threads);
2233 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2234 cache_info->nexus_info[
id],exception);
2236 return(MagickFalse);
2272 MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2276 *magick_restrict cache_info;
2279 id = GetOpenMPThreadId();
2282 *magick_restrict pixels;
2284 assert(image != (
const Image *) NULL);
2285 assert(image->signature == MagickCoreSignature);
2286 assert(image->cache != (Cache) NULL);
2288 assert(cache_info->signature == MagickCoreSignature);
2289 *pixel=image->background_color;
2290 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2291 (GetOneVirtualPixelFromHandler) NULL)
2292 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2293 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2294 assert(
id < (
int) cache_info->number_threads);
2295 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2296 1UL,1UL,cache_info->nexus_info[
id],exception);
2298 return(MagickFalse);
2337 static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2338 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2342 *magick_restrict cache_info;
2345 id = GetOpenMPThreadId();
2348 *magick_restrict pixels;
2350 assert(image != (
const Image *) NULL);
2351 assert(image->signature == MagickCoreSignature);
2352 assert(image->cache != (Cache) NULL);
2354 assert(cache_info->signature == MagickCoreSignature);
2355 assert(
id < (
int) cache_info->number_threads);
2356 *pixel=image->background_color;
2357 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2358 cache_info->nexus_info[
id],exception);
2360 return(MagickFalse);
2390 MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2393 *magick_restrict cache_info;
2395 assert(cache != (Cache) NULL);
2397 assert(cache_info->signature == MagickCoreSignature);
2398 if (IsEventLogging() != MagickFalse)
2399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2400 cache_info->filename);
2401 return(cache_info->channels);
2426 MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2429 *magick_restrict cache_info;
2431 assert(cache != (Cache) NULL);
2433 assert(cache_info->signature == MagickCoreSignature);
2434 if (IsEventLogging() != MagickFalse)
2435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2436 cache_info->filename);
2437 return(cache_info->colorspace);
2463 MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2466 *magick_restrict cache_info;
2468 assert(image != (
const Image *) NULL);
2469 assert(image->signature == MagickCoreSignature);
2470 assert(image->cache != (Cache) NULL);
2472 assert(cache_info->signature == MagickCoreSignature);
2473 return(cache_info->cache_filename);
2498 MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2501 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2502 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2503 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2504 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2505 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2506 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2507 cache_methods->get_authentic_indexes_from_handler=
2508 GetAuthenticIndexesFromCache;
2509 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2510 cache_methods->get_one_authentic_pixel_from_handler=
2511 GetOneAuthenticPixelFromCache;
2512 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2513 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2514 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2541 MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2545 *magick_restrict cache_info;
2550 assert(cache != NULL);
2552 assert(cache_info->signature == MagickCoreSignature);
2553 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2555 return((MagickSizeType) cache_info->columns*cache_info->rows);
2586 MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2590 *magick_restrict cache_info;
2592 assert(image != (
const Image *) NULL);
2593 assert(image->signature == MagickCoreSignature);
2594 assert(image->cache != (Cache) NULL);
2595 assert(length != (MagickSizeType *) NULL);
2597 assert(exception->signature == MagickCoreSignature);
2599 assert(cache_info->signature == MagickCoreSignature);
2601 *length=cache_info->length;
2602 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2603 return((
void *) NULL);
2604 return((
void *) cache_info->pixels);
2631 MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2634 *magick_restrict cache_info;
2636 assert(cache != (Cache) NULL);
2638 assert(cache_info->signature == MagickCoreSignature);
2639 if (IsEventLogging() != MagickFalse)
2640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2641 cache_info->filename);
2642 return(cache_info->storage_class);
2672 MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2675 assert(image != (
Image *) NULL);
2676 assert(image->signature == MagickCoreSignature);
2677 if (IsEventLogging() != MagickFalse)
2678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2680 if (GetImagePixelCacheType(image) == DiskCache)
2709 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2712 *magick_restrict cache_info;
2714 assert(image != (
Image *) NULL);
2715 assert(image->signature == MagickCoreSignature);
2716 assert(image->cache != (Cache) NULL);
2718 assert(cache_info->signature == MagickCoreSignature);
2719 return(cache_info->virtual_pixel_method);
2745 static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2748 *magick_restrict cache_info;
2751 id = GetOpenMPThreadId();
2753 assert(image != (
const Image *) NULL);
2754 assert(image->signature == MagickCoreSignature);
2755 assert(image->cache != (Cache) NULL);
2757 assert(cache_info->signature == MagickCoreSignature);
2758 assert(
id < (
int) cache_info->number_threads);
2759 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2788 MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2792 *magick_restrict cache_info;
2794 assert(cache != (Cache) NULL);
2796 assert(cache_info->signature == MagickCoreSignature);
2797 if (cache_info->storage_class == UndefinedClass)
2798 return((IndexPacket *) NULL);
2799 return(nexus_info->indexes);
2827 MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2830 *magick_restrict cache_info;
2833 id = GetOpenMPThreadId();
2835 assert(image != (
const Image *) NULL);
2836 assert(image->signature == MagickCoreSignature);
2837 assert(image->cache != (Cache) NULL);
2839 assert(cache_info->signature == MagickCoreSignature);
2840 if (cache_info->methods.get_virtual_indexes_from_handler !=
2841 (GetVirtualIndexesFromHandler) NULL)
2846 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2847 if (indexes != (IndexPacket *) NULL)
2850 assert(
id < (
int) cache_info->number_threads);
2851 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2894 0, 48, 12, 60, 3, 51, 15, 63,
2895 32, 16, 44, 28, 35, 19, 47, 31,
2896 8, 56, 4, 52, 11, 59, 7, 55,
2897 40, 24, 36, 20, 43, 27, 39, 23,
2898 2, 50, 14, 62, 1, 49, 13, 61,
2899 34, 18, 46, 30, 33, 17, 45, 29,
2900 10, 58, 6, 54, 9, 57, 5, 53,
2901 42, 26, 38, 22, 41, 25, 37, 21
2904 static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2909 index=x+DitherMatrix[x & 0x07]-32L;
2912 if (index >= (ssize_t) columns)
2913 return((ssize_t) columns-1L);
2917 static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2922 index=y+DitherMatrix[y & 0x07]-32L;
2925 if (index >= (ssize_t) rows)
2926 return((ssize_t) rows-1L);
2930 static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2934 if (x >= (ssize_t) columns)
2935 return((ssize_t) (columns-1));
2939 static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2943 if (y >= (ssize_t) rows)
2944 return((ssize_t) (rows-1));
2948 static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2951 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2952 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2953 return(MagickFalse);
2957 static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2959 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2962 static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2964 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2967 static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2968 const size_t extent)
2973 modulo.quotient=offset;
2977 modulo.quotient=offset/((ssize_t) extent);
2978 modulo.remainder=offset % ((ssize_t) extent);
2980 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2983 modulo.remainder+=((ssize_t) extent);
2988 MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2989 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2990 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2994 *magick_restrict cache_info;
2997 *magick_restrict virtual_indexes;
3004 *magick_restrict indexes;
3014 *magick_restrict virtual_nexus;
3017 *magick_restrict pixels,
3028 assert(image != (
const Image *) NULL);
3029 assert(image->signature == MagickCoreSignature);
3030 assert(image->cache != (Cache) NULL);
3032 assert(cache_info->signature == MagickCoreSignature);
3033 if (cache_info->type == UndefinedCache)
3035 #if defined(MAGICKCORE_OPENCL_SUPPORT) 3036 CopyOpenCLBuffer(cache_info);
3038 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3039 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3040 MagickTrue : MagickFalse,nexus_info,exception);
3043 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3045 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3046 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3048 offset+=nexus_info->region.x;
3049 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3050 nexus_info->region.width-1L;
3051 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3052 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3053 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3054 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3062 if (nexus_info->authentic_pixel_cache != MagickFalse)
3064 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3065 if (status == MagickFalse)
3067 if ((cache_info->storage_class == PseudoClass) ||
3068 (cache_info->colorspace == CMYKColorspace))
3070 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3071 if (status == MagickFalse)
3079 virtual_nexus=nexus_info->virtual_nexus;
3081 indexes=nexus_info->indexes;
3082 switch (virtual_pixel_method)
3084 case BlackVirtualPixelMethod:
3086 SetPixelRed(&virtual_pixel,0);
3087 SetPixelGreen(&virtual_pixel,0);
3088 SetPixelBlue(&virtual_pixel,0);
3089 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3092 case GrayVirtualPixelMethod:
3094 SetPixelRed(&virtual_pixel,QuantumRange/2);
3095 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3096 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3097 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3100 case TransparentVirtualPixelMethod:
3102 SetPixelRed(&virtual_pixel,0);
3103 SetPixelGreen(&virtual_pixel,0);
3104 SetPixelBlue(&virtual_pixel,0);
3105 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3108 case MaskVirtualPixelMethod:
3109 case WhiteVirtualPixelMethod:
3111 SetPixelRed(&virtual_pixel,QuantumRange);
3112 SetPixelGreen(&virtual_pixel,QuantumRange);
3113 SetPixelBlue(&virtual_pixel,QuantumRange);
3114 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3119 virtual_pixel=image->background_color;
3123 virtual_index=(IndexPacket) 0;
3124 for (v=0; v < (ssize_t) rows; v++)
3130 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3131 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3132 y_offset=EdgeY(y_offset,cache_info->rows);
3133 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3139 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3140 (ssize_t) columns-u);
3141 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3142 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3152 length=(MagickSizeType) 1;
3153 switch (virtual_pixel_method)
3155 case BackgroundVirtualPixelMethod:
3156 case ConstantVirtualPixelMethod:
3157 case BlackVirtualPixelMethod:
3158 case GrayVirtualPixelMethod:
3159 case TransparentVirtualPixelMethod:
3160 case MaskVirtualPixelMethod:
3161 case WhiteVirtualPixelMethod:
3164 virtual_indexes=(&virtual_index);
3167 case EdgeVirtualPixelMethod:
3170 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3171 EdgeX(x_offset,cache_info->columns),
3172 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3174 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3178 case RandomVirtualPixelMethod:
3180 if (cache_info->random_info == (
RandomInfo *) NULL)
3181 cache_info->random_info=AcquireRandomInfo();
3182 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3183 RandomX(cache_info->random_info,cache_info->columns),
3184 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3185 virtual_nexus,exception);
3186 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3190 case DitherVirtualPixelMethod:
3192 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3193 DitherX(x_offset,cache_info->columns),
3194 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3196 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3200 case TileVirtualPixelMethod:
3202 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3203 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3204 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3205 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3207 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3211 case MirrorVirtualPixelMethod:
3213 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3214 if ((x_modulo.quotient & 0x01) == 1L)
3215 x_modulo.remainder=(ssize_t) cache_info->columns-
3216 x_modulo.remainder-1L;
3217 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3218 if ((y_modulo.quotient & 0x01) == 1L)
3219 y_modulo.remainder=(ssize_t) cache_info->rows-
3220 y_modulo.remainder-1L;
3221 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3222 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3224 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3228 case CheckerTileVirtualPixelMethod:
3230 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3231 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3232 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3235 virtual_indexes=(&virtual_index);
3238 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3239 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3241 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3245 case HorizontalTileVirtualPixelMethod:
3247 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3250 virtual_indexes=(&virtual_index);
3253 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3254 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3255 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3256 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3258 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3262 case VerticalTileVirtualPixelMethod:
3264 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3267 virtual_indexes=(&virtual_index);
3270 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3271 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3272 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3273 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3275 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3279 case HorizontalTileEdgeVirtualPixelMethod:
3281 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3282 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3283 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3284 virtual_nexus,exception);
3285 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3289 case VerticalTileEdgeVirtualPixelMethod:
3291 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3292 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3293 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3294 virtual_nexus,exception);
3295 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3303 if ((indexes != (IndexPacket *) NULL) &&
3304 (virtual_indexes != (
const IndexPacket *) NULL))
3305 *indexes++=(*virtual_indexes);
3311 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3312 (
size_t) length,1UL,virtual_nexus,exception);
3315 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3316 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3317 q+=(ptrdiff_t) length;
3318 if ((indexes != (IndexPacket *) NULL) &&
3319 (virtual_indexes != (
const IndexPacket *) NULL))
3321 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3322 sizeof(*virtual_indexes));
3326 if (u < (ssize_t) columns)
3332 if (v < (ssize_t) rows)
3372 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3373 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3376 *magick_restrict cache_info;
3379 id = GetOpenMPThreadId();
3381 assert(image != (
const Image *) NULL);
3382 assert(image->signature == MagickCoreSignature);
3383 assert(image->cache != (Cache) NULL);
3385 assert(cache_info->signature == MagickCoreSignature);
3386 assert(
id < (
int) cache_info->number_threads);
3387 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3388 cache_info->nexus_info[
id],exception));
3417 *magick_restrict cache_info;
3420 id = GetOpenMPThreadId();
3422 assert(image != (
const Image *) NULL);
3423 assert(image->signature == MagickCoreSignature);
3424 assert(image->cache != (Cache) NULL);
3426 assert(cache_info->signature == MagickCoreSignature);
3427 if (cache_info->methods.get_virtual_pixels_handler !=
3428 (GetVirtualPixelsHandler) NULL)
3429 return(cache_info->methods.get_virtual_pixels_handler(image));
3430 assert(
id < (
int) cache_info->number_threads);
3431 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3483 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3487 *magick_restrict cache_info;
3490 id = GetOpenMPThreadId();
3492 assert(image != (
const Image *) NULL);
3493 assert(image->signature == MagickCoreSignature);
3494 assert(image->cache != (Cache) NULL);
3496 assert(cache_info->signature == MagickCoreSignature);
3497 if (cache_info->methods.get_virtual_pixel_handler !=
3498 (GetVirtualPixelHandler) NULL)
3499 return(cache_info->methods.get_virtual_pixel_handler(image,
3500 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3501 assert(
id < (
int) cache_info->number_threads);
3502 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3503 columns,rows,cache_info->nexus_info[
id],exception));
3532 *magick_restrict cache_info;
3535 id = GetOpenMPThreadId();
3537 assert(image != (
const Image *) NULL);
3538 assert(image->signature == MagickCoreSignature);
3539 assert(image->cache != (Cache) NULL);
3541 assert(cache_info->signature == MagickCoreSignature);
3542 assert(
id < (
int) cache_info->number_threads);
3543 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3572 MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3576 *magick_restrict cache_info;
3578 assert(cache != (Cache) NULL);
3580 assert(cache_info->signature == MagickCoreSignature);
3581 if (cache_info->storage_class == UndefinedClass)
3623 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3628 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3629 gamma=MagickSafeReciprocal(gamma);
3630 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3631 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3632 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3633 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3634 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3637 static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3641 *magick_restrict cache_info;
3647 *magick_restrict nexus_indexes,
3648 *magick_restrict indexes;
3658 **magick_restrict mask_nexus;
3670 if (IsEventLogging() != MagickFalse)
3671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3672 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3674 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3677 if (cache_info == (Cache) NULL)
3678 return(MagickFalse);
3679 mask_nexus=AcquirePixelCacheNexus(1);
3680 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3681 nexus_info->virtual_nexus,exception);
3682 indexes=nexus_info->virtual_nexus->indexes;
3683 q=nexus_info->pixels;
3684 nexus_indexes=nexus_info->indexes;
3685 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3686 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3687 nexus_info->region.height,mask_nexus[0],&image->exception);
3690 return(MagickFalse);
3692 GetMagickPixelPacket(image,&alpha);
3693 GetMagickPixelPacket(image,&beta);
3694 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3699 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3701 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3702 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3703 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3704 alpha.opacity,&beta);
3705 SetPixelRed(q,ClampToQuantum(beta.red));
3706 SetPixelGreen(q,ClampToQuantum(beta.green));
3707 SetPixelBlue(q,ClampToQuantum(beta.blue));
3708 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3709 if (cache_info->active_index_channel != MagickFalse)
3710 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3717 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3752 static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3753 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3758 if ((count == 0) || (quantum == 0))
3760 length=count*quantum;
3761 if (quantum != (length/count))
3768 return(MagickFalse);
3771 static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3780 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3782 if (*cache_info->cache_filename ==
'\0')
3783 file=AcquireUniqueFileResource(cache_info->cache_filename);
3789 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3794 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3795 O_BINARY | O_EXCL,S_MODE);
3797 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3803 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3806 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3811 return(MagickFalse);
3812 (void) AcquireMagickResource(FileResource,1);
3813 if (cache_info->file != -1)
3814 (void) ClosePixelCacheOnDisk(cache_info);
3815 cache_info->file=file;
3816 cache_info->disk_mode=mode;
3820 static inline MagickOffsetType WritePixelCacheRegion(
3821 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3822 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3830 #if !defined(MAGICKCORE_HAVE_PWRITE) 3831 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3832 return((MagickOffsetType) -1);
3834 for (i=0; i < (MagickOffsetType) length; i+=count)
3836 #if !defined(MAGICKCORE_HAVE_PWRITE) 3837 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3838 (MagickSizeType) i,MagickMaxBufferExtent));
3840 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3841 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3853 static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3856 *magick_restrict cache_info;
3862 if (cache_info->debug != MagickFalse)
3865 format[MaxTextExtent],
3866 message[MaxTextExtent];
3868 (void) FormatMagickSize(length,MagickFalse,format);
3869 (void) FormatLocaleString(message,MaxTextExtent,
3870 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3871 cache_info->cache_filename,cache_info->file,format);
3872 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3874 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3876 return(MagickFalse);
3877 if ((MagickSizeType) offset < length)
3883 extent=(MagickOffsetType) length-1;
3884 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3887 return(MagickFalse);
3888 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE) 3889 if (cache_info->synchronize != MagickFalse)
3890 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3891 return(MagickFalse);
3894 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3896 return(MagickFalse);
3900 static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3904 *magick_restrict cache_info,
3908 format[MaxTextExtent],
3909 message[MaxTextExtent];
3926 assert(image != (
const Image *) NULL);
3927 assert(image->signature == MagickCoreSignature);
3928 assert(image->cache != (Cache) NULL);
3929 if (IsEventLogging() != MagickFalse)
3930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3931 if (cache_anonymous_memory < 0)
3939 cache_anonymous_memory=0;
3940 value=GetPolicyValue(
"pixel-cache-memory");
3941 if (value == (
char *) NULL)
3942 value=GetPolicyValue(
"cache:memory-map");
3943 if (LocaleCompare(value,
"anonymous") == 0)
3945 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS) 3946 cache_anonymous_memory=1;
3948 (void) ThrowMagickException(exception,GetMagickModule(),
3949 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3950 "'%s' (policy requires anonymous memory mapping)",image->filename);
3953 value=DestroyString(value);
3955 if ((image->columns == 0) || (image->rows == 0))
3956 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3958 assert(cache_info->signature == MagickCoreSignature);
3959 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3960 ((MagickSizeType) image->rows > cache_info->height_limit))
3961 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3963 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3965 length=GetImageListLength(image);
3966 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3967 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3970 source_info=(*cache_info);
3971 source_info.file=(-1);
3972 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3973 image->filename,(
double) image->scene);
3974 cache_info->storage_class=image->storage_class;
3975 cache_info->colorspace=image->colorspace;
3976 cache_info->rows=image->rows;
3977 cache_info->columns=image->columns;
3978 cache_info->channels=image->channels;
3979 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3980 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3981 cache_info->mode=mode;
3982 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3984 if (cache_info->active_index_channel != MagickFalse)
3985 packet_size+=
sizeof(IndexPacket);
3986 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3988 cache_info->storage_class=UndefinedClass;
3989 cache_info->length=0;
3990 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3993 columns=(size_t) (length/cache_info->rows/packet_size);
3994 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3995 ((ssize_t) cache_info->rows < 0))
3997 cache_info->storage_class=UndefinedClass;
3998 cache_info->length=0;
3999 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
4002 cache_info->length=length;
4003 if (image->ping != MagickFalse)
4005 cache_info->type=PingCache;
4008 status=AcquireMagickResource(AreaResource,(MagickSizeType)
4009 cache_info->columns*cache_info->rows);
4010 if (cache_info->mode == PersistMode)
4012 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4013 if ((status != MagickFalse) &&
4014 (length == (MagickSizeType) ((
size_t) length)) &&
4015 ((cache_info->type == UndefinedCache) ||
4016 (cache_info->type == MemoryCache)))
4018 status=AcquireMagickResource(MemoryResource,cache_info->length);
4019 if (status != MagickFalse)
4022 if (cache_anonymous_memory <= 0)
4024 cache_info->mapped=MagickFalse;
4025 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
4026 AcquireAlignedMemory(1,(
size_t) cache_info->length));
4030 cache_info->mapped=MagickTrue;
4031 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
4032 cache_info->length);
4036 cache_info->mapped=source_info.mapped;
4037 cache_info->pixels=source_info.pixels;
4044 cache_info->colorspace=image->colorspace;
4045 cache_info->type=MemoryCache;
4046 cache_info->indexes=(IndexPacket *) NULL;
4047 if (cache_info->active_index_channel != MagickFalse)
4048 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4050 if ((source_info.storage_class != UndefinedClass) &&
4053 status&=ClonePixelCacheRepository(cache_info,&source_info,
4055 RelinquishPixelCachePixels(&source_info);
4057 if (cache_info->debug != MagickFalse)
4059 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4060 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4062 (void) FormatLocaleString(message,MaxTextExtent,
4063 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4064 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4065 type,(
double) cache_info->columns,(double) cache_info->rows,
4067 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4070 cache_info->storage_class=image->storage_class;
4073 if ((source_info.storage_class != UndefinedClass) &&
4075 RelinquishPixelCachePixels(&source_info);
4076 cache_info->type=UndefinedCache;
4077 return(MagickFalse);
4083 status=AcquireMagickResource(DiskResource,cache_info->length);
4084 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4086 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4094 server_info=AcquireDistributeCacheInfo(exception);
4097 status=OpenDistributePixelCache(server_info,image);
4098 if (status == MagickFalse)
4100 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4101 GetDistributeCacheHostname(server_info));
4102 server_info=DestroyDistributeCacheInfo(server_info);
4110 cache_info->type=DistributedCache;
4111 cache_info->storage_class=image->storage_class;
4112 cache_info->colorspace=image->colorspace;
4113 cache_info->server_info=server_info;
4114 (void) FormatLocaleString(cache_info->cache_filename,
4115 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4118 cache_info->server_info));
4119 if ((source_info.storage_class != UndefinedClass) &&
4122 status=ClonePixelCacheRepository(cache_info,&source_info,
4124 RelinquishPixelCachePixels(&source_info);
4126 if (cache_info->debug != MagickFalse)
4128 (void) FormatMagickSize(cache_info->length,MagickFalse,
4130 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4132 (void) FormatLocaleString(message,MaxTextExtent,
4133 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4134 cache_info->cache_filename,GetDistributeCacheFile(
4136 (double) cache_info->columns,(
double) cache_info->rows,
4138 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4143 if ((source_info.storage_class != UndefinedClass) &&
4145 RelinquishPixelCachePixels(&source_info);
4146 cache_info->type=UndefinedCache;
4147 return(MagickFalse);
4152 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4153 RelinquishPixelCachePixels(&source_info);
4154 cache_info->type=UndefinedCache;
4155 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4156 "CacheResourcesExhausted",
"`%s'",image->filename);
4157 return(MagickFalse);
4162 if (status == MagickFalse)
4164 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4165 RelinquishPixelCachePixels(&source_info);
4166 cache_info->type=UndefinedCache;
4167 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4168 "CacheResourcesExhausted",
"`%s'",image->filename);
4169 return(MagickFalse);
4171 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4172 (cache_info->mode != PersistMode))
4174 (void) ClosePixelCacheOnDisk(cache_info);
4175 *cache_info->cache_filename=
'\0';
4177 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4179 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4180 RelinquishPixelCachePixels(&source_info);
4181 cache_info->type=UndefinedCache;
4182 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4184 return(MagickFalse);
4186 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4187 cache_info->length);
4188 if (status == MagickFalse)
4190 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4191 RelinquishPixelCachePixels(&source_info);
4192 cache_info->type=UndefinedCache;
4193 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4195 return(MagickFalse);
4197 cache_info->storage_class=image->storage_class;
4198 cache_info->colorspace=image->colorspace;
4199 cache_info->type=DiskCache;
4200 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4201 if (length == (MagickSizeType) ((size_t) length))
4203 status=AcquireMagickResource(MapResource,cache_info->length);
4204 if (status != MagickFalse)
4206 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4207 cache_info->offset,(
size_t) cache_info->length);
4210 cache_info->mapped=source_info.mapped;
4211 cache_info->pixels=source_info.pixels;
4212 RelinquishMagickResource(MapResource,cache_info->length);
4219 (void) ClosePixelCacheOnDisk(cache_info);
4220 cache_info->type=MapCache;
4221 cache_info->mapped=MagickTrue;
4222 cache_info->indexes=(IndexPacket *) NULL;
4223 if (cache_info->active_index_channel != MagickFalse)
4224 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4226 if ((source_info.storage_class != UndefinedClass) &&
4229 status=ClonePixelCacheRepository(cache_info,&source_info,
4231 RelinquishPixelCachePixels(&source_info);
4233 if (cache_info->debug != MagickFalse)
4235 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4236 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4238 (void) FormatLocaleString(message,MaxTextExtent,
4239 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4240 cache_info->filename,cache_info->cache_filename,
4241 cache_info->file,type,(
double) cache_info->columns,
4242 (double) cache_info->rows,format);
4243 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4248 if ((source_info.storage_class != UndefinedClass) &&
4250 RelinquishPixelCachePixels(&source_info);
4251 cache_info->type=UndefinedCache;
4252 return(MagickFalse);
4259 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4261 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4262 RelinquishPixelCachePixels(&source_info);
4264 if (cache_info->debug != MagickFalse)
4266 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4267 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4269 (void) FormatLocaleString(message,MaxTextExtent,
4270 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4271 cache_info->cache_filename,cache_info->file,type,(
double)
4272 cache_info->columns,(double) cache_info->rows,format);
4273 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4277 cache_info->type=UndefinedCache;
4278 return(MagickFalse);
4320 MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4321 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4325 *magick_restrict cache_info,
4326 *magick_restrict clone_info;
4334 assert(image != (
Image *) NULL);
4335 assert(image->signature == MagickCoreSignature);
4336 if (IsEventLogging() != MagickFalse)
4337 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4338 assert(image->cache != (
void *) NULL);
4339 assert(filename != (
const char *) NULL);
4340 assert(offset != (MagickOffsetType *) NULL);
4341 page_size=GetMagickPageSize();
4343 assert(cache_info->signature == MagickCoreSignature);
4344 #if defined(MAGICKCORE_OPENCL_SUPPORT) 4345 CopyOpenCLBuffer(cache_info);
4347 if (attach != MagickFalse)
4352 if (cache_info->debug != MagickFalse)
4353 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4354 "attach persistent cache");
4355 (void) CopyMagickString(cache_info->cache_filename,filename,
4357 cache_info->type=MapCache;
4358 cache_info->offset=(*offset);
4359 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4360 return(MagickFalse);
4361 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4362 ((MagickOffsetType) cache_info->length % page_size));
4368 status=AcquireMagickResource(DiskResource,cache_info->length);
4369 if (status == MagickFalse)
4371 cache_info->type=UndefinedCache;
4372 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4373 "CacheResourcesExhausted",
"`%s'",image->filename);
4374 return(MagickFalse);
4376 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4377 clone_info->type=DiskCache;
4378 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4379 clone_info->file=(-1);
4380 clone_info->storage_class=cache_info->storage_class;
4381 clone_info->colorspace=cache_info->colorspace;
4382 clone_info->columns=cache_info->columns;
4383 clone_info->rows=cache_info->rows;
4384 clone_info->active_index_channel=cache_info->active_index_channel;
4385 clone_info->mode=PersistMode;
4386 clone_info->length=cache_info->length;
4387 clone_info->channels=cache_info->channels;
4388 clone_info->offset=(*offset);
4389 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4390 if (status != MagickFalse)
4391 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4392 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4393 ((MagickOffsetType) cache_info->length % page_size));
4394 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4436 MagickExport
PixelPacket *QueueAuthenticPixel(
Image *image,
const ssize_t x,
4437 const ssize_t y,
const size_t columns,
const size_t rows,
4438 const MagickBooleanType clone,
NexusInfo *nexus_info,
4441 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4446 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4450 *magick_restrict cache_info;
4459 *magick_restrict pixels;
4464 assert(image != (
const Image *) NULL);
4465 assert(image->signature == MagickCoreSignature);
4466 assert(image->cache != (Cache) NULL);
4467 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4468 if (cache_info == (Cache) NULL)
4470 assert(cache_info->signature == MagickCoreSignature);
4471 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4472 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4473 (y >= (ssize_t) cache_info->rows))
4475 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4476 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4479 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4481 offset=y*(MagickOffsetType) cache_info->columns+x;
4484 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4485 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4486 (MagickOffsetType) columns-1;
4487 if ((MagickSizeType) offset >= number_pixels)
4492 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4493 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4494 MagickTrue : MagickFalse,nexus_info,exception);
4531 static PixelPacket *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4532 const ssize_t y,
const size_t columns,
const size_t rows,
4536 *magick_restrict cache_info;
4539 id = GetOpenMPThreadId();
4541 assert(image != (
const Image *) NULL);
4542 assert(image->signature == MagickCoreSignature);
4543 assert(image->cache != (Cache) NULL);
4545 assert(cache_info->signature == MagickCoreSignature);
4546 assert(
id < (
int) cache_info->number_threads);
4547 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4548 cache_info->nexus_info[
id],exception));
4607 MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4608 const ssize_t y,
const size_t columns,
const size_t rows,
4612 *magick_restrict cache_info;
4615 id = GetOpenMPThreadId();
4617 assert(image != (
Image *) NULL);
4618 assert(image->signature == MagickCoreSignature);
4619 assert(image->cache != (Cache) NULL);
4621 assert(cache_info->signature == MagickCoreSignature);
4622 if (cache_info->methods.queue_authentic_pixels_handler !=
4623 (QueueAuthenticPixelsHandler) NULL)
4624 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4626 assert(
id < (
int) cache_info->number_threads);
4627 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4628 cache_info->nexus_info[
id],exception));
4660 static inline MagickOffsetType ReadPixelCacheRegion(
4661 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4662 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4670 #if !defined(MAGICKCORE_HAVE_PREAD) 4671 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4672 return((MagickOffsetType) -1);
4674 for (i=0; i < (MagickOffsetType) length; i+=count)
4676 #if !defined(MAGICKCORE_HAVE_PREAD) 4677 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4678 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4680 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4681 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4693 static MagickBooleanType ReadPixelCacheIndexes(
4714 if (cache_info->active_index_channel == MagickFalse)
4715 return(MagickFalse);
4716 if (nexus_info->authentic_pixel_cache != MagickFalse)
4718 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4719 return(MagickFalse);
4720 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4721 nexus_info->region.x;
4722 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4723 rows=nexus_info->region.height;
4725 q=nexus_info->indexes;
4727 switch (cache_info->type)
4738 if ((cache_info->columns == nexus_info->region.width) &&
4739 (extent == (MagickSizeType) ((
size_t) extent)))
4744 p=cache_info->indexes+offset;
4745 for (y=0; y < (ssize_t) rows; y++)
4747 (void) memcpy(q,p,(
size_t) length);
4748 p+=(ptrdiff_t) cache_info->columns;
4749 q+=(ptrdiff_t) nexus_info->region.width;
4758 LockSemaphoreInfo(cache_info->file_semaphore);
4759 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4761 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4762 cache_info->cache_filename);
4763 UnlockSemaphoreInfo(cache_info->file_semaphore);
4764 return(MagickFalse);
4766 if ((cache_info->columns == nexus_info->region.width) &&
4767 (extent <= MagickMaxBufferExtent))
4772 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4773 for (y=0; y < (ssize_t) rows; y++)
4775 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4776 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4777 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4778 if (count < (MagickOffsetType) length)
4780 offset+=(MagickOffsetType) cache_info->columns;
4781 q+=(ptrdiff_t) nexus_info->region.width;
4783 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4784 (
void) ClosePixelCacheOnDisk(cache_info);
4785 UnlockSemaphoreInfo(cache_info->file_semaphore);
4788 case DistributedCache:
4796 LockSemaphoreInfo(cache_info->file_semaphore);
4797 region=nexus_info->region;
4798 if ((cache_info->columns != nexus_info->region.width) ||
4799 (extent > MagickMaxBufferExtent))
4806 for (y=0; y < (ssize_t) rows; y++)
4809 cache_info->server_info,®ion,length,(
unsigned char *) q);
4810 if (count != (MagickOffsetType) length)
4812 q+=(ptrdiff_t) nexus_info->region.width;
4815 UnlockSemaphoreInfo(cache_info->file_semaphore);
4821 if (y < (ssize_t) rows)
4823 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4824 cache_info->cache_filename);
4825 return(MagickFalse);
4827 if ((cache_info->debug != MagickFalse) &&
4828 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4829 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4830 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4831 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4832 nexus_info->region.x,(
double) nexus_info->region.y);
4864 static MagickBooleanType ReadPixelCachePixels(
4885 if (nexus_info->authentic_pixel_cache != MagickFalse)
4887 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4888 return(MagickFalse);
4889 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4890 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4891 return(MagickFalse);
4892 offset+=nexus_info->region.x;
4893 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4894 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4895 return(MagickFalse);
4896 rows=nexus_info->region.height;
4898 if ((extent == 0) || ((extent/length) != rows))
4899 return(MagickFalse);
4900 q=nexus_info->pixels;
4902 switch (cache_info->type)
4913 if ((cache_info->columns == nexus_info->region.width) &&
4914 (extent == (MagickSizeType) ((
size_t) extent)))
4919 p=cache_info->pixels+offset;
4920 for (y=0; y < (ssize_t) rows; y++)
4922 (void) memcpy(q,p,(
size_t) length);
4923 p+=(ptrdiff_t) cache_info->columns;
4924 q+=(ptrdiff_t) nexus_info->region.width;
4933 LockSemaphoreInfo(cache_info->file_semaphore);
4934 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4936 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4937 cache_info->cache_filename);
4938 UnlockSemaphoreInfo(cache_info->file_semaphore);
4939 return(MagickFalse);
4941 if ((cache_info->columns == nexus_info->region.width) &&
4942 (extent <= MagickMaxBufferExtent))
4947 for (y=0; y < (ssize_t) rows; y++)
4949 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4950 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4951 if (count < (MagickOffsetType) length)
4953 offset+=(MagickOffsetType) cache_info->columns;
4954 q+=(ptrdiff_t) nexus_info->region.width;
4956 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4957 (
void) ClosePixelCacheOnDisk(cache_info);
4958 UnlockSemaphoreInfo(cache_info->file_semaphore);
4961 case DistributedCache:
4969 LockSemaphoreInfo(cache_info->file_semaphore);
4970 region=nexus_info->region;
4971 if ((cache_info->columns != nexus_info->region.width) ||
4972 (extent > MagickMaxBufferExtent))
4979 for (y=0; y < (ssize_t) rows; y++)
4982 cache_info->server_info,®ion,length,(
unsigned char *) q);
4983 if (count != (MagickOffsetType) length)
4985 q+=(ptrdiff_t) nexus_info->region.width;
4988 UnlockSemaphoreInfo(cache_info->file_semaphore);
4994 if (y < (ssize_t) rows)
4996 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4997 cache_info->cache_filename);
4998 return(MagickFalse);
5000 if ((cache_info->debug != MagickFalse) &&
5001 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5002 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5003 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5004 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5005 nexus_info->region.x,(
double) nexus_info->region.y);
5032 MagickExport Cache ReferencePixelCache(Cache cache)
5035 *magick_restrict cache_info;
5037 assert(cache != (Cache *) NULL);
5039 assert(cache_info->signature == MagickCoreSignature);
5040 LockSemaphoreInfo(cache_info->semaphore);
5041 cache_info->reference_count++;
5042 UnlockSemaphoreInfo(cache_info->semaphore);
5064 MagickPrivate
void ResetCacheAnonymousMemory(
void)
5066 cache_anonymous_memory=0;
5093 MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5096 *magick_restrict cache_info;
5098 GetOneAuthenticPixelFromHandler
5099 get_one_authentic_pixel_from_handler;
5101 GetOneVirtualPixelFromHandler
5102 get_one_virtual_pixel_from_handler;
5107 assert(cache != (Cache) NULL);
5110 assert(cache_info->signature == MagickCoreSignature);
5111 if (IsEventLogging() != MagickFalse)
5112 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5113 cache_info->filename);
5114 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5115 cache_info->methods.get_virtual_pixel_handler=
5116 cache_methods->get_virtual_pixel_handler;
5117 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5118 cache_info->methods.destroy_pixel_handler=
5119 cache_methods->destroy_pixel_handler;
5120 if (cache_methods->get_virtual_indexes_from_handler !=
5121 (GetVirtualIndexesFromHandler) NULL)
5122 cache_info->methods.get_virtual_indexes_from_handler=
5123 cache_methods->get_virtual_indexes_from_handler;
5124 if (cache_methods->get_authentic_pixels_handler !=
5125 (GetAuthenticPixelsHandler) NULL)
5126 cache_info->methods.get_authentic_pixels_handler=
5127 cache_methods->get_authentic_pixels_handler;
5128 if (cache_methods->queue_authentic_pixels_handler !=
5129 (QueueAuthenticPixelsHandler) NULL)
5130 cache_info->methods.queue_authentic_pixels_handler=
5131 cache_methods->queue_authentic_pixels_handler;
5132 if (cache_methods->sync_authentic_pixels_handler !=
5133 (SyncAuthenticPixelsHandler) NULL)
5134 cache_info->methods.sync_authentic_pixels_handler=
5135 cache_methods->sync_authentic_pixels_handler;
5136 if (cache_methods->get_authentic_pixels_from_handler !=
5137 (GetAuthenticPixelsFromHandler) NULL)
5138 cache_info->methods.get_authentic_pixels_from_handler=
5139 cache_methods->get_authentic_pixels_from_handler;
5140 if (cache_methods->get_authentic_indexes_from_handler !=
5141 (GetAuthenticIndexesFromHandler) NULL)
5142 cache_info->methods.get_authentic_indexes_from_handler=
5143 cache_methods->get_authentic_indexes_from_handler;
5144 get_one_virtual_pixel_from_handler=
5145 cache_info->methods.get_one_virtual_pixel_from_handler;
5146 if (get_one_virtual_pixel_from_handler !=
5147 (GetOneVirtualPixelFromHandler) NULL)
5148 cache_info->methods.get_one_virtual_pixel_from_handler=
5149 cache_methods->get_one_virtual_pixel_from_handler;
5150 get_one_authentic_pixel_from_handler=
5151 cache_methods->get_one_authentic_pixel_from_handler;
5152 if (get_one_authentic_pixel_from_handler !=
5153 (GetOneAuthenticPixelFromHandler) NULL)
5154 cache_info->methods.get_one_authentic_pixel_from_handler=
5155 cache_methods->get_one_authentic_pixel_from_handler;
5196 static inline MagickBooleanType AcquireCacheNexusPixels(
5197 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5200 if (length != (MagickSizeType) ((
size_t) length))
5202 (void) ThrowMagickException(exception,GetMagickModule(),
5203 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5204 cache_info->filename);
5205 return(MagickFalse);
5207 nexus_info->length=0;
5208 nexus_info->mapped=MagickFalse;
5209 if (cache_anonymous_memory <= 0)
5211 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5212 AcquireAlignedMemory(1,(
size_t) length));
5214 (
void) memset(nexus_info->cache,0,(
size_t) length);
5218 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5220 nexus_info->mapped=MagickTrue;
5224 (void) ThrowMagickException(exception,GetMagickModule(),
5225 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5226 cache_info->filename);
5227 return(MagickFalse);
5229 nexus_info->length=length;
5233 static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5236 if (nexus_info->length < CACHE_LINE_SIZE)
5238 if (mode == ReadMode)
5240 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5244 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5247 static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5250 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5251 return(MagickFalse);
5252 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5253 return(MagickFalse);
5258 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5259 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5260 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5270 assert(cache_info != (
const CacheInfo *) NULL);
5271 assert(cache_info->signature == MagickCoreSignature);
5272 if (cache_info->type == UndefinedCache)
5274 assert(nexus_info->signature == MagickCoreSignature);
5275 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5276 if ((width == 0) || (height == 0))
5278 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5279 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5282 if (((MagickSizeType) width > cache_info->width_limit) ||
5283 ((MagickSizeType) height > cache_info->height_limit))
5285 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5286 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5289 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5290 (ValidatePixelOffset(y,height) == MagickFalse))
5292 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5293 "InvalidPixel",
"`%s'",cache_info->filename);
5296 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5297 (buffered == MagickFalse))
5299 if (((x >= 0) && (y >= 0) &&
5300 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5301 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5302 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5310 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5312 offset=y*(MagickOffsetType) cache_info->columns+x;
5313 nexus_info->pixels=cache_info->pixels+offset;
5314 nexus_info->indexes=(IndexPacket *) NULL;
5315 if (cache_info->active_index_channel != MagickFalse)
5316 nexus_info->indexes=cache_info->indexes+offset;
5317 nexus_info->region.width=width;
5318 nexus_info->region.height=height;
5319 nexus_info->region.x=x;
5320 nexus_info->region.y=y;
5321 nexus_info->authentic_pixel_cache=MagickTrue;
5322 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5323 return(nexus_info->pixels);
5329 number_pixels=(MagickSizeType) width*height;
5330 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5332 if (cache_info->active_index_channel != MagickFalse)
5333 length+=number_pixels*
sizeof(IndexPacket);
5336 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5338 if (nexus_info->length < length)
5340 RelinquishCacheNexusPixels(nexus_info);
5341 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5343 if (status == MagickFalse)
5345 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5348 nexus_info->pixels=nexus_info->cache;
5349 nexus_info->indexes=(IndexPacket *) NULL;
5350 if (cache_info->active_index_channel != MagickFalse)
5351 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5352 nexus_info->region.width=width;
5353 nexus_info->region.height=height;
5354 nexus_info->region.x=x;
5355 nexus_info->region.y=y;
5356 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5357 MagickTrue : MagickFalse;
5358 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5359 return(nexus_info->pixels);
5390 static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5391 const Quantum opacity)
5394 *magick_restrict image_view;
5402 assert(image != (
Image *) NULL);
5403 assert(image->signature == MagickCoreSignature);
5404 if (IsEventLogging() != MagickFalse)
5405 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5406 assert(image->cache != (Cache) NULL);
5407 image->matte=MagickTrue;
5409 image_view=AcquireVirtualCacheView(image,&image->exception);
5410 #if defined(MAGICKCORE_OPENMP_SUPPORT) 5411 #pragma omp parallel for schedule(static) shared(status) \ 5412 magick_number_threads(image,image,image->rows,2) 5414 for (y=0; y < (ssize_t) image->rows; y++)
5422 if (status == MagickFalse)
5424 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5431 for (x=0; x < (ssize_t) image->columns; x++)
5436 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5438 image_view=DestroyCacheView(image_view);
5442 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5443 const VirtualPixelMethod virtual_pixel_method)
5446 *magick_restrict cache_info;
5451 assert(image != (
Image *) NULL);
5452 assert(image->signature == MagickCoreSignature);
5453 if (IsEventLogging() != MagickFalse)
5454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5455 assert(image->cache != (Cache) NULL);
5457 assert(cache_info->signature == MagickCoreSignature);
5458 method=cache_info->virtual_pixel_method;
5459 cache_info->virtual_pixel_method=virtual_pixel_method;
5460 if ((image->columns != 0) && (image->rows != 0))
5461 switch (virtual_pixel_method)
5463 case BackgroundVirtualPixelMethod:
5465 if ((image->background_color.opacity != OpaqueOpacity) &&
5466 (image->matte == MagickFalse))
5467 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5468 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5469 (IsGrayColorspace(image->colorspace) != MagickFalse))
5470 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5473 case TransparentVirtualPixelMethod:
5475 if (image->matte == MagickFalse)
5476 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5485 #if defined(MAGICKCORE_OPENCL_SUPPORT) 5509 static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5514 assert(cache_info != (
CacheInfo *)NULL);
5515 if ((cache_info->type != MemoryCache) ||
5521 LockSemaphoreInfo(cache_info->semaphore);
5530 clEnv=GetDefaultOpenCLEnv();
5531 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5532 if (events != (cl_event *) NULL)
5546 context=GetOpenCLContext(clEnv);
5547 queue=AcquireOpenCLCommandQueue(clEnv);
5548 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5549 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5550 cache_info->length,event_count,events,NULL,&status);
5551 assert(pixels == cache_info->pixels);
5552 events=(cl_event *) RelinquishMagickMemory(events);
5553 RelinquishOpenCLCommandQueue(clEnv,queue);
5555 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5557 UnlockSemaphoreInfo(cache_info->semaphore);
5560 MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5563 *magick_restrict cache_info;
5565 assert(image != (
Image *)NULL);
5567 CopyOpenCLBuffer(cache_info);
5600 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5604 *magick_restrict cache_info;
5612 assert(image != (
Image *) NULL);
5613 assert(image->signature == MagickCoreSignature);
5614 if (image->cache == (Cache) NULL)
5615 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5617 assert(cache_info->signature == MagickCoreSignature);
5618 if (cache_info->type == UndefinedCache)
5619 return(MagickFalse);
5620 if ((image->storage_class == DirectClass) &&
5621 (image->clip_mask != (
Image *) NULL) &&
5622 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5623 return(MagickFalse);
5624 if ((image->storage_class == DirectClass) &&
5625 (image->mask != (
Image *) NULL) &&
5626 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5627 return(MagickFalse);
5628 if (nexus_info->authentic_pixel_cache != MagickFalse)
5630 if (image->taint == MagickFalse)
5631 image->taint=MagickTrue;
5634 assert(cache_info->signature == MagickCoreSignature);
5635 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5636 if ((cache_info->active_index_channel != MagickFalse) &&
5637 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5638 return(MagickFalse);
5639 if ((status != MagickFalse) && (image->taint == MagickFalse))
5640 image->taint=MagickTrue;
5671 static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5675 *magick_restrict cache_info;
5678 id = GetOpenMPThreadId();
5683 assert(image != (
Image *) NULL);
5684 assert(image->signature == MagickCoreSignature);
5685 assert(image->cache != (Cache) NULL);
5687 assert(cache_info->signature == MagickCoreSignature);
5688 assert(
id < (
int) cache_info->number_threads);
5689 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5721 MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5725 *magick_restrict cache_info;
5728 id = GetOpenMPThreadId();
5733 assert(image != (
Image *) NULL);
5734 assert(image->signature == MagickCoreSignature);
5735 assert(image->cache != (Cache) NULL);
5737 assert(cache_info->signature == MagickCoreSignature);
5738 if (cache_info->methods.sync_authentic_pixels_handler !=
5739 (SyncAuthenticPixelsHandler) NULL)
5740 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5741 assert(
id < (
int) cache_info->number_threads);
5742 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5774 MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5778 *magick_restrict cache_info;
5780 assert(image != (
Image *) NULL);
5782 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5783 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5814 static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5834 if (cache_info->active_index_channel == MagickFalse)
5835 return(MagickFalse);
5836 if (nexus_info->authentic_pixel_cache != MagickFalse)
5838 if (nexus_info->indexes == (IndexPacket *) NULL)
5839 return(MagickFalse);
5840 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5841 return(MagickFalse);
5842 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5843 nexus_info->region.x;
5844 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5845 rows=nexus_info->region.height;
5846 extent=(MagickSizeType) length*rows;
5847 p=nexus_info->indexes;
5849 switch (cache_info->type)
5860 if ((cache_info->columns == nexus_info->region.width) &&
5861 (extent == (MagickSizeType) ((
size_t) extent)))
5866 q=cache_info->indexes+offset;
5867 for (y=0; y < (ssize_t) rows; y++)
5869 (void) memcpy(q,p,(
size_t) length);
5870 p+=(ptrdiff_t) nexus_info->region.width;
5871 q+=(ptrdiff_t) cache_info->columns;
5880 LockSemaphoreInfo(cache_info->file_semaphore);
5881 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5883 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5884 cache_info->cache_filename);
5885 UnlockSemaphoreInfo(cache_info->file_semaphore);
5886 return(MagickFalse);
5888 if ((cache_info->columns == nexus_info->region.width) &&
5889 (extent <= MagickMaxBufferExtent))
5894 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5895 for (y=0; y < (ssize_t) rows; y++)
5897 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5898 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5899 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5901 if (count < (MagickOffsetType) length)
5903 p+=(ptrdiff_t) nexus_info->region.width;
5904 offset+=(MagickOffsetType) cache_info->columns;
5906 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5907 (
void) ClosePixelCacheOnDisk(cache_info);
5908 UnlockSemaphoreInfo(cache_info->file_semaphore);
5911 case DistributedCache:
5919 LockSemaphoreInfo(cache_info->file_semaphore);
5920 region=nexus_info->region;
5921 if ((cache_info->columns != nexus_info->region.width) ||
5922 (extent > MagickMaxBufferExtent))
5929 for (y=0; y < (ssize_t) rows; y++)
5932 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5933 if (count != (MagickOffsetType) length)
5935 p+=(ptrdiff_t) nexus_info->region.width;
5938 UnlockSemaphoreInfo(cache_info->file_semaphore);
5944 if (y < (ssize_t) rows)
5946 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5947 cache_info->cache_filename);
5948 return(MagickFalse);
5950 if ((cache_info->debug != MagickFalse) &&
5951 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5952 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5953 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5954 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5955 nexus_info->region.x,(
double) nexus_info->region.y);
5987 static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
6007 if (nexus_info->authentic_pixel_cache != MagickFalse)
6009 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
6010 return(MagickFalse);
6011 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
6012 nexus_info->region.x;
6013 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
6014 rows=nexus_info->region.height;
6016 p=nexus_info->pixels;
6018 switch (cache_info->type)
6029 if ((cache_info->columns == nexus_info->region.width) &&
6030 (extent == (MagickSizeType) ((
size_t) extent)))
6035 q=cache_info->pixels+offset;
6036 for (y=0; y < (ssize_t) rows; y++)
6038 (void) memcpy(q,p,(
size_t) length);
6039 p+=(ptrdiff_t) nexus_info->region.width;
6040 q+=(ptrdiff_t) cache_info->columns;
6049 LockSemaphoreInfo(cache_info->file_semaphore);
6050 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6052 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6053 cache_info->cache_filename);
6054 UnlockSemaphoreInfo(cache_info->file_semaphore);
6055 return(MagickFalse);
6057 if ((cache_info->columns == nexus_info->region.width) &&
6058 (extent <= MagickMaxBufferExtent))
6063 for (y=0; y < (ssize_t) rows; y++)
6065 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6066 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6067 if (count < (MagickOffsetType) length)
6069 p+=(ptrdiff_t) nexus_info->region.width;
6070 offset+=(MagickOffsetType) cache_info->columns;
6072 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6073 (
void) ClosePixelCacheOnDisk(cache_info);
6074 UnlockSemaphoreInfo(cache_info->file_semaphore);
6077 case DistributedCache:
6085 LockSemaphoreInfo(cache_info->file_semaphore);
6086 region=nexus_info->region;
6087 if ((cache_info->columns != nexus_info->region.width) ||
6088 (extent > MagickMaxBufferExtent))
6095 for (y=0; y < (ssize_t) rows; y++)
6098 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6099 if (count != (MagickOffsetType) length)
6101 p+=(ptrdiff_t) nexus_info->region.width;
6104 UnlockSemaphoreInfo(cache_info->file_semaphore);
6110 if (y < (ssize_t) rows)
6112 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6113 cache_info->cache_filename);
6114 return(MagickFalse);
6116 if ((cache_info->debug != MagickFalse) &&
6117 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6118 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6119 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6120 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6121 nexus_info->region.x,(
double) nexus_info->region.y);