43#include "magick/studio.h"
44#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
47#include "magick/cache-private.h"
48#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/colorspace-private.h"
51#include "magick/composite-private.h"
52#include "magick/distribute-cache-private.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/geometry.h"
56#include "magick/list.h"
57#include "magick/log.h"
58#include "magick/magick.h"
59#include "magick/memory_.h"
60#include "magick/memory-private.h"
61#include "magick/nt-base-private.h"
62#include "magick/option.h"
63#include "magick/pixel.h"
64#include "magick/pixel-accessor.h"
65#include "magick/pixel-private.h"
66#include "magick/policy.h"
67#include "magick/quantum.h"
68#include "magick/random_.h"
69#include "magick/registry.h"
70#include "magick/resource_.h"
71#include "magick/semaphore.h"
72#include "magick/splay-tree.h"
73#include "magick/string_.h"
74#include "magick/string-private.h"
75#include "magick/thread-private.h"
76#include "magick/timer-private.h"
77#include "magick/utility.h"
78#include "magick/utility-private.h"
79#if defined(MAGICKCORE_ZLIB_DELEGATE)
86#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
87#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
88 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
103#if defined(__cplusplus) || defined(c_plusplus)
111static const IndexPacket
112 *GetVirtualIndexesFromCache(
const Image *);
115 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
117 *GetVirtualPixelsCache(
const Image *);
119static MagickBooleanType
120 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,
122 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
125 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
137 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
139 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
141 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
142 const ssize_t,
const ssize_t,
const size_t,
const size_t,
146#if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
151#if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
164#if defined(MAGICKCORE_OPENCL_SUPPORT)
171 for (i=0; i < (ssize_t) info->event_count; i++)
172 clEnv->library->clReleaseEvent(info->events[i]);
173 info->events=(cl_event *) RelinquishMagickMemory(info->events);
174 DestroySemaphoreInfo(&info->events_semaphore);
175 if (info->buffer != (cl_mem) NULL)
177 clEnv->library->clReleaseMemObject(info->buffer);
178 info->buffer=(cl_mem) NULL;
183static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
184 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
199 magick_unreferenced(event);
200 magick_unreferenced(event_command_exec_status);
202 clEnv=GetDefaultOpenCLEnv();
203 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
211 status=clEnv->library->clGetEventInfo(info->events[i],
212 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
213 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
215 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
216 &RelinquishPixelCachePixelsDelayed,info);
221 RelinquishMagickResource(MemoryResource,info->length);
222 (void) RelinquishOpenCLCacheInfo(clEnv,info);
223 (void) RelinquishAlignedMemory(pixels);
226static MagickBooleanType RelinquishOpenCLBuffer(
232 assert(cache_info != (
CacheInfo *) NULL);
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
240 cl_uint *event_count)
249 events=(cl_event *) NULL;
250 LockSemaphoreInfo(opencl_info->events_semaphore);
251 *event_count=opencl_info->event_count;
252 if (*event_count > 0)
254 events=(cl_event *) AcquireQuantumMemory(*event_count,
sizeof(*events));
255 if (events == (cl_event *) NULL)
259 for (i=0; i < opencl_info->event_count; i++)
260 events[i]=opencl_info->events[i];
263 UnlockSemaphoreInfo(opencl_info->events_semaphore);
268#if defined(MAGICKCORE_OPENCL_SUPPORT)
294extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
297 *magick_restrict cache_info;
302 assert(image != (
const Image *) NULL);
303 assert(event != (cl_event) NULL);
306 clEnv=GetDefaultOpenCLEnv();
307 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
309 clEnv->library->clWaitForEvents(1,&event);
312 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
313 if (cache_info->opencl->events == (cl_event *) NULL)
315 cache_info->opencl->events=(cl_event *) AcquireMagickMemory(
sizeof(
316 *cache_info->opencl->events));
317 cache_info->opencl->event_count=1;
320 cache_info->opencl->events=(cl_event *) ResizeQuantumMemory(
321 cache_info->opencl->events,++cache_info->opencl->event_count,
322 sizeof(*cache_info->opencl->events));
323 if (cache_info->opencl->events == (cl_event *) NULL)
324 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
325 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
326 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
352MagickExport Cache AcquirePixelCache(
const size_t number_threads)
355 *magick_restrict cache_info;
360 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
362 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
363 (void) memset(cache_info,0,
sizeof(*cache_info));
364 cache_info->type=UndefinedCache;
365 cache_info->mode=IOMode;
366 cache_info->disk_mode=IOMode;
367 cache_info->colorspace=sRGBColorspace;
368 cache_info->channels=4;
369 cache_info->file=(-1);
370 cache_info->id=GetMagickThreadId();
371 cache_info->number_threads=number_threads;
372 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
373 cache_info->number_threads=GetOpenMPMaximumThreads();
374 if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
375 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
376 if (cache_info->number_threads == 0)
377 cache_info->number_threads=1;
378 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
379 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
380 if (value != (
const char *) NULL)
382 cache_info->synchronize=IsStringTrue(value);
383 value=DestroyString(value);
385 value=GetPolicyValue(
"cache:synchronize");
386 if (value != (
const char *) NULL)
388 cache_info->synchronize=IsStringTrue(value);
389 value=DestroyString(value);
391 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
392 (MagickSizeType) MAGICK_SSIZE_MAX);
393 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
394 (MagickSizeType) MAGICK_SSIZE_MAX);
395 cache_info->semaphore=AllocateSemaphoreInfo();
396 cache_info->reference_count=1;
397 cache_info->file_semaphore=AllocateSemaphoreInfo();
398 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
399 cache_info->signature=MagickCoreSignature;
400 return((Cache ) cache_info);
425MagickExport
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
428 **magick_restrict nexus_info;
433 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
434 number_threads,
sizeof(*nexus_info)));
436 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
437 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
438 2*
sizeof(**nexus_info));
440 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
441 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
442 for (i=0; i < (ssize_t) (2*number_threads); i++)
444 nexus_info[i]=(*nexus_info+i);
445 if (i < (ssize_t) number_threads)
446 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
447 nexus_info[i]->signature=MagickCoreSignature;
480MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
484 *magick_restrict cache_info;
486 assert(image != (
const Image *) NULL);
487 assert(image->signature == MagickCoreSignature);
489 assert(exception->signature == MagickCoreSignature);
490 assert(image->cache != (Cache) NULL);
492 assert(cache_info->signature == MagickCoreSignature);
495 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
496 return((
const void *) NULL);
497 *length=cache_info->length;
498 return((
const void *) cache_info->pixels);
519MagickExport MagickBooleanType CacheComponentGenesis(
void)
522 cache_semaphore=AllocateSemaphoreInfo();
544MagickExport
void CacheComponentTerminus(
void)
547 ActivateSemaphoreInfo(&cache_semaphore);
549 DestroySemaphoreInfo(&cache_semaphore);
581static MagickBooleanType ClipPixelCacheNexus(
Image *image,
585 *magick_restrict cache_info;
591 *magick_restrict nexus_indexes,
592 *magick_restrict indexes;
598 **magick_restrict clip_nexus;
610 if (IsEventLogging() != MagickFalse)
611 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
612 if ((image->clip_mask == (
Image *) NULL) ||
613 (image->storage_class == PseudoClass))
615 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
618 if (cache_info == (Cache) NULL)
620 clip_nexus=AcquirePixelCacheNexus(1);
621 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
622 nexus_info->region.width,nexus_info->region.height,
623 nexus_info->virtual_nexus,exception);
624 indexes=nexus_info->virtual_nexus->indexes;
625 q=nexus_info->pixels;
626 nexus_indexes=nexus_info->indexes;
627 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
628 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
629 nexus_info->region.height,clip_nexus[0],exception);
634 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
639 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
644 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
645 if (fabs(mask_alpha) >= MagickEpsilon)
647 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
648 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
649 GetPixelOpacity(q)));
650 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
651 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
652 GetPixelOpacity(q)));
653 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
654 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
655 GetPixelOpacity(q)));
656 SetPixelOpacity(q,GetPixelOpacity(p));
657 if (cache_info->active_index_channel != MagickFalse)
658 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
666 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
692MagickExport Cache ClonePixelCache(
const Cache cache)
695 *magick_restrict clone_info;
698 *magick_restrict cache_info;
700 assert(cache != NULL);
702 assert(cache_info->signature == MagickCoreSignature);
703 if (IsEventLogging() != MagickFalse)
704 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
705 cache_info->filename);
706 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
707 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
708 return((Cache ) clone_info);
736MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
739 *magick_restrict cache_info,
740 *magick_restrict source_info;
742 assert(clone != (Cache) NULL);
744 assert(source_info->signature == MagickCoreSignature);
745 if (IsEventLogging() != MagickFalse)
746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
747 source_info->filename);
748 assert(cache != (Cache) NULL);
750 assert(cache_info->signature == MagickCoreSignature);
751 source_info->methods=cache_info->methods;
783static MagickBooleanType ClonePixelCacheOnDisk(
804 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
805 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
807 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
808 (lseek(clone_info->file,0,SEEK_SET) < 0))
810 quantum=(size_t) MagickMaxBufferExtent;
811 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
813#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
814 if (cache_info->length < 0x7ffff000)
816 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
817 (
size_t) cache_info->length);
818 if (count == (ssize_t) cache_info->length)
820 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
821 (lseek(clone_info->file,0,SEEK_SET) < 0))
825 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
827 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
828 if (buffer == (
unsigned char *) NULL)
829 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
831 while ((count=read(cache_info->file,buffer,quantum)) > 0)
836 number_bytes=write(clone_info->file,buffer,(
size_t) count);
837 if (number_bytes != count)
839 extent+=(size_t) number_bytes;
841 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
842 if (extent != cache_info->length)
847static MagickBooleanType ClonePixelCacheRepository(
851#define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
852#define cache_number_threads(source,destination,chunk,multithreaded) \
853 num_threads((multithreaded) == 0 ? 1 : \
854 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
855 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
856 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
857 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
863 **magick_restrict cache_nexus,
864 **magick_restrict clone_nexus;
872 assert(cache_info != (
CacheInfo *) NULL);
873 assert(clone_info != (
CacheInfo *) NULL);
875 if (cache_info->type == PingCache)
877 if ((cache_info->storage_class == clone_info->storage_class) &&
878 (cache_info->colorspace == clone_info->colorspace) &&
879 (cache_info->channels == clone_info->channels) &&
880 (cache_info->columns == clone_info->columns) &&
881 (cache_info->rows == clone_info->rows) &&
882 (cache_info->active_index_channel == clone_info->active_index_channel))
887 if (((cache_info->type == MemoryCache) ||
888 (cache_info->type == MapCache)) &&
889 ((clone_info->type == MemoryCache) ||
890 (clone_info->type == MapCache)))
892 (void) memcpy(clone_info->pixels,cache_info->pixels,
893 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
894 if ((cache_info->active_index_channel != MagickFalse) &&
895 (clone_info->active_index_channel != MagickFalse))
896 (void) memcpy(clone_info->indexes,cache_info->indexes,
897 cache_info->columns*cache_info->rows*
898 sizeof(*cache_info->indexes));
901 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
902 return(ClonePixelCacheOnDisk(cache_info,clone_info));
907 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
908 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
909 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
910 sizeof(*cache_info->pixels);
912#if defined(MAGICKCORE_OPENMP_SUPPORT)
913 #pragma omp parallel for schedule(static) shared(status) \
914 cache_number_threads(cache_info,clone_info,cache_info->rows,4)
916 for (y=0; y < (ssize_t) cache_info->rows; y++)
919 id = GetOpenMPThreadId();
924 if (status == MagickFalse)
926 if (y >= (ssize_t) clone_info->rows)
928 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
929 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
932 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
933 if (status == MagickFalse)
935 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
936 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
939 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
940 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
941 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
943 if ((cache_info->active_index_channel != MagickFalse) &&
944 (clone_info->active_index_channel != MagickFalse))
949 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
950 sizeof(*cache_info->indexes);
951#if defined(MAGICKCORE_OPENMP_SUPPORT)
952 #pragma omp parallel for schedule(static) shared(status) \
953 cache_number_threads(cache_info,clone_info,cache_info->rows,4)
955 for (y=0; y < (ssize_t) cache_info->rows; y++)
958 id = GetOpenMPThreadId();
963 if (status == MagickFalse)
965 if (y >= (ssize_t) clone_info->rows)
967 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
968 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
971 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
972 if (status == MagickFalse)
974 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
975 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
978 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
979 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
982 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
983 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
984 if (cache_info->debug != MagickFalse)
987 message[MaxTextExtent];
989 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
990 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
991 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
992 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1019static void DestroyImagePixelCache(
Image *image)
1021 assert(image != (
Image *) NULL);
1022 assert(image->signature == MagickCoreSignature);
1023 if (IsEventLogging() != MagickFalse)
1024 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1025 if (image->cache != (
void *) NULL)
1026 image->cache=DestroyPixelCache(image->cache);
1051MagickExport
void DestroyImagePixels(
Image *image)
1054 *magick_restrict cache_info;
1056 assert(image != (
const Image *) NULL);
1057 assert(image->signature == MagickCoreSignature);
1058 if (IsEventLogging() != MagickFalse)
1059 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1060 assert(image->cache != (Cache) NULL);
1062 assert(cache_info->signature == MagickCoreSignature);
1063 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1065 cache_info->methods.destroy_pixel_handler(image);
1068 image->cache=DestroyPixelCache(image->cache);
1094static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1100 if (cache_info->file != -1)
1102 status=close(cache_info->file);
1103 cache_info->file=(-1);
1104 RelinquishMagickResource(FileResource,1);
1106 return(status == -1 ? MagickFalse : MagickTrue);
1109static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1111 switch (cache_info->type)
1115 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1116#if defined(MAGICKCORE_OPENCL_SUPPORT)
1117 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1123 if (cache_info->mapped == MagickFalse)
1124 cache_info->pixels=(
PixelPacket *) RelinquishAlignedMemory(
1125 cache_info->pixels);
1128 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1131 RelinquishMagickResource(MemoryResource,cache_info->length);
1136 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1138 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1139 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1140 *cache_info->cache_filename=
'\0';
1141 RelinquishMagickResource(MapResource,cache_info->length);
1146 if (cache_info->file != -1)
1147 (void) ClosePixelCacheOnDisk(cache_info);
1148 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1149 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1150 *cache_info->cache_filename=
'\0';
1151 RelinquishMagickResource(DiskResource,cache_info->length);
1154 case DistributedCache:
1156 *cache_info->cache_filename=
'\0';
1158 cache_info->server_info);
1164 cache_info->type=UndefinedCache;
1165 cache_info->mapped=MagickFalse;
1166 cache_info->indexes=(IndexPacket *) NULL;
1169MagickExport Cache DestroyPixelCache(Cache cache)
1172 *magick_restrict cache_info;
1174 assert(cache != (Cache) NULL);
1176 assert(cache_info->signature == MagickCoreSignature);
1177 if (IsEventLogging() != MagickFalse)
1178 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1179 cache_info->filename);
1180 LockSemaphoreInfo(cache_info->semaphore);
1181 cache_info->reference_count--;
1182 if (cache_info->reference_count != 0)
1184 UnlockSemaphoreInfo(cache_info->semaphore);
1185 return((Cache) NULL);
1187 UnlockSemaphoreInfo(cache_info->semaphore);
1188 if (cache_info->debug != MagickFalse)
1191 message[MaxTextExtent];
1193 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1194 cache_info->filename);
1195 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1197 RelinquishPixelCachePixels(cache_info);
1200 cache_info->server_info);
1201 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1202 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1203 cache_info->number_threads);
1204 if (cache_info->random_info != (
RandomInfo *) NULL)
1205 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1207 DestroySemaphoreInfo(&cache_info->file_semaphore);
1209 DestroySemaphoreInfo(&cache_info->semaphore);
1210 cache_info->signature=(~MagickCoreSignature);
1211 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1242static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1244 if (nexus_info->mapped == MagickFalse)
1245 (void) RelinquishAlignedMemory(nexus_info->cache);
1247 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1250 nexus_info->indexes=(IndexPacket *) NULL;
1251 nexus_info->length=0;
1252 nexus_info->mapped=MagickFalse;
1256 const size_t number_threads)
1261 assert(nexus_info != (
NexusInfo **) NULL);
1262 for (i=0; i < (ssize_t) (2*number_threads); i++)
1265 RelinquishCacheNexusPixels(nexus_info[i]);
1266 nexus_info[i]->signature=(~MagickCoreSignature);
1268 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1269 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1296static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1299 *magick_restrict cache_info;
1302 id = GetOpenMPThreadId();
1304 assert(image != (
const Image *) NULL);
1305 assert(image->signature == MagickCoreSignature);
1306 assert(image->cache != (Cache) NULL);
1308 assert(cache_info->signature == MagickCoreSignature);
1309 assert(
id < (
int) cache_info->number_threads);
1310 return(cache_info->nexus_info[
id]->indexes);
1338MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1341 *magick_restrict cache_info;
1344 id = GetOpenMPThreadId();
1346 assert(image != (
const Image *) NULL);
1347 assert(image->signature == MagickCoreSignature);
1348 assert(image->cache != (Cache) NULL);
1350 assert(cache_info->signature == MagickCoreSignature);
1351 if (cache_info->methods.get_authentic_indexes_from_handler !=
1352 (GetAuthenticIndexesFromHandler) NULL)
1353 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1354 assert(
id < (
int) cache_info->number_threads);
1355 return(cache_info->nexus_info[
id]->indexes);
1358#if defined(MAGICKCORE_OPENCL_SUPPORT)
1382MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1386 *magick_restrict cache_info;
1397 assert(image != (
const Image *) NULL);
1399 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1401 SyncImagePixelCache((
Image *) image,exception);
1404 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1405 return((cl_mem) NULL);
1406 LockSemaphoreInfo(cache_info->semaphore);
1407 clEnv=GetDefaultOpenCLEnv();
1410 assert(cache_info->pixels != NULL);
1411 context=GetOpenCLContext(clEnv);
1413 sizeof(*cache_info->opencl));
1414 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1415 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1416 cache_info->opencl->length=cache_info->length;
1417 cache_info->opencl->pixels=cache_info->pixels;
1418 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1419 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1420 if (status != CL_SUCCESS)
1421 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1424 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1425 UnlockSemaphoreInfo(cache_info->semaphore);
1427 return((cl_mem) NULL);
1428 return(cache_info->opencl->buffer);
1468 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1472 *magick_restrict cache_info;
1475 *magick_restrict pixels;
1480 assert(image != (
Image *) NULL);
1481 assert(image->signature == MagickCoreSignature);
1482 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1483 nexus_info,exception);
1487 assert(cache_info->signature == MagickCoreSignature);
1488 if (nexus_info->authentic_pixel_cache != MagickFalse)
1490 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1492 if (cache_info->active_index_channel != MagickFalse)
1493 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1524 *magick_restrict cache_info;
1527 id = GetOpenMPThreadId();
1529 assert(image != (
const Image *) NULL);
1530 assert(image->signature == MagickCoreSignature);
1531 assert(image->cache != (Cache) NULL);
1533 assert(cache_info->signature == MagickCoreSignature);
1534 assert(
id < (
int) cache_info->number_threads);
1535 return(cache_info->nexus_info[
id]->pixels);
1564 *magick_restrict cache_info;
1567 id = GetOpenMPThreadId();
1569 assert(image != (
const Image *) NULL);
1570 assert(image->signature == MagickCoreSignature);
1571 assert(image->cache != (Cache) NULL);
1573 assert(cache_info->signature == MagickCoreSignature);
1574 if (cache_info->methods.get_authentic_pixels_from_handler !=
1575 (GetAuthenticPixelsFromHandler) NULL)
1576 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1577 assert(
id < (
int) cache_info->number_threads);
1578 return(cache_info->nexus_info[
id]->pixels);
1628 const ssize_t y,
const size_t columns,
const size_t rows,
1632 *magick_restrict cache_info;
1635 id = GetOpenMPThreadId();
1637 assert(image != (
Image *) NULL);
1638 assert(image->signature == MagickCoreSignature);
1639 assert(image->cache != (Cache) NULL);
1641 assert(cache_info->signature == MagickCoreSignature);
1642 if (cache_info->methods.get_authentic_pixels_handler !=
1643 (GetAuthenticPixelsHandler) NULL)
1644 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1646 assert(
id < (
int) cache_info->number_threads);
1647 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1648 cache_info->nexus_info[
id],exception));
1683 const ssize_t y,
const size_t columns,
const size_t rows,
1687 *magick_restrict cache_info;
1690 id = GetOpenMPThreadId();
1692 assert(image != (
const Image *) NULL);
1693 assert(image->signature == MagickCoreSignature);
1694 assert(image->cache != (Cache) NULL);
1696 if (cache_info == (Cache) NULL)
1698 assert(cache_info->signature == MagickCoreSignature);
1699 assert(
id < (
int) cache_info->number_threads);
1700 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1701 cache_info->nexus_info[
id],exception));
1727MagickExport MagickSizeType GetImageExtent(
const Image *image)
1730 *magick_restrict cache_info;
1733 id = GetOpenMPThreadId();
1735 assert(image != (
Image *) NULL);
1736 assert(image->signature == MagickCoreSignature);
1737 if (IsEventLogging() != MagickFalse)
1738 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1739 assert(image->cache != (Cache) NULL);
1741 assert(cache_info->signature == MagickCoreSignature);
1742 assert(
id < (
int) cache_info->number_threads);
1743 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1746#if defined(MAGICKCORE_OPENCL_SUPPORT)
1774extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1775 cl_uint *event_count)
1778 *magick_restrict cache_info;
1783 assert(image != (
const Image *) NULL);
1784 assert(event_count != (cl_uint *) NULL);
1787 events=(cl_event *) NULL;
1789 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1824static inline MagickBooleanType ValidatePixelCacheMorphology(
1825 const Image *magick_restrict image)
1828 *magick_restrict cache_info;
1834 if ((image->storage_class != cache_info->storage_class) ||
1835 (image->colorspace != cache_info->colorspace) ||
1836 (image->channels != cache_info->channels) ||
1837 (image->columns != cache_info->columns) ||
1838 (image->rows != cache_info->rows) ||
1839 (cache_info->nexus_info == (
NexusInfo **) NULL))
1840 return(MagickFalse);
1844static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1848 *magick_restrict cache_info;
1852 status = MagickTrue;
1854 static MagickSizeType
1855 cpu_throttle = MagickResourceInfinity,
1858 if (IsImageTTLExpired(image) != MagickFalse)
1863 (void) ThrowMagickException(exception,GetMagickModule(),
1864 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1865 return((Cache) NULL);
1867 if (cpu_throttle == MagickResourceInfinity)
1868 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1869 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1870 MagickDelay(cpu_throttle);
1871 LockSemaphoreInfo(image->semaphore);
1872 assert(image->cache != (Cache) NULL);
1874#if defined(MAGICKCORE_OPENCL_SUPPORT)
1875 CopyOpenCLBuffer(cache_info);
1877 destroy=MagickFalse;
1878 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1880 LockSemaphoreInfo(cache_info->semaphore);
1881 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1892 clone_image=(*image);
1893 clone_image.semaphore=AllocateSemaphoreInfo();
1894 clone_image.reference_count=1;
1895 clone_image.cache=ClonePixelCache(cache_info);
1896 clone_info=(
CacheInfo *) clone_image.cache;
1897 status=OpenPixelCache(&clone_image,IOMode,exception);
1898 if (status == MagickFalse)
1899 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1902 if (clone != MagickFalse)
1903 status=ClonePixelCacheRepository(clone_info,cache_info,
1905 if (status == MagickFalse)
1906 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1910 image->cache=clone_info;
1913 DestroySemaphoreInfo(&clone_image.semaphore);
1915 UnlockSemaphoreInfo(cache_info->semaphore);
1917 if (destroy != MagickFalse)
1918 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1919 if (status != MagickFalse)
1924 if (image->type != UndefinedType)
1925 image->type=UndefinedType;
1926 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1928 status=OpenPixelCache(image,IOMode,exception);
1930 if (cache_info->file != -1)
1931 (void) ClosePixelCacheOnDisk(cache_info);
1934 UnlockSemaphoreInfo(image->semaphore);
1935 if (status == MagickFalse)
1936 return((Cache) NULL);
1937 return(image->cache);
1964MagickExport CacheType GetPixelCacheType(
const Image *image)
1966 return(GetImagePixelCacheType(image));
1969MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1972 *magick_restrict cache_info;
1974 assert(image != (
Image *) NULL);
1975 assert(image->signature == MagickCoreSignature);
1976 assert(image->cache != (Cache) NULL);
1978 assert(cache_info->signature == MagickCoreSignature);
1979 return(cache_info->type);
2012MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
2016 *magick_restrict cache_info;
2019 *magick_restrict pixels;
2021 assert(image != (
Image *) NULL);
2022 assert(image->signature == MagickCoreSignature);
2023 assert(image->cache != (Cache) NULL);
2025 assert(cache_info->signature == MagickCoreSignature);
2026 *pixel=image->background_color;
2027 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2028 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2029 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2031 return(MagickFalse);
2067static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2071 *magick_restrict cache_info;
2074 id = GetOpenMPThreadId();
2077 *magick_restrict pixels;
2079 assert(image != (
const Image *) NULL);
2080 assert(image->signature == MagickCoreSignature);
2081 assert(image->cache != (Cache) NULL);
2083 assert(cache_info->signature == MagickCoreSignature);
2084 *pixel=image->background_color;
2085 assert(
id < (
int) cache_info->number_threads);
2086 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2087 cache_info->nexus_info[
id],exception);
2089 return(MagickFalse);
2126MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2131 *magick_restrict cache_info;
2134 id = GetOpenMPThreadId();
2137 *magick_restrict indexes;
2140 *magick_restrict pixels;
2142 assert(image != (
const Image *) NULL);
2143 assert(image->signature == MagickCoreSignature);
2144 assert(image->cache != (Cache) NULL);
2146 assert(cache_info->signature == MagickCoreSignature);
2147 assert(
id < (
int) cache_info->number_threads);
2148 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2149 1UL,1UL,cache_info->nexus_info[
id],exception);
2150 GetMagickPixelPacket(image,pixel);
2152 return(MagickFalse);
2153 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2154 SetMagickPixelPacket(image,pixels,indexes,pixel);
2193MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2194 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2198 *magick_restrict cache_info;
2201 id = GetOpenMPThreadId();
2204 *magick_restrict pixels;
2206 assert(image != (
const Image *) NULL);
2207 assert(image->signature == MagickCoreSignature);
2208 assert(image->cache != (Cache) NULL);
2210 assert(cache_info->signature == MagickCoreSignature);
2211 *pixel=image->background_color;
2212 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2213 (GetOneVirtualPixelFromHandler) NULL)
2214 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2215 virtual_pixel_method,x,y,pixel,exception));
2216 assert(
id < (
int) cache_info->number_threads);
2217 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2218 cache_info->nexus_info[
id],exception);
2220 return(MagickFalse);
2256MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2260 *magick_restrict cache_info;
2263 id = GetOpenMPThreadId();
2266 *magick_restrict pixels;
2268 assert(image != (
const Image *) NULL);
2269 assert(image->signature == MagickCoreSignature);
2270 assert(image->cache != (Cache) NULL);
2272 assert(cache_info->signature == MagickCoreSignature);
2273 *pixel=image->background_color;
2274 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2275 (GetOneVirtualPixelFromHandler) NULL)
2276 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2277 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2278 assert(
id < (
int) cache_info->number_threads);
2279 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2280 1UL,1UL,cache_info->nexus_info[
id],exception);
2282 return(MagickFalse);
2321static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2322 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2326 *magick_restrict cache_info;
2329 id = GetOpenMPThreadId();
2332 *magick_restrict pixels;
2334 assert(image != (
const Image *) NULL);
2335 assert(image->signature == MagickCoreSignature);
2336 assert(image->cache != (Cache) NULL);
2338 assert(cache_info->signature == MagickCoreSignature);
2339 assert(
id < (
int) cache_info->number_threads);
2340 *pixel=image->background_color;
2341 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2342 cache_info->nexus_info[
id],exception);
2344 return(MagickFalse);
2374MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2377 *magick_restrict cache_info;
2379 assert(cache != (Cache) NULL);
2381 assert(cache_info->signature == MagickCoreSignature);
2382 if (IsEventLogging() != MagickFalse)
2383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2384 cache_info->filename);
2385 return(cache_info->channels);
2410MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2413 *magick_restrict cache_info;
2415 assert(cache != (Cache) NULL);
2417 assert(cache_info->signature == MagickCoreSignature);
2418 if (IsEventLogging() != MagickFalse)
2419 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2420 cache_info->filename);
2421 return(cache_info->colorspace);
2447MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2450 *magick_restrict cache_info;
2452 assert(image != (
const Image *) NULL);
2453 assert(image->signature == MagickCoreSignature);
2454 assert(image->cache != (Cache) NULL);
2456 assert(cache_info->signature == MagickCoreSignature);
2457 return(cache_info->cache_filename);
2482MagickExport
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2485 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2486 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2487 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2488 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2489 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2490 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2491 cache_methods->get_authentic_indexes_from_handler=
2492 GetAuthenticIndexesFromCache;
2493 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2494 cache_methods->get_one_authentic_pixel_from_handler=
2495 GetOneAuthenticPixelFromCache;
2496 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2497 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2498 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2525MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2529 *magick_restrict cache_info;
2534 assert(cache != NULL);
2536 assert(cache_info->signature == MagickCoreSignature);
2537 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2539 return((MagickSizeType) cache_info->columns*cache_info->rows);
2570MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2574 *magick_restrict cache_info;
2576 assert(image != (
const Image *) NULL);
2577 assert(image->signature == MagickCoreSignature);
2578 assert(image->cache != (Cache) NULL);
2579 assert(length != (MagickSizeType *) NULL);
2581 assert(exception->signature == MagickCoreSignature);
2583 assert(cache_info->signature == MagickCoreSignature);
2585 *length=cache_info->length;
2586 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2587 return((
void *) NULL);
2588 return((
void *) cache_info->pixels);
2615MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2618 *magick_restrict cache_info;
2620 assert(cache != (Cache) NULL);
2622 assert(cache_info->signature == MagickCoreSignature);
2623 if (IsEventLogging() != MagickFalse)
2624 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2625 cache_info->filename);
2626 return(cache_info->storage_class);
2656MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2659 assert(image != (
Image *) NULL);
2660 assert(image->signature == MagickCoreSignature);
2661 if (IsEventLogging() != MagickFalse)
2662 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2664 if (GetImagePixelCacheType(image) == DiskCache)
2693MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2696 *magick_restrict cache_info;
2698 assert(image != (
Image *) NULL);
2699 assert(image->signature == MagickCoreSignature);
2700 assert(image->cache != (Cache) NULL);
2702 assert(cache_info->signature == MagickCoreSignature);
2703 return(cache_info->virtual_pixel_method);
2729static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2732 *magick_restrict cache_info;
2735 id = GetOpenMPThreadId();
2737 assert(image != (
const Image *) NULL);
2738 assert(image->signature == MagickCoreSignature);
2739 assert(image->cache != (Cache) NULL);
2741 assert(cache_info->signature == MagickCoreSignature);
2742 assert(
id < (
int) cache_info->number_threads);
2743 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2772MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2776 *magick_restrict cache_info;
2778 assert(cache != (Cache) NULL);
2780 assert(cache_info->signature == MagickCoreSignature);
2781 if (cache_info->storage_class == UndefinedClass)
2782 return((IndexPacket *) NULL);
2783 return(nexus_info->indexes);
2811MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2814 *magick_restrict cache_info;
2817 id = GetOpenMPThreadId();
2819 assert(image != (
const Image *) NULL);
2820 assert(image->signature == MagickCoreSignature);
2821 assert(image->cache != (Cache) NULL);
2823 assert(cache_info->signature == MagickCoreSignature);
2824 if (cache_info->methods.get_virtual_indexes_from_handler !=
2825 (GetVirtualIndexesFromHandler) NULL)
2830 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2831 if (indexes != (IndexPacket *) NULL)
2834 assert(
id < (
int) cache_info->number_threads);
2835 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2878 0, 48, 12, 60, 3, 51, 15, 63,
2879 32, 16, 44, 28, 35, 19, 47, 31,
2880 8, 56, 4, 52, 11, 59, 7, 55,
2881 40, 24, 36, 20, 43, 27, 39, 23,
2882 2, 50, 14, 62, 1, 49, 13, 61,
2883 34, 18, 46, 30, 33, 17, 45, 29,
2884 10, 58, 6, 54, 9, 57, 5, 53,
2885 42, 26, 38, 22, 41, 25, 37, 21
2888static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2893 index=x+DitherMatrix[x & 0x07]-32L;
2896 if (index >= (ssize_t) columns)
2897 return((ssize_t) columns-1L);
2901static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2906 index=y+DitherMatrix[y & 0x07]-32L;
2909 if (index >= (ssize_t) rows)
2910 return((ssize_t) rows-1L);
2914static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2918 if (x >= (ssize_t) columns)
2919 return((ssize_t) (columns-1));
2923static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2927 if (y >= (ssize_t) rows)
2928 return((ssize_t) (rows-1));
2932static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2935 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2936 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2937 return(MagickFalse);
2941static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2943 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2946static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2948 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2951static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2952 const size_t extent)
2957 modulo.quotient=offset;
2961 modulo.quotient=offset/((ssize_t) extent);
2962 modulo.remainder=offset % ((ssize_t) extent);
2964 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2967 modulo.remainder+=((ssize_t) extent);
2972MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2973 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2974 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2978 *magick_restrict cache_info;
2981 *magick_restrict virtual_indexes;
2988 *magick_restrict indexes;
2998 *magick_restrict virtual_nexus;
3001 *magick_restrict pixels,
3012 assert(image != (
const Image *) NULL);
3013 assert(image->signature == MagickCoreSignature);
3014 assert(image->cache != (Cache) NULL);
3016 assert(cache_info->signature == MagickCoreSignature);
3017 if (cache_info->type == UndefinedCache)
3019#if defined(MAGICKCORE_OPENCL_SUPPORT)
3020 CopyOpenCLBuffer(cache_info);
3022 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3023 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
3024 MagickTrue : MagickFalse,nexus_info,exception);
3027 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3029 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3030 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3032 offset+=nexus_info->region.x;
3033 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3034 nexus_info->region.width-1L;
3035 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3036 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3037 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3038 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3046 if (nexus_info->authentic_pixel_cache != MagickFalse)
3048 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3049 if (status == MagickFalse)
3051 if ((cache_info->storage_class == PseudoClass) ||
3052 (cache_info->colorspace == CMYKColorspace))
3054 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3055 if (status == MagickFalse)
3063 virtual_nexus=nexus_info->virtual_nexus;
3065 indexes=nexus_info->indexes;
3066 switch (virtual_pixel_method)
3068 case BlackVirtualPixelMethod:
3070 SetPixelRed(&virtual_pixel,0);
3071 SetPixelGreen(&virtual_pixel,0);
3072 SetPixelBlue(&virtual_pixel,0);
3073 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3076 case GrayVirtualPixelMethod:
3078 SetPixelRed(&virtual_pixel,QuantumRange/2);
3079 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3080 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3081 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3084 case TransparentVirtualPixelMethod:
3086 SetPixelRed(&virtual_pixel,0);
3087 SetPixelGreen(&virtual_pixel,0);
3088 SetPixelBlue(&virtual_pixel,0);
3089 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3092 case MaskVirtualPixelMethod:
3093 case WhiteVirtualPixelMethod:
3095 SetPixelRed(&virtual_pixel,QuantumRange);
3096 SetPixelGreen(&virtual_pixel,QuantumRange);
3097 SetPixelBlue(&virtual_pixel,QuantumRange);
3098 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3103 virtual_pixel=image->background_color;
3107 virtual_index=(IndexPacket) 0;
3108 for (v=0; v < (ssize_t) rows; v++)
3114 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3115 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3116 y_offset=EdgeY(y_offset,cache_info->rows);
3117 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3123 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3124 (ssize_t) columns-u);
3125 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3126 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3136 length=(MagickSizeType) 1;
3137 switch (virtual_pixel_method)
3139 case BackgroundVirtualPixelMethod:
3140 case ConstantVirtualPixelMethod:
3141 case BlackVirtualPixelMethod:
3142 case GrayVirtualPixelMethod:
3143 case TransparentVirtualPixelMethod:
3144 case MaskVirtualPixelMethod:
3145 case WhiteVirtualPixelMethod:
3148 virtual_indexes=(&virtual_index);
3151 case EdgeVirtualPixelMethod:
3154 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3155 EdgeX(x_offset,cache_info->columns),
3156 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3158 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3162 case RandomVirtualPixelMethod:
3164 if (cache_info->random_info == (
RandomInfo *) NULL)
3165 cache_info->random_info=AcquireRandomInfo();
3166 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3167 RandomX(cache_info->random_info,cache_info->columns),
3168 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3169 virtual_nexus,exception);
3170 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3174 case DitherVirtualPixelMethod:
3176 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3177 DitherX(x_offset,cache_info->columns),
3178 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3180 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3184 case TileVirtualPixelMethod:
3186 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3187 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3188 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3189 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3191 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3195 case MirrorVirtualPixelMethod:
3197 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3198 if ((x_modulo.quotient & 0x01) == 1L)
3199 x_modulo.remainder=(ssize_t) cache_info->columns-
3200 x_modulo.remainder-1L;
3201 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3202 if ((y_modulo.quotient & 0x01) == 1L)
3203 y_modulo.remainder=(ssize_t) cache_info->rows-
3204 y_modulo.remainder-1L;
3205 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3206 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3208 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3212 case CheckerTileVirtualPixelMethod:
3214 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3215 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3216 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3219 virtual_indexes=(&virtual_index);
3222 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3223 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3225 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3229 case HorizontalTileVirtualPixelMethod:
3231 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3234 virtual_indexes=(&virtual_index);
3237 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3238 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3239 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3240 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3242 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3246 case VerticalTileVirtualPixelMethod:
3248 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3251 virtual_indexes=(&virtual_index);
3254 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3255 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3256 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3257 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3259 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3263 case HorizontalTileEdgeVirtualPixelMethod:
3265 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3266 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3267 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3268 virtual_nexus,exception);
3269 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3273 case VerticalTileEdgeVirtualPixelMethod:
3275 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3276 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3277 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3278 virtual_nexus,exception);
3279 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3287 if ((indexes != (IndexPacket *) NULL) &&
3288 (virtual_indexes != (
const IndexPacket *) NULL))
3289 *indexes++=(*virtual_indexes);
3295 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3296 (
size_t) length,1UL,virtual_nexus,exception);
3299 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3300 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3301 q+=(ptrdiff_t) length;
3302 if ((indexes != (IndexPacket *) NULL) &&
3303 (virtual_indexes != (
const IndexPacket *) NULL))
3305 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3306 sizeof(*virtual_indexes));
3310 if (u < (ssize_t) columns)
3316 if (v < (ssize_t) rows)
3356 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3357 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3360 *magick_restrict cache_info;
3363 id = GetOpenMPThreadId();
3365 assert(image != (
const Image *) NULL);
3366 assert(image->signature == MagickCoreSignature);
3367 assert(image->cache != (Cache) NULL);
3369 assert(cache_info->signature == MagickCoreSignature);
3370 assert(
id < (
int) cache_info->number_threads);
3371 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3372 cache_info->nexus_info[
id],exception));
3401 *magick_restrict cache_info;
3404 id = GetOpenMPThreadId();
3406 assert(image != (
const Image *) NULL);
3407 assert(image->signature == MagickCoreSignature);
3408 assert(image->cache != (Cache) NULL);
3410 assert(cache_info->signature == MagickCoreSignature);
3411 if (cache_info->methods.get_virtual_pixels_handler !=
3412 (GetVirtualPixelsHandler) NULL)
3413 return(cache_info->methods.get_virtual_pixels_handler(image));
3414 assert(
id < (
int) cache_info->number_threads);
3415 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3467 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3471 *magick_restrict cache_info;
3474 id = GetOpenMPThreadId();
3476 assert(image != (
const Image *) NULL);
3477 assert(image->signature == MagickCoreSignature);
3478 assert(image->cache != (Cache) NULL);
3480 assert(cache_info->signature == MagickCoreSignature);
3481 if (cache_info->methods.get_virtual_pixel_handler !=
3482 (GetVirtualPixelHandler) NULL)
3483 return(cache_info->methods.get_virtual_pixel_handler(image,
3484 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3485 assert(
id < (
int) cache_info->number_threads);
3486 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3487 columns,rows,cache_info->nexus_info[
id],exception));
3516 *magick_restrict cache_info;
3519 id = GetOpenMPThreadId();
3521 assert(image != (
const Image *) NULL);
3522 assert(image->signature == MagickCoreSignature);
3523 assert(image->cache != (Cache) NULL);
3525 assert(cache_info->signature == MagickCoreSignature);
3526 assert(
id < (
int) cache_info->number_threads);
3527 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3556MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3560 *magick_restrict cache_info;
3562 assert(cache != (Cache) NULL);
3564 assert(cache_info->signature == MagickCoreSignature);
3565 if (cache_info->storage_class == UndefinedClass)
3607 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3612 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3613 gamma=PerceptibleReciprocal(gamma);
3614 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3615 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3616 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3617 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3618 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3621static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3625 *magick_restrict cache_info;
3631 *magick_restrict nexus_indexes,
3632 *magick_restrict indexes;
3642 **magick_restrict mask_nexus;
3654 if (IsEventLogging() != MagickFalse)
3655 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3656 if ((image->mask == (
Image *) NULL) || (image->storage_class == PseudoClass))
3658 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3661 if (cache_info == (Cache) NULL)
3662 return(MagickFalse);
3663 mask_nexus=AcquirePixelCacheNexus(1);
3664 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3665 nexus_info->virtual_nexus,exception);
3666 indexes=nexus_info->virtual_nexus->indexes;
3667 q=nexus_info->pixels;
3668 nexus_indexes=nexus_info->indexes;
3669 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3670 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3671 nexus_info->region.height,mask_nexus[0],&image->exception);
3674 return(MagickFalse);
3676 GetMagickPixelPacket(image,&alpha);
3677 GetMagickPixelPacket(image,&beta);
3678 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3683 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3685 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3686 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3687 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3688 alpha.opacity,&beta);
3689 SetPixelRed(q,ClampToQuantum(beta.red));
3690 SetPixelGreen(q,ClampToQuantum(beta.green));
3691 SetPixelBlue(q,ClampToQuantum(beta.blue));
3692 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3693 if (cache_info->active_index_channel != MagickFalse)
3694 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3701 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3736static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3745 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3747 if (*cache_info->cache_filename ==
'\0')
3748 file=AcquireUniqueFileResource(cache_info->cache_filename);
3754 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3759 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3760 O_BINARY | O_EXCL,S_MODE);
3762 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3768 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3771 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3776 return(MagickFalse);
3777 (void) AcquireMagickResource(FileResource,1);
3778 if (cache_info->file != -1)
3779 (void) ClosePixelCacheOnDisk(cache_info);
3780 cache_info->file=file;
3781 cache_info->disk_mode=mode;
3785static inline MagickOffsetType WritePixelCacheRegion(
3786 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3787 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3795#if !defined(MAGICKCORE_HAVE_PWRITE)
3796 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3797 return((MagickOffsetType) -1);
3799 for (i=0; i < (MagickOffsetType) length; i+=count)
3801#if !defined(MAGICKCORE_HAVE_PWRITE)
3802 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3803 (MagickSizeType) i,MagickMaxBufferExtent));
3805 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3806 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3818static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3821 *magick_restrict cache_info;
3827 if (cache_info->debug != MagickFalse)
3830 format[MaxTextExtent],
3831 message[MaxTextExtent];
3833 (void) FormatMagickSize(length,MagickFalse,format);
3834 (void) FormatLocaleString(message,MaxTextExtent,
3835 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3836 cache_info->cache_filename,cache_info->file,format);
3837 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3839 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3841 return(MagickFalse);
3842 if ((MagickSizeType) offset < length)
3848 extent=(MagickOffsetType) length-1;
3849 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3852 return(MagickFalse);
3853#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3854 if (cache_info->synchronize != MagickFalse)
3855 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3856 return(MagickFalse);
3859 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3861 return(MagickFalse);
3865static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3869 *magick_restrict cache_info,
3873 format[MaxTextExtent],
3874 message[MaxTextExtent];
3891 assert(image != (
const Image *) NULL);
3892 assert(image->signature == MagickCoreSignature);
3893 assert(image->cache != (Cache) NULL);
3894 if (IsEventLogging() != MagickFalse)
3895 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3896 if (cache_anonymous_memory < 0)
3904 cache_anonymous_memory=0;
3905 value=GetPolicyValue(
"pixel-cache-memory");
3906 if (value == (
char *) NULL)
3907 value=GetPolicyValue(
"cache:memory-map");
3908 if (LocaleCompare(value,
"anonymous") == 0)
3910#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3911 cache_anonymous_memory=1;
3913 (void) ThrowMagickException(exception,GetMagickModule(),
3914 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3915 "'%s' (policy requires anonymous memory mapping)",image->filename);
3918 value=DestroyString(value);
3920 if ((image->columns == 0) || (image->rows == 0))
3921 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3923 assert(cache_info->signature == MagickCoreSignature);
3924 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3925 ((MagickSizeType) image->rows > cache_info->height_limit))
3926 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3928 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3930 length=GetImageListLength(image);
3931 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3932 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3935 source_info=(*cache_info);
3936 source_info.file=(-1);
3937 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3938 image->filename,(
double) image->scene);
3939 cache_info->storage_class=image->storage_class;
3940 cache_info->colorspace=image->colorspace;
3941 cache_info->rows=image->rows;
3942 cache_info->columns=image->columns;
3943 cache_info->channels=image->channels;
3944 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3945 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3946 cache_info->mode=mode;
3947 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3949 if (cache_info->active_index_channel != MagickFalse)
3950 packet_size+=
sizeof(IndexPacket);
3951 length=number_pixels*packet_size;
3952 columns=(size_t) (length/cache_info->rows/packet_size);
3953 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3954 ((ssize_t) cache_info->rows < 0))
3955 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3957 cache_info->length=length;
3958 if (image->ping != MagickFalse)
3960 cache_info->type=PingCache;
3963 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3964 cache_info->columns*cache_info->rows);
3965 if (cache_info->mode == PersistMode)
3967 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
3968 if ((status != MagickFalse) &&
3969 (length == (MagickSizeType) ((
size_t) length)) &&
3970 ((cache_info->type == UndefinedCache) ||
3971 (cache_info->type == MemoryCache)))
3973 status=AcquireMagickResource(MemoryResource,cache_info->length);
3974 if (status != MagickFalse)
3977 if (cache_anonymous_memory <= 0)
3979 cache_info->mapped=MagickFalse;
3980 cache_info->pixels=(
PixelPacket *) MagickAssumeAligned(
3981 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3985 cache_info->mapped=MagickTrue;
3986 cache_info->pixels=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
3987 cache_info->length);
3991 cache_info->mapped=source_info.mapped;
3992 cache_info->pixels=source_info.pixels;
3999 cache_info->colorspace=image->colorspace;
4000 cache_info->type=MemoryCache;
4001 cache_info->indexes=(IndexPacket *) NULL;
4002 if (cache_info->active_index_channel != MagickFalse)
4003 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4005 if ((source_info.storage_class != UndefinedClass) &&
4008 status&=ClonePixelCacheRepository(cache_info,&source_info,
4010 RelinquishPixelCachePixels(&source_info);
4012 if (cache_info->debug != MagickFalse)
4014 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4015 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4017 (void) FormatLocaleString(message,MaxTextExtent,
4018 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4019 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4020 type,(
double) cache_info->columns,(
double) cache_info->rows,
4022 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4025 cache_info->storage_class=image->storage_class;
4028 if ((source_info.storage_class != UndefinedClass) &&
4030 RelinquishPixelCachePixels(&source_info);
4031 cache_info->type=UndefinedCache;
4032 return(MagickFalse);
4038 status=AcquireMagickResource(DiskResource,cache_info->length);
4039 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4041 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4049 server_info=AcquireDistributeCacheInfo(exception);
4052 status=OpenDistributePixelCache(server_info,image);
4053 if (status == MagickFalse)
4055 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4056 GetDistributeCacheHostname(server_info));
4057 server_info=DestroyDistributeCacheInfo(server_info);
4065 cache_info->type=DistributedCache;
4066 cache_info->storage_class=image->storage_class;
4067 cache_info->colorspace=image->colorspace;
4068 cache_info->server_info=server_info;
4069 (void) FormatLocaleString(cache_info->cache_filename,
4070 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4073 cache_info->server_info));
4074 if ((source_info.storage_class != UndefinedClass) &&
4077 status=ClonePixelCacheRepository(cache_info,&source_info,
4079 RelinquishPixelCachePixels(&source_info);
4081 if (cache_info->debug != MagickFalse)
4083 (void) FormatMagickSize(cache_info->length,MagickFalse,
4085 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4087 (void) FormatLocaleString(message,MaxTextExtent,
4088 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4089 cache_info->cache_filename,GetDistributeCacheFile(
4091 (
double) cache_info->columns,(
double) cache_info->rows,
4093 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4098 if ((source_info.storage_class != UndefinedClass) &&
4100 RelinquishPixelCachePixels(&source_info);
4101 cache_info->type=UndefinedCache;
4102 return(MagickFalse);
4107 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4108 RelinquishPixelCachePixels(&source_info);
4109 cache_info->type=UndefinedCache;
4110 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4111 "CacheResourcesExhausted",
"`%s'",image->filename);
4112 return(MagickFalse);
4117 if (status == MagickFalse)
4119 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4120 RelinquishPixelCachePixels(&source_info);
4121 cache_info->type=UndefinedCache;
4122 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4123 "CacheResourcesExhausted",
"`%s'",image->filename);
4124 return(MagickFalse);
4126 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4127 (cache_info->mode != PersistMode))
4129 (void) ClosePixelCacheOnDisk(cache_info);
4130 *cache_info->cache_filename=
'\0';
4132 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4134 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4135 RelinquishPixelCachePixels(&source_info);
4136 cache_info->type=UndefinedCache;
4137 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4139 return(MagickFalse);
4141 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4142 cache_info->length);
4143 if (status == MagickFalse)
4145 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4146 RelinquishPixelCachePixels(&source_info);
4147 cache_info->type=UndefinedCache;
4148 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4150 return(MagickFalse);
4152 cache_info->storage_class=image->storage_class;
4153 cache_info->colorspace=image->colorspace;
4154 cache_info->type=DiskCache;
4155 length=number_pixels*(
sizeof(
PixelPacket)+
sizeof(IndexPacket));
4156 if (length == (MagickSizeType) ((
size_t) length))
4158 status=AcquireMagickResource(MapResource,cache_info->length);
4159 if (status != MagickFalse)
4161 cache_info->pixels=(
PixelPacket *) MapBlob(cache_info->file,mode,
4162 cache_info->offset,(
size_t) cache_info->length);
4165 cache_info->mapped=source_info.mapped;
4166 cache_info->pixels=source_info.pixels;
4167 RelinquishMagickResource(MapResource,cache_info->length);
4174 (void) ClosePixelCacheOnDisk(cache_info);
4175 cache_info->type=MapCache;
4176 cache_info->mapped=MagickTrue;
4177 cache_info->indexes=(IndexPacket *) NULL;
4178 if (cache_info->active_index_channel != MagickFalse)
4179 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4181 if ((source_info.storage_class != UndefinedClass) &&
4184 status=ClonePixelCacheRepository(cache_info,&source_info,
4186 RelinquishPixelCachePixels(&source_info);
4188 if (cache_info->debug != MagickFalse)
4190 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4191 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4193 (void) FormatLocaleString(message,MaxTextExtent,
4194 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4195 cache_info->filename,cache_info->cache_filename,
4196 cache_info->file,type,(
double) cache_info->columns,
4197 (
double) cache_info->rows,format);
4198 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4203 if ((source_info.storage_class != UndefinedClass) &&
4205 RelinquishPixelCachePixels(&source_info);
4206 cache_info->type=UndefinedCache;
4207 return(MagickFalse);
4214 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4216 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4217 RelinquishPixelCachePixels(&source_info);
4219 if (cache_info->debug != MagickFalse)
4221 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4222 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4224 (void) FormatLocaleString(message,MaxTextExtent,
4225 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4226 cache_info->cache_filename,cache_info->file,type,(
double)
4227 cache_info->columns,(
double) cache_info->rows,format);
4228 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4232 cache_info->type=UndefinedCache;
4233 return(MagickFalse);
4275MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4276 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4280 *magick_restrict cache_info,
4281 *magick_restrict clone_info;
4289 assert(image != (
Image *) NULL);
4290 assert(image->signature == MagickCoreSignature);
4291 if (IsEventLogging() != MagickFalse)
4292 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4293 assert(image->cache != (
void *) NULL);
4294 assert(filename != (
const char *) NULL);
4295 assert(offset != (MagickOffsetType *) NULL);
4296 page_size=GetMagickPageSize();
4298 assert(cache_info->signature == MagickCoreSignature);
4299#if defined(MAGICKCORE_OPENCL_SUPPORT)
4300 CopyOpenCLBuffer(cache_info);
4302 if (attach != MagickFalse)
4307 if (cache_info->debug != MagickFalse)
4308 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4309 "attach persistent cache");
4310 (void) CopyMagickString(cache_info->cache_filename,filename,
4312 cache_info->type=MapCache;
4313 cache_info->offset=(*offset);
4314 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4315 return(MagickFalse);
4316 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4317 ((MagickOffsetType) cache_info->length % page_size));
4323 status=AcquireMagickResource(DiskResource,cache_info->length);
4324 if (status == MagickFalse)
4326 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4327 "CacheResourcesExhausted",
"`%s'",image->filename);
4328 return(MagickFalse);
4330 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4331 clone_info->type=DiskCache;
4332 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4333 clone_info->file=(-1);
4334 clone_info->storage_class=cache_info->storage_class;
4335 clone_info->colorspace=cache_info->colorspace;
4336 clone_info->columns=cache_info->columns;
4337 clone_info->rows=cache_info->rows;
4338 clone_info->active_index_channel=cache_info->active_index_channel;
4339 clone_info->mode=PersistMode;
4340 clone_info->length=cache_info->length;
4341 clone_info->channels=cache_info->channels;
4342 clone_info->offset=(*offset);
4343 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4344 if (status != MagickFalse)
4345 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4346 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4347 ((MagickOffsetType) cache_info->length % page_size));
4348 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4391 const ssize_t y,
const size_t columns,
const size_t rows,
4392 const MagickBooleanType clone,
NexusInfo *nexus_info,
4395 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4400 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4404 *magick_restrict cache_info;
4413 *magick_restrict pixels;
4418 assert(image != (
const Image *) NULL);
4419 assert(image->signature == MagickCoreSignature);
4420 assert(image->cache != (Cache) NULL);
4421 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4422 if (cache_info == (Cache) NULL)
4424 assert(cache_info->signature == MagickCoreSignature);
4425 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4426 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4427 (y >= (ssize_t) cache_info->rows))
4429 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4430 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4433 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4435 offset=y*(MagickOffsetType) cache_info->columns+x;
4438 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4439 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4440 (MagickOffsetType) columns-1;
4441 if ((MagickSizeType) offset >= number_pixels)
4446 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4447 (image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL) ?
4448 MagickTrue : MagickFalse,nexus_info,exception);
4486 const ssize_t y,
const size_t columns,
const size_t rows,
4490 *magick_restrict cache_info;
4493 id = GetOpenMPThreadId();
4495 assert(image != (
const Image *) NULL);
4496 assert(image->signature == MagickCoreSignature);
4497 assert(image->cache != (Cache) NULL);
4499 assert(cache_info->signature == MagickCoreSignature);
4500 assert(
id < (
int) cache_info->number_threads);
4501 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4502 cache_info->nexus_info[
id],exception));
4561MagickExport
PixelPacket *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4562 const ssize_t y,
const size_t columns,
const size_t rows,
4566 *magick_restrict cache_info;
4569 id = GetOpenMPThreadId();
4571 assert(image != (
Image *) NULL);
4572 assert(image->signature == MagickCoreSignature);
4573 assert(image->cache != (Cache) NULL);
4575 assert(cache_info->signature == MagickCoreSignature);
4576 if (cache_info->methods.queue_authentic_pixels_handler !=
4577 (QueueAuthenticPixelsHandler) NULL)
4578 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4580 assert(
id < (
int) cache_info->number_threads);
4581 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4582 cache_info->nexus_info[
id],exception));
4614static inline MagickOffsetType ReadPixelCacheRegion(
4615 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4616 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4624#if !defined(MAGICKCORE_HAVE_PREAD)
4625 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4626 return((MagickOffsetType) -1);
4628 for (i=0; i < (MagickOffsetType) length; i+=count)
4630#if !defined(MAGICKCORE_HAVE_PREAD)
4631 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4632 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4634 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4635 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4647static MagickBooleanType ReadPixelCacheIndexes(
4668 if (cache_info->active_index_channel == MagickFalse)
4669 return(MagickFalse);
4670 if (nexus_info->authentic_pixel_cache != MagickFalse)
4672 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4673 return(MagickFalse);
4674 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4675 nexus_info->region.x;
4676 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4677 rows=nexus_info->region.height;
4679 q=nexus_info->indexes;
4681 switch (cache_info->type)
4692 if ((cache_info->columns == nexus_info->region.width) &&
4693 (extent == (MagickSizeType) ((
size_t) extent)))
4698 p=cache_info->indexes+offset;
4699 for (y=0; y < (ssize_t) rows; y++)
4701 (void) memcpy(q,p,(
size_t) length);
4702 p+=(ptrdiff_t) cache_info->columns;
4703 q+=(ptrdiff_t) nexus_info->region.width;
4712 LockSemaphoreInfo(cache_info->file_semaphore);
4713 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4715 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4716 cache_info->cache_filename);
4717 UnlockSemaphoreInfo(cache_info->file_semaphore);
4718 return(MagickFalse);
4720 if ((cache_info->columns == nexus_info->region.width) &&
4721 (extent <= MagickMaxBufferExtent))
4726 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4727 for (y=0; y < (ssize_t) rows; y++)
4729 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4730 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
4731 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4732 if (count < (MagickOffsetType) length)
4734 offset+=(MagickOffsetType) cache_info->columns;
4735 q+=(ptrdiff_t) nexus_info->region.width;
4737 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4738 (void) ClosePixelCacheOnDisk(cache_info);
4739 UnlockSemaphoreInfo(cache_info->file_semaphore);
4742 case DistributedCache:
4750 LockSemaphoreInfo(cache_info->file_semaphore);
4751 region=nexus_info->region;
4752 if ((cache_info->columns != nexus_info->region.width) ||
4753 (extent > MagickMaxBufferExtent))
4760 for (y=0; y < (ssize_t) rows; y++)
4763 cache_info->server_info,®ion,length,(
unsigned char *) q);
4764 if (count != (MagickOffsetType) length)
4766 q+=(ptrdiff_t) nexus_info->region.width;
4769 UnlockSemaphoreInfo(cache_info->file_semaphore);
4775 if (y < (ssize_t) rows)
4777 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4778 cache_info->cache_filename);
4779 return(MagickFalse);
4781 if ((cache_info->debug != MagickFalse) &&
4782 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4783 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4784 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4785 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4786 nexus_info->region.x,(
double) nexus_info->region.y);
4818static MagickBooleanType ReadPixelCachePixels(
4839 if (nexus_info->authentic_pixel_cache != MagickFalse)
4841 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4842 return(MagickFalse);
4843 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4844 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4845 return(MagickFalse);
4846 offset+=nexus_info->region.x;
4847 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
4848 if ((length/
sizeof(
PixelPacket)) != nexus_info->region.width)
4849 return(MagickFalse);
4850 rows=nexus_info->region.height;
4852 if ((extent == 0) || ((extent/length) != rows))
4853 return(MagickFalse);
4854 q=nexus_info->pixels;
4856 switch (cache_info->type)
4867 if ((cache_info->columns == nexus_info->region.width) &&
4868 (extent == (MagickSizeType) ((
size_t) extent)))
4873 p=cache_info->pixels+offset;
4874 for (y=0; y < (ssize_t) rows; y++)
4876 (void) memcpy(q,p,(
size_t) length);
4877 p+=(ptrdiff_t) cache_info->columns;
4878 q+=(ptrdiff_t) nexus_info->region.width;
4887 LockSemaphoreInfo(cache_info->file_semaphore);
4888 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4890 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4891 cache_info->cache_filename);
4892 UnlockSemaphoreInfo(cache_info->file_semaphore);
4893 return(MagickFalse);
4895 if ((cache_info->columns == nexus_info->region.width) &&
4896 (extent <= MagickMaxBufferExtent))
4901 for (y=0; y < (ssize_t) rows; y++)
4903 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4904 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4905 if (count < (MagickOffsetType) length)
4907 offset+=(MagickOffsetType) cache_info->columns;
4908 q+=(ptrdiff_t) nexus_info->region.width;
4910 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4911 (void) ClosePixelCacheOnDisk(cache_info);
4912 UnlockSemaphoreInfo(cache_info->file_semaphore);
4915 case DistributedCache:
4923 LockSemaphoreInfo(cache_info->file_semaphore);
4924 region=nexus_info->region;
4925 if ((cache_info->columns != nexus_info->region.width) ||
4926 (extent > MagickMaxBufferExtent))
4933 for (y=0; y < (ssize_t) rows; y++)
4936 cache_info->server_info,®ion,length,(
unsigned char *) q);
4937 if (count != (MagickOffsetType) length)
4939 q+=(ptrdiff_t) nexus_info->region.width;
4942 UnlockSemaphoreInfo(cache_info->file_semaphore);
4948 if (y < (ssize_t) rows)
4950 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4951 cache_info->cache_filename);
4952 return(MagickFalse);
4954 if ((cache_info->debug != MagickFalse) &&
4955 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4956 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4957 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4958 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4959 nexus_info->region.x,(
double) nexus_info->region.y);
4986MagickExport Cache ReferencePixelCache(Cache cache)
4989 *magick_restrict cache_info;
4991 assert(cache != (Cache *) NULL);
4993 assert(cache_info->signature == MagickCoreSignature);
4994 LockSemaphoreInfo(cache_info->semaphore);
4995 cache_info->reference_count++;
4996 UnlockSemaphoreInfo(cache_info->semaphore);
5018MagickPrivate
void ResetCacheAnonymousMemory(
void)
5020 cache_anonymous_memory=0;
5047MagickExport
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5050 *magick_restrict cache_info;
5052 GetOneAuthenticPixelFromHandler
5053 get_one_authentic_pixel_from_handler;
5055 GetOneVirtualPixelFromHandler
5056 get_one_virtual_pixel_from_handler;
5061 assert(cache != (Cache) NULL);
5064 assert(cache_info->signature == MagickCoreSignature);
5065 if (IsEventLogging() != MagickFalse)
5066 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5067 cache_info->filename);
5068 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5069 cache_info->methods.get_virtual_pixel_handler=
5070 cache_methods->get_virtual_pixel_handler;
5071 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5072 cache_info->methods.destroy_pixel_handler=
5073 cache_methods->destroy_pixel_handler;
5074 if (cache_methods->get_virtual_indexes_from_handler !=
5075 (GetVirtualIndexesFromHandler) NULL)
5076 cache_info->methods.get_virtual_indexes_from_handler=
5077 cache_methods->get_virtual_indexes_from_handler;
5078 if (cache_methods->get_authentic_pixels_handler !=
5079 (GetAuthenticPixelsHandler) NULL)
5080 cache_info->methods.get_authentic_pixels_handler=
5081 cache_methods->get_authentic_pixels_handler;
5082 if (cache_methods->queue_authentic_pixels_handler !=
5083 (QueueAuthenticPixelsHandler) NULL)
5084 cache_info->methods.queue_authentic_pixels_handler=
5085 cache_methods->queue_authentic_pixels_handler;
5086 if (cache_methods->sync_authentic_pixels_handler !=
5087 (SyncAuthenticPixelsHandler) NULL)
5088 cache_info->methods.sync_authentic_pixels_handler=
5089 cache_methods->sync_authentic_pixels_handler;
5090 if (cache_methods->get_authentic_pixels_from_handler !=
5091 (GetAuthenticPixelsFromHandler) NULL)
5092 cache_info->methods.get_authentic_pixels_from_handler=
5093 cache_methods->get_authentic_pixels_from_handler;
5094 if (cache_methods->get_authentic_indexes_from_handler !=
5095 (GetAuthenticIndexesFromHandler) NULL)
5096 cache_info->methods.get_authentic_indexes_from_handler=
5097 cache_methods->get_authentic_indexes_from_handler;
5098 get_one_virtual_pixel_from_handler=
5099 cache_info->methods.get_one_virtual_pixel_from_handler;
5100 if (get_one_virtual_pixel_from_handler !=
5101 (GetOneVirtualPixelFromHandler) NULL)
5102 cache_info->methods.get_one_virtual_pixel_from_handler=
5103 cache_methods->get_one_virtual_pixel_from_handler;
5104 get_one_authentic_pixel_from_handler=
5105 cache_methods->get_one_authentic_pixel_from_handler;
5106 if (get_one_authentic_pixel_from_handler !=
5107 (GetOneAuthenticPixelFromHandler) NULL)
5108 cache_info->methods.get_one_authentic_pixel_from_handler=
5109 cache_methods->get_one_authentic_pixel_from_handler;
5150static inline MagickBooleanType AcquireCacheNexusPixels(
5151 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5154 if (length != (MagickSizeType) ((
size_t) length))
5156 (void) ThrowMagickException(exception,GetMagickModule(),
5157 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5158 cache_info->filename);
5159 return(MagickFalse);
5161 nexus_info->length=0;
5162 nexus_info->mapped=MagickFalse;
5163 if (cache_anonymous_memory <= 0)
5165 nexus_info->cache=(
PixelPacket *) MagickAssumeAligned(
5166 AcquireAlignedMemory(1,(
size_t) length));
5168 (void) memset(nexus_info->cache,0,(
size_t) length);
5172 nexus_info->cache=(
PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5174 nexus_info->mapped=MagickTrue;
5178 (void) ThrowMagickException(exception,GetMagickModule(),
5179 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5180 cache_info->filename);
5181 return(MagickFalse);
5183 nexus_info->length=length;
5187static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5190 if (nexus_info->length < CACHE_LINE_SIZE)
5192 if (mode == ReadMode)
5194 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5198 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5201static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5204 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5205 return(MagickFalse);
5206 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5207 return(MagickFalse);
5212 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5213 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5214 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5224 assert(cache_info != (
const CacheInfo *) NULL);
5225 assert(cache_info->signature == MagickCoreSignature);
5226 if (cache_info->type == UndefinedCache)
5228 assert(nexus_info->signature == MagickCoreSignature);
5229 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5230 if ((width == 0) || (height == 0))
5232 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5233 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5236 if (((MagickSizeType) width > cache_info->width_limit) ||
5237 ((MagickSizeType) height > cache_info->height_limit))
5239 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5240 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5243 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5244 (ValidatePixelOffset(y,height) == MagickFalse))
5246 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5247 "InvalidPixel",
"`%s'",cache_info->filename);
5250 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5251 (buffered == MagickFalse))
5253 if (((x >= 0) && (y >= 0) &&
5254 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5255 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5256 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5264 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5266 offset=y*(MagickOffsetType) cache_info->columns+x;
5267 nexus_info->pixels=cache_info->pixels+offset;
5268 nexus_info->indexes=(IndexPacket *) NULL;
5269 if (cache_info->active_index_channel != MagickFalse)
5270 nexus_info->indexes=cache_info->indexes+offset;
5271 nexus_info->region.width=width;
5272 nexus_info->region.height=height;
5273 nexus_info->region.x=x;
5274 nexus_info->region.y=y;
5275 nexus_info->authentic_pixel_cache=MagickTrue;
5276 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5277 return(nexus_info->pixels);
5283 number_pixels=(MagickSizeType) width*height;
5284 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5286 if (cache_info->active_index_channel != MagickFalse)
5287 length+=number_pixels*
sizeof(IndexPacket);
5290 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5292 if (nexus_info->length < length)
5294 RelinquishCacheNexusPixels(nexus_info);
5295 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5297 if (status == MagickFalse)
5299 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5302 nexus_info->pixels=nexus_info->cache;
5303 nexus_info->indexes=(IndexPacket *) NULL;
5304 if (cache_info->active_index_channel != MagickFalse)
5305 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5306 nexus_info->region.width=width;
5307 nexus_info->region.height=height;
5308 nexus_info->region.x=x;
5309 nexus_info->region.y=y;
5310 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5311 MagickTrue : MagickFalse;
5312 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5313 return(nexus_info->pixels);
5344static MagickBooleanType SetCacheAlphaChannel(
Image *image,
5345 const Quantum opacity)
5348 *magick_restrict image_view;
5356 assert(image != (
Image *) NULL);
5357 assert(image->signature == MagickCoreSignature);
5358 if (IsEventLogging() != MagickFalse)
5359 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5360 assert(image->cache != (Cache) NULL);
5361 image->matte=MagickTrue;
5363 image_view=AcquireVirtualCacheView(image,&image->exception);
5364#if defined(MAGICKCORE_OPENMP_SUPPORT)
5365 #pragma omp parallel for schedule(static) shared(status) \
5366 magick_number_threads(image,image,image->rows,2)
5368 for (y=0; y < (ssize_t) image->rows; y++)
5376 if (status == MagickFalse)
5378 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5385 for (x=0; x < (ssize_t) image->columns; x++)
5390 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5392 image_view=DestroyCacheView(image_view);
5396MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5397 const VirtualPixelMethod virtual_pixel_method)
5400 *magick_restrict cache_info;
5405 assert(image != (
Image *) NULL);
5406 assert(image->signature == MagickCoreSignature);
5407 if (IsEventLogging() != MagickFalse)
5408 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5409 assert(image->cache != (Cache) NULL);
5411 assert(cache_info->signature == MagickCoreSignature);
5412 method=cache_info->virtual_pixel_method;
5413 cache_info->virtual_pixel_method=virtual_pixel_method;
5414 if ((image->columns != 0) && (image->rows != 0))
5415 switch (virtual_pixel_method)
5417 case BackgroundVirtualPixelMethod:
5419 if ((image->background_color.opacity != OpaqueOpacity) &&
5420 (image->matte == MagickFalse))
5421 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5422 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5423 (IsGrayColorspace(image->colorspace) != MagickFalse))
5424 (void) SetImageColorspace((
Image *) image,sRGBColorspace);
5427 case TransparentVirtualPixelMethod:
5429 if (image->matte == MagickFalse)
5430 (void) SetCacheAlphaChannel((
Image *) image,OpaqueOpacity);
5439#if defined(MAGICKCORE_OPENCL_SUPPORT)
5463static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5468 assert(cache_info != (
CacheInfo *)NULL);
5469 if ((cache_info->type != MemoryCache) ||
5475 LockSemaphoreInfo(cache_info->semaphore);
5484 clEnv=GetDefaultOpenCLEnv();
5485 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5486 if (events != (cl_event *) NULL)
5500 context=GetOpenCLContext(clEnv);
5501 queue=AcquireOpenCLCommandQueue(clEnv);
5502 pixels=(
PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5503 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5504 cache_info->length,event_count,events,NULL,&status);
5505 assert(pixels == cache_info->pixels);
5506 events=(cl_event *) RelinquishMagickMemory(events);
5507 RelinquishOpenCLCommandQueue(clEnv,queue);
5509 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5511 UnlockSemaphoreInfo(cache_info->semaphore);
5514MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5517 *magick_restrict cache_info;
5519 assert(image != (
Image *)NULL);
5521 CopyOpenCLBuffer(cache_info);
5554MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5558 *magick_restrict cache_info;
5566 assert(image != (
Image *) NULL);
5567 assert(image->signature == MagickCoreSignature);
5568 if (image->cache == (Cache) NULL)
5569 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5571 assert(cache_info->signature == MagickCoreSignature);
5572 if (cache_info->type == UndefinedCache)
5573 return(MagickFalse);
5574 if ((image->storage_class == DirectClass) &&
5575 (image->clip_mask != (
Image *) NULL) &&
5576 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5577 return(MagickFalse);
5578 if ((image->storage_class == DirectClass) &&
5579 (image->mask != (
Image *) NULL) &&
5580 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5581 return(MagickFalse);
5582 if (nexus_info->authentic_pixel_cache != MagickFalse)
5584 if (image->taint == MagickFalse)
5585 image->taint=MagickTrue;
5588 assert(cache_info->signature == MagickCoreSignature);
5589 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5590 if ((cache_info->active_index_channel != MagickFalse) &&
5591 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5592 return(MagickFalse);
5593 if ((status != MagickFalse) && (image->taint == MagickFalse))
5594 image->taint=MagickTrue;
5625static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5629 *magick_restrict cache_info;
5632 id = GetOpenMPThreadId();
5637 assert(image != (
Image *) NULL);
5638 assert(image->signature == MagickCoreSignature);
5639 assert(image->cache != (Cache) NULL);
5641 assert(cache_info->signature == MagickCoreSignature);
5642 assert(
id < (
int) cache_info->number_threads);
5643 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5675MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5679 *magick_restrict cache_info;
5682 id = GetOpenMPThreadId();
5687 assert(image != (
Image *) NULL);
5688 assert(image->signature == MagickCoreSignature);
5689 assert(image->cache != (Cache) NULL);
5691 assert(cache_info->signature == MagickCoreSignature);
5692 if (cache_info->methods.sync_authentic_pixels_handler !=
5693 (SyncAuthenticPixelsHandler) NULL)
5694 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5695 assert(
id < (
int) cache_info->number_threads);
5696 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5728MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5732 *magick_restrict cache_info;
5734 assert(image != (
Image *) NULL);
5736 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5737 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5768static MagickBooleanType WritePixelCacheIndexes(
CacheInfo *cache_info,
5788 if (cache_info->active_index_channel == MagickFalse)
5789 return(MagickFalse);
5790 if (nexus_info->authentic_pixel_cache != MagickFalse)
5792 if (nexus_info->indexes == (IndexPacket *) NULL)
5793 return(MagickFalse);
5794 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5795 return(MagickFalse);
5796 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5797 nexus_info->region.x;
5798 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5799 rows=nexus_info->region.height;
5800 extent=(MagickSizeType) length*rows;
5801 p=nexus_info->indexes;
5803 switch (cache_info->type)
5814 if ((cache_info->columns == nexus_info->region.width) &&
5815 (extent == (MagickSizeType) ((
size_t) extent)))
5820 q=cache_info->indexes+offset;
5821 for (y=0; y < (ssize_t) rows; y++)
5823 (void) memcpy(q,p,(
size_t) length);
5824 p+=(ptrdiff_t) nexus_info->region.width;
5825 q+=(ptrdiff_t) cache_info->columns;
5834 LockSemaphoreInfo(cache_info->file_semaphore);
5835 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5837 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5838 cache_info->cache_filename);
5839 UnlockSemaphoreInfo(cache_info->file_semaphore);
5840 return(MagickFalse);
5842 if ((cache_info->columns == nexus_info->region.width) &&
5843 (extent <= MagickMaxBufferExtent))
5848 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5849 for (y=0; y < (ssize_t) rows; y++)
5851 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5852 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(
PixelPacket)+
5853 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5855 if (count < (MagickOffsetType) length)
5857 p+=(ptrdiff_t) nexus_info->region.width;
5858 offset+=(MagickOffsetType) cache_info->columns;
5860 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5861 (void) ClosePixelCacheOnDisk(cache_info);
5862 UnlockSemaphoreInfo(cache_info->file_semaphore);
5865 case DistributedCache:
5873 LockSemaphoreInfo(cache_info->file_semaphore);
5874 region=nexus_info->region;
5875 if ((cache_info->columns != nexus_info->region.width) ||
5876 (extent > MagickMaxBufferExtent))
5883 for (y=0; y < (ssize_t) rows; y++)
5886 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5887 if (count != (MagickOffsetType) length)
5889 p+=(ptrdiff_t) nexus_info->region.width;
5892 UnlockSemaphoreInfo(cache_info->file_semaphore);
5898 if (y < (ssize_t) rows)
5900 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5901 cache_info->cache_filename);
5902 return(MagickFalse);
5904 if ((cache_info->debug != MagickFalse) &&
5905 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5906 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5907 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5908 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5909 nexus_info->region.x,(
double) nexus_info->region.y);
5941static MagickBooleanType WritePixelCachePixels(
CacheInfo *cache_info,
5961 if (nexus_info->authentic_pixel_cache != MagickFalse)
5963 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5964 return(MagickFalse);
5965 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5966 nexus_info->region.x;
5967 length=(MagickSizeType) nexus_info->region.width*
sizeof(
PixelPacket);
5968 rows=nexus_info->region.height;
5970 p=nexus_info->pixels;
5972 switch (cache_info->type)
5983 if ((cache_info->columns == nexus_info->region.width) &&
5984 (extent == (MagickSizeType) ((
size_t) extent)))
5989 q=cache_info->pixels+offset;
5990 for (y=0; y < (ssize_t) rows; y++)
5992 (void) memcpy(q,p,(
size_t) length);
5993 p+=(ptrdiff_t) nexus_info->region.width;
5994 q+=(ptrdiff_t) cache_info->columns;
6003 LockSemaphoreInfo(cache_info->file_semaphore);
6004 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6006 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6007 cache_info->cache_filename);
6008 UnlockSemaphoreInfo(cache_info->file_semaphore);
6009 return(MagickFalse);
6011 if ((cache_info->columns == nexus_info->region.width) &&
6012 (extent <= MagickMaxBufferExtent))
6017 for (y=0; y < (ssize_t) rows; y++)
6019 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6020 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6021 if (count < (MagickOffsetType) length)
6023 p+=(ptrdiff_t) nexus_info->region.width;
6024 offset+=(MagickOffsetType) cache_info->columns;
6026 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6027 (void) ClosePixelCacheOnDisk(cache_info);
6028 UnlockSemaphoreInfo(cache_info->file_semaphore);
6031 case DistributedCache:
6039 LockSemaphoreInfo(cache_info->file_semaphore);
6040 region=nexus_info->region;
6041 if ((cache_info->columns != nexus_info->region.width) ||
6042 (extent > MagickMaxBufferExtent))
6049 for (y=0; y < (ssize_t) rows; y++)
6052 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6053 if (count != (MagickOffsetType) length)
6055 p+=(ptrdiff_t) nexus_info->region.width;
6058 UnlockSemaphoreInfo(cache_info->file_semaphore);
6064 if (y < (ssize_t) rows)
6066 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6067 cache_info->cache_filename);
6068 return(MagickFalse);
6070 if ((cache_info->debug != MagickFalse) &&
6071 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6072 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6073 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6074 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6075 nexus_info->region.x,(
double) nexus_info->region.y);