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)
108 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
111static const IndexPacket
112 *GetVirtualIndexesFromCache(
const Image *);
114static const PixelPacket
115 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
116 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
117 *GetVirtualPixelsCache(
const Image *);
119static MagickBooleanType
120 GetOneAuthenticPixelFromCache(Image *,
const ssize_t,
const ssize_t,
121 PixelPacket *,ExceptionInfo *),
122 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
123 const ssize_t,
const ssize_t,PixelPacket *,ExceptionInfo *),
124 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
125 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
126 ReadPixelCacheIndexes(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
128 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
130 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
131 WritePixelCacheIndexes(CacheInfo *,NexusInfo *magick_restrict,
133 WritePixelCachePixels(CacheInfo *,NexusInfo *magick_restrict,
137 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
138 const size_t,ExceptionInfo *),
139 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
140 const size_t,ExceptionInfo *),
141 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
142 const ssize_t,
const ssize_t,
const size_t,
const size_t,
143 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
146#if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(CacheInfo *magick_restrict);
151#if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
164#if defined(MAGICKCORE_OPENCL_SUPPORT)
165static inline OpenCLCacheInfo *RelinquishOpenCLCacheInfo(MagickCLEnv clEnv,
166 OpenCLCacheInfo *info)
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;
180 return((OpenCLCacheInfo *) RelinquishMagickMemory(info));
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);
201 info=(OpenCLCacheInfo *) user_data;
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(
227 CacheInfo *magick_restrict cache_info)
232 assert(cache_info != (CacheInfo *) NULL);
233 if (cache_info->opencl == (OpenCLCacheInfo *) NULL)
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
239static cl_event *CopyOpenCLEvents(OpenCLCacheInfo *opencl_info,
240 cl_uint *event_count)
248 assert(opencl_info != (OpenCLCacheInfo *) NULL);
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);
304 cache_info=(CacheInfo *)image->cache;
305 assert(cache_info->opencl != (OpenCLCacheInfo *) 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));
361 if (cache_info == (CacheInfo *) NULL)
362 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
363 (void) memset(cache_info,0,
sizeof(*cache_info));
364 cache_info->type=UndefinedCache;
365 cache_info->mode=IOMode;
366 cache_info->disk_mode=IOMode;
367 cache_info->colorspace=sRGBColorspace;
368 cache_info->channels=4;
369 cache_info->file=(-1);
370 cache_info->id=GetMagickThreadId();
371 cache_info->number_threads=number_threads;
372 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
373 cache_info->number_threads=GetOpenMPMaximumThreads();
374 if (cache_info->number_threads == 0)
375 cache_info->number_threads=1;
376 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
377 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
378 if (value != (
const char *) NULL)
380 cache_info->synchronize=IsStringTrue(value);
381 value=DestroyString(value);
383 value=GetPolicyValue(
"cache:synchronize");
384 if (value != (
const char *) NULL)
386 cache_info->synchronize=IsStringTrue(value);
387 value=DestroyString(value);
389 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
390 (MagickSizeType) MAGICK_SSIZE_MAX);
391 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
392 (MagickSizeType) MAGICK_SSIZE_MAX);
393 cache_info->semaphore=AllocateSemaphoreInfo();
394 cache_info->reference_count=1;
395 cache_info->file_semaphore=AllocateSemaphoreInfo();
396 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
397 cache_info->signature=MagickCoreSignature;
398 return((Cache ) cache_info);
423MagickExport NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
426 **magick_restrict nexus_info;
431 nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
432 number_threads,
sizeof(*nexus_info)));
433 if (nexus_info == (NexusInfo **) NULL)
434 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
435 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
436 2*
sizeof(**nexus_info));
437 if (*nexus_info == (NexusInfo *) NULL)
438 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
439 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
440 for (i=0; i < (ssize_t) (2*number_threads); i++)
442 nexus_info[i]=(*nexus_info+i);
443 if (i < (ssize_t) number_threads)
444 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
445 nexus_info[i]->signature=MagickCoreSignature;
478MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
479 MagickSizeType *length,ExceptionInfo *exception)
482 *magick_restrict cache_info;
484 assert(image != (
const Image *) NULL);
485 assert(image->signature == MagickCoreSignature);
486 assert(exception != (ExceptionInfo *) NULL);
487 assert(exception->signature == MagickCoreSignature);
488 assert(image->cache != (Cache) NULL);
489 cache_info=(CacheInfo *) image->cache;
490 assert(cache_info->signature == MagickCoreSignature);
493 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
494 return((
const void *) NULL);
495 *length=cache_info->length;
496 return((
const void *) cache_info->pixels);
517MagickExport MagickBooleanType CacheComponentGenesis(
void)
520 cache_semaphore=AllocateSemaphoreInfo();
542MagickExport
void CacheComponentTerminus(
void)
545 ActivateSemaphoreInfo(&cache_semaphore);
547 DestroySemaphoreInfo(&cache_semaphore);
579static MagickBooleanType ClipPixelCacheNexus(Image *image,
580 NexusInfo *nexus_info,ExceptionInfo *exception)
583 *magick_restrict cache_info;
589 *magick_restrict nexus_indexes,
590 *magick_restrict indexes;
596 **magick_restrict clip_nexus;
608 if (IsEventLogging() != MagickFalse)
609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
610 if ((image->clip_mask == (Image *) NULL) ||
611 (image->storage_class == PseudoClass))
613 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
615 cache_info=(CacheInfo *) image->cache;
616 if (cache_info == (Cache) NULL)
618 clip_nexus=AcquirePixelCacheNexus(1);
619 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
620 nexus_info->region.width,nexus_info->region.height,
621 nexus_info->virtual_nexus,exception);
622 indexes=nexus_info->virtual_nexus->indexes;
623 q=nexus_info->pixels;
624 nexus_indexes=nexus_info->indexes;
625 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
626 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
627 nexus_info->region.height,clip_nexus[0],exception);
628 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL) ||
629 (r == (
const PixelPacket *) NULL))
632 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
637 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
642 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
643 if (fabs(mask_alpha) >= MagickEpsilon)
645 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
646 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
647 GetPixelOpacity(q)));
648 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
649 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
650 GetPixelOpacity(q)));
651 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
652 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
653 GetPixelOpacity(q)));
654 SetPixelOpacity(q,GetPixelOpacity(p));
655 if (cache_info->active_index_channel != MagickFalse)
656 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
664 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
690MagickExport Cache ClonePixelCache(
const Cache cache)
693 *magick_restrict clone_info;
696 *magick_restrict cache_info;
698 assert(cache != NULL);
699 cache_info=(
const CacheInfo *) cache;
700 assert(cache_info->signature == MagickCoreSignature);
701 if (IsEventLogging() != MagickFalse)
702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
703 cache_info->filename);
704 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
705 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
706 return((Cache ) clone_info);
734MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
737 *magick_restrict cache_info,
738 *magick_restrict source_info;
740 assert(clone != (Cache) NULL);
741 source_info=(CacheInfo *) clone;
742 assert(source_info->signature == MagickCoreSignature);
743 if (IsEventLogging() != MagickFalse)
744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
745 source_info->filename);
746 assert(cache != (Cache) NULL);
747 cache_info=(CacheInfo *) cache;
748 assert(cache_info->signature == MagickCoreSignature);
749 source_info->methods=cache_info->methods;
781static MagickBooleanType ClonePixelCacheOnDisk(
782 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
802 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
803 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
805 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
806 (lseek(clone_info->file,0,SEEK_SET) < 0))
808 quantum=(size_t) MagickMaxBufferExtent;
809 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
811#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
812 if (cache_info->length < 0x7ffff000)
814 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
815 (
size_t) cache_info->length);
816 if (count == (ssize_t) cache_info->length)
818 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
819 (lseek(clone_info->file,0,SEEK_SET) < 0))
823 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
825 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
826 if (buffer == (
unsigned char *) NULL)
827 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
829 while ((count=read(cache_info->file,buffer,quantum)) > 0)
834 number_bytes=write(clone_info->file,buffer,(
size_t) count);
835 if (number_bytes != count)
837 extent+=(size_t) number_bytes;
839 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
840 if (extent != cache_info->length)
845static inline int GetCacheNumberThreads(
const CacheInfo *source,
846 const CacheInfo *destination,
const size_t chunk,
const int factor)
849 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
851 workload_factor = 64UL << factor;
856 number_threads=(chunk <= workload_factor) ? 1 :
857 (chunk >= (workload_factor << 6)) ? max_threads :
858 1+(chunk-workload_factor)*(max_threads-1)/(((workload_factor << 6))-1);
862 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
863 ((destination->type != MemoryCache) && (destination->type != MapCache)))
864 number_threads=MagickMin(number_threads,4);
865 return((
int) number_threads);
868static MagickBooleanType ClonePixelCacheRepository(
869 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
870 ExceptionInfo *exception)
872#define cache_number_threads(source,destination,chunk,factor) \
873 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
879 **magick_restrict cache_nexus,
880 **magick_restrict clone_nexus;
888 assert(cache_info != (CacheInfo *) NULL);
889 assert(clone_info != (CacheInfo *) NULL);
890 assert(exception != (ExceptionInfo *) NULL);
891 if (cache_info->type == PingCache)
893 if ((cache_info->storage_class == clone_info->storage_class) &&
894 (cache_info->colorspace == clone_info->colorspace) &&
895 (cache_info->channels == clone_info->channels) &&
896 (cache_info->columns == clone_info->columns) &&
897 (cache_info->rows == clone_info->rows) &&
898 (cache_info->active_index_channel == clone_info->active_index_channel))
903 if (((cache_info->type == MemoryCache) ||
904 (cache_info->type == MapCache)) &&
905 ((clone_info->type == MemoryCache) ||
906 (clone_info->type == MapCache)))
908 (void) memcpy(clone_info->pixels,cache_info->pixels,
909 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
910 if ((cache_info->active_index_channel != MagickFalse) &&
911 (clone_info->active_index_channel != MagickFalse))
912 (void) memcpy(clone_info->indexes,cache_info->indexes,
913 cache_info->columns*cache_info->rows*
914 sizeof(*cache_info->indexes));
917 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
918 return(ClonePixelCacheOnDisk(cache_info,clone_info));
923 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
924 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
925 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
926 sizeof(*cache_info->pixels);
928#if defined(MAGICKCORE_OPENMP_SUPPORT)
929 #pragma omp parallel for schedule(static) shared(status) \
930 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
932 for (y=0; y < (ssize_t) cache_info->rows; y++)
935 id = GetOpenMPThreadId();
940 if (status == MagickFalse)
942 if (y >= (ssize_t) clone_info->rows)
944 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
945 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
946 if (pixels == (PixelPacket *) NULL)
948 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
949 if (status == MagickFalse)
951 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
952 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
953 if (pixels == (PixelPacket *) NULL)
955 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
956 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
957 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
959 if ((cache_info->active_index_channel != MagickFalse) &&
960 (clone_info->active_index_channel != MagickFalse))
965 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
966 sizeof(*cache_info->indexes);
967#if defined(MAGICKCORE_OPENMP_SUPPORT)
968 #pragma omp parallel for schedule(static) shared(status) \
969 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
971 for (y=0; y < (ssize_t) cache_info->rows; y++)
974 id = GetOpenMPThreadId();
979 if (status == MagickFalse)
981 if (y >= (ssize_t) clone_info->rows)
983 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
984 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
985 if (pixels == (PixelPacket *) NULL)
987 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
988 if (status == MagickFalse)
990 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
991 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
992 if (pixels == (PixelPacket *) NULL)
994 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
995 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
998 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
999 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
1000 if (cache_info->debug != MagickFalse)
1003 message[MaxTextExtent];
1005 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
1006 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
1007 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
1008 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1035static void DestroyImagePixelCache(Image *image)
1037 assert(image != (Image *) NULL);
1038 assert(image->signature == MagickCoreSignature);
1039 if (IsEventLogging() != MagickFalse)
1040 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1041 if (image->cache != (
void *) NULL)
1042 image->cache=DestroyPixelCache(image->cache);
1067MagickExport
void DestroyImagePixels(Image *image)
1070 *magick_restrict cache_info;
1072 assert(image != (
const Image *) NULL);
1073 assert(image->signature == MagickCoreSignature);
1074 if (IsEventLogging() != MagickFalse)
1075 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1076 assert(image->cache != (Cache) NULL);
1077 cache_info=(CacheInfo *) image->cache;
1078 assert(cache_info->signature == MagickCoreSignature);
1079 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1081 cache_info->methods.destroy_pixel_handler(image);
1084 image->cache=DestroyPixelCache(image->cache);
1110static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
1116 if (cache_info->file != -1)
1118 status=close(cache_info->file);
1119 cache_info->file=(-1);
1120 RelinquishMagickResource(FileResource,1);
1122 return(status == -1 ? MagickFalse : MagickTrue);
1125static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1127 switch (cache_info->type)
1131 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1132#if defined(MAGICKCORE_OPENCL_SUPPORT)
1133 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1135 cache_info->pixels=(PixelPacket *) NULL;
1139 if (cache_info->mapped == MagickFalse)
1140 cache_info->pixels=(PixelPacket *) RelinquishAlignedMemory(
1141 cache_info->pixels);
1144 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1145 cache_info->pixels=(PixelPacket *) NULL;
1147 RelinquishMagickResource(MemoryResource,cache_info->length);
1152 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1153 cache_info->pixels=(PixelPacket *) NULL;
1154 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1155 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1156 *cache_info->cache_filename=
'\0';
1157 RelinquishMagickResource(MapResource,cache_info->length);
1162 if (cache_info->file != -1)
1163 (void) ClosePixelCacheOnDisk(cache_info);
1164 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1165 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1166 *cache_info->cache_filename=
'\0';
1167 RelinquishMagickResource(DiskResource,cache_info->length);
1170 case DistributedCache:
1172 *cache_info->cache_filename=
'\0';
1173 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1174 cache_info->server_info);
1180 cache_info->type=UndefinedCache;
1181 cache_info->mapped=MagickFalse;
1182 cache_info->indexes=(IndexPacket *) NULL;
1185MagickExport Cache DestroyPixelCache(Cache cache)
1188 *magick_restrict cache_info;
1190 assert(cache != (Cache) NULL);
1191 cache_info=(CacheInfo *) cache;
1192 assert(cache_info->signature == MagickCoreSignature);
1193 if (IsEventLogging() != MagickFalse)
1194 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1195 cache_info->filename);
1196 LockSemaphoreInfo(cache_info->semaphore);
1197 cache_info->reference_count--;
1198 if (cache_info->reference_count != 0)
1200 UnlockSemaphoreInfo(cache_info->semaphore);
1201 return((Cache) NULL);
1203 UnlockSemaphoreInfo(cache_info->semaphore);
1204 if (cache_info->debug != MagickFalse)
1207 message[MaxTextExtent];
1209 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1210 cache_info->filename);
1211 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1213 RelinquishPixelCachePixels(cache_info);
1214 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1215 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1216 cache_info->server_info);
1217 if (cache_info->nexus_info != (NexusInfo **) NULL)
1218 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1219 cache_info->number_threads);
1220 if (cache_info->random_info != (RandomInfo *) NULL)
1221 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1223 DestroySemaphoreInfo(&cache_info->file_semaphore);
1225 DestroySemaphoreInfo(&cache_info->semaphore);
1226 cache_info->signature=(~MagickCoreSignature);
1227 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1258static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1260 if (nexus_info->mapped == MagickFalse)
1261 (void) RelinquishAlignedMemory(nexus_info->cache);
1263 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1264 nexus_info->cache=(PixelPacket *) NULL;
1265 nexus_info->pixels=(PixelPacket *) NULL;
1266 nexus_info->indexes=(IndexPacket *) NULL;
1267 nexus_info->length=0;
1268 nexus_info->mapped=MagickFalse;
1271MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1272 const size_t number_threads)
1277 assert(nexus_info != (NexusInfo **) NULL);
1278 for (i=0; i < (ssize_t) (2*number_threads); i++)
1280 if (nexus_info[i]->cache != (PixelPacket *) NULL)
1281 RelinquishCacheNexusPixels(nexus_info[i]);
1282 nexus_info[i]->signature=(~MagickCoreSignature);
1284 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1285 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1312static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1315 *magick_restrict cache_info;
1318 id = GetOpenMPThreadId();
1320 assert(image != (
const Image *) NULL);
1321 assert(image->signature == MagickCoreSignature);
1322 assert(image->cache != (Cache) NULL);
1323 cache_info=(CacheInfo *) image->cache;
1324 assert(cache_info->signature == MagickCoreSignature);
1325 assert(
id < (
int) cache_info->number_threads);
1326 return(cache_info->nexus_info[
id]->indexes);
1354MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1357 *magick_restrict cache_info;
1360 id = GetOpenMPThreadId();
1362 assert(image != (
const Image *) NULL);
1363 assert(image->signature == MagickCoreSignature);
1364 assert(image->cache != (Cache) NULL);
1365 cache_info=(CacheInfo *) image->cache;
1366 assert(cache_info->signature == MagickCoreSignature);
1367 if (cache_info->methods.get_authentic_indexes_from_handler !=
1368 (GetAuthenticIndexesFromHandler) NULL)
1369 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1370 assert(
id < (
int) cache_info->number_threads);
1371 return(cache_info->nexus_info[
id]->indexes);
1374#if defined(MAGICKCORE_OPENCL_SUPPORT)
1398MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1399 ExceptionInfo *exception)
1402 *magick_restrict cache_info;
1413 assert(image != (
const Image *) NULL);
1414 cache_info=(CacheInfo *)image->cache;
1415 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1417 SyncImagePixelCache((Image *) image,exception);
1418 cache_info=(CacheInfo *)image->cache;
1420 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1421 return((cl_mem) NULL);
1422 LockSemaphoreInfo(cache_info->semaphore);
1423 clEnv=GetDefaultOpenCLEnv();
1424 if (cache_info->opencl == (OpenCLCacheInfo *) NULL)
1426 assert(cache_info->pixels != NULL);
1427 context=GetOpenCLContext(clEnv);
1428 cache_info->opencl=(OpenCLCacheInfo *) AcquireCriticalMemory(
1429 sizeof(*cache_info->opencl));
1430 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1431 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1432 cache_info->opencl->length=cache_info->length;
1433 cache_info->opencl->pixels=cache_info->pixels;
1434 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1435 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1436 if (status != CL_SUCCESS)
1437 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1439 if (cache_info->opencl != (OpenCLCacheInfo *) NULL)
1440 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1441 UnlockSemaphoreInfo(cache_info->semaphore);
1442 if (cache_info->opencl == (OpenCLCacheInfo *) NULL)
1443 return((cl_mem) NULL);
1444 return(cache_info->opencl->buffer);
1483MagickExport PixelPacket *GetAuthenticPixelCacheNexus(Image *image,
1484 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1485 NexusInfo *nexus_info,ExceptionInfo *exception)
1488 *magick_restrict cache_info;
1491 *magick_restrict pixels;
1496 assert(image != (Image *) NULL);
1497 assert(image->signature == MagickCoreSignature);
1498 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1499 nexus_info,exception);
1500 if (pixels == (PixelPacket *) NULL)
1501 return((PixelPacket *) NULL);
1502 cache_info=(CacheInfo *) image->cache;
1503 assert(cache_info->signature == MagickCoreSignature);
1504 if (nexus_info->authentic_pixel_cache != MagickFalse)
1506 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1507 return((PixelPacket *) NULL);
1508 if (cache_info->active_index_channel != MagickFalse)
1509 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1510 return((PixelPacket *) NULL);
1537static PixelPacket *GetAuthenticPixelsFromCache(
const Image *image)
1540 *magick_restrict cache_info;
1543 id = GetOpenMPThreadId();
1545 assert(image != (
const Image *) NULL);
1546 assert(image->signature == MagickCoreSignature);
1547 assert(image->cache != (Cache) NULL);
1548 cache_info=(CacheInfo *) image->cache;
1549 assert(cache_info->signature == MagickCoreSignature);
1550 assert(
id < (
int) cache_info->number_threads);
1551 return(cache_info->nexus_info[
id]->pixels);
1577MagickExport PixelPacket *GetAuthenticPixelQueue(
const Image *image)
1580 *magick_restrict cache_info;
1583 id = GetOpenMPThreadId();
1585 assert(image != (
const Image *) NULL);
1586 assert(image->signature == MagickCoreSignature);
1587 assert(image->cache != (Cache) NULL);
1588 cache_info=(CacheInfo *) image->cache;
1589 assert(cache_info->signature == MagickCoreSignature);
1590 if (cache_info->methods.get_authentic_pixels_from_handler !=
1591 (GetAuthenticPixelsFromHandler) NULL)
1592 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1593 assert(
id < (
int) cache_info->number_threads);
1594 return(cache_info->nexus_info[
id]->pixels);
1643MagickExport PixelPacket *GetAuthenticPixels(Image *image,
const ssize_t x,
1644 const ssize_t y,
const size_t columns,
const size_t rows,
1645 ExceptionInfo *exception)
1648 *magick_restrict cache_info;
1651 id = GetOpenMPThreadId();
1653 assert(image != (Image *) NULL);
1654 assert(image->signature == MagickCoreSignature);
1655 assert(image->cache != (Cache) NULL);
1656 cache_info=(CacheInfo *) image->cache;
1657 assert(cache_info->signature == MagickCoreSignature);
1658 if (cache_info->methods.get_authentic_pixels_handler !=
1659 (GetAuthenticPixelsHandler) NULL)
1660 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1662 assert(
id < (
int) cache_info->number_threads);
1663 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1664 cache_info->nexus_info[
id],exception));
1698static PixelPacket *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1699 const ssize_t y,
const size_t columns,
const size_t rows,
1700 ExceptionInfo *exception)
1703 *magick_restrict cache_info;
1706 id = GetOpenMPThreadId();
1708 assert(image != (
const Image *) NULL);
1709 assert(image->signature == MagickCoreSignature);
1710 assert(image->cache != (Cache) NULL);
1711 cache_info=(CacheInfo *) image->cache;
1712 if (cache_info == (Cache) NULL)
1713 return((PixelPacket *) NULL);
1714 assert(cache_info->signature == MagickCoreSignature);
1715 assert(
id < (
int) cache_info->number_threads);
1716 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1717 cache_info->nexus_info[
id],exception));
1743MagickExport MagickSizeType GetImageExtent(
const Image *image)
1746 *magick_restrict cache_info;
1749 id = GetOpenMPThreadId();
1751 assert(image != (Image *) NULL);
1752 assert(image->signature == MagickCoreSignature);
1753 if (IsEventLogging() != MagickFalse)
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1755 assert(image->cache != (Cache) NULL);
1756 cache_info=(CacheInfo *) image->cache;
1757 assert(cache_info->signature == MagickCoreSignature);
1758 assert(
id < (
int) cache_info->number_threads);
1759 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1762#if defined(MAGICKCORE_OPENCL_SUPPORT)
1790extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1791 cl_uint *event_count)
1794 *magick_restrict cache_info;
1799 assert(image != (
const Image *) NULL);
1800 assert(event_count != (cl_uint *) NULL);
1801 cache_info=(CacheInfo *) image->cache;
1803 events=(cl_event *) NULL;
1804 if (cache_info->opencl != (OpenCLCacheInfo *) NULL)
1805 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1840static inline MagickBooleanType ValidatePixelCacheMorphology(
1841 const Image *magick_restrict image)
1844 *magick_restrict cache_info;
1849 cache_info=(CacheInfo *) image->cache;
1850 if ((image->storage_class != cache_info->storage_class) ||
1851 (image->colorspace != cache_info->colorspace) ||
1852 (image->channels != cache_info->channels) ||
1853 (image->columns != cache_info->columns) ||
1854 (image->rows != cache_info->rows) ||
1855 (cache_info->nexus_info == (NexusInfo **) NULL))
1856 return(MagickFalse);
1860static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1861 ExceptionInfo *exception)
1864 *magick_restrict cache_info;
1868 status = MagickTrue;
1870 static MagickSizeType
1871 cpu_throttle = MagickResourceInfinity,
1874 if (IsImageTTLExpired(image) != MagickFalse)
1879 (void) ThrowMagickException(exception,GetMagickModule(),
1880 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1881 return((Cache) NULL);
1883 if (cpu_throttle == MagickResourceInfinity)
1884 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1885 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1886 MagickDelay(cpu_throttle);
1887 LockSemaphoreInfo(image->semaphore);
1888 assert(image->cache != (Cache) NULL);
1889 cache_info=(CacheInfo *) image->cache;
1890#if defined(MAGICKCORE_OPENCL_SUPPORT)
1891 CopyOpenCLBuffer(cache_info);
1893 destroy=MagickFalse;
1894 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1896 LockSemaphoreInfo(cache_info->semaphore);
1897 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1908 clone_image=(*image);
1909 clone_image.semaphore=AllocateSemaphoreInfo();
1910 clone_image.reference_count=1;
1911 clone_image.cache=ClonePixelCache(cache_info);
1912 clone_info=(CacheInfo *) clone_image.cache;
1913 status=OpenPixelCache(&clone_image,IOMode,exception);
1914 if (status == MagickFalse)
1915 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1918 if (clone != MagickFalse)
1919 status=ClonePixelCacheRepository(clone_info,cache_info,
1921 if (status == MagickFalse)
1922 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1926 image->cache=clone_info;
1929 DestroySemaphoreInfo(&clone_image.semaphore);
1931 UnlockSemaphoreInfo(cache_info->semaphore);
1933 if (destroy != MagickFalse)
1934 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1935 if (status != MagickFalse)
1940 if (image->type != UndefinedType)
1941 image->type=UndefinedType;
1942 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1944 status=OpenPixelCache(image,IOMode,exception);
1945 cache_info=(CacheInfo *) image->cache;
1946 if (cache_info->file != -1)
1947 (void) ClosePixelCacheOnDisk(cache_info);
1950 UnlockSemaphoreInfo(image->semaphore);
1951 if (status == MagickFalse)
1952 return((Cache) NULL);
1953 return(image->cache);
1980MagickExport CacheType GetPixelCacheType(
const Image *image)
1982 return(GetImagePixelCacheType(image));
1985MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1988 *magick_restrict cache_info;
1990 assert(image != (Image *) NULL);
1991 assert(image->signature == MagickCoreSignature);
1992 assert(image->cache != (Cache) NULL);
1993 cache_info=(CacheInfo *) image->cache;
1994 assert(cache_info->signature == MagickCoreSignature);
1995 return(cache_info->type);
2028MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2029 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2032 *magick_restrict cache_info;
2035 *magick_restrict pixels;
2037 assert(image != (Image *) NULL);
2038 assert(image->signature == MagickCoreSignature);
2039 assert(image->cache != (Cache) NULL);
2040 cache_info=(CacheInfo *) image->cache;
2041 assert(cache_info->signature == MagickCoreSignature);
2042 *pixel=image->background_color;
2043 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2044 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2045 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2046 if (pixels == (PixelPacket *) NULL)
2047 return(MagickFalse);
2083static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2084 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2087 *magick_restrict cache_info;
2090 id = GetOpenMPThreadId();
2093 *magick_restrict pixels;
2095 assert(image != (
const Image *) NULL);
2096 assert(image->signature == MagickCoreSignature);
2097 assert(image->cache != (Cache) NULL);
2098 cache_info=(CacheInfo *) image->cache;
2099 assert(cache_info->signature == MagickCoreSignature);
2100 *pixel=image->background_color;
2101 assert(
id < (
int) cache_info->number_threads);
2102 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2103 cache_info->nexus_info[
id],exception);
2104 if (pixels == (PixelPacket *) NULL)
2105 return(MagickFalse);
2142MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2143 const ssize_t x,
const ssize_t y,MagickPixelPacket *pixel,
2144 ExceptionInfo *exception)
2147 *magick_restrict cache_info;
2150 id = GetOpenMPThreadId();
2153 *magick_restrict indexes;
2156 *magick_restrict pixels;
2158 assert(image != (
const Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(image->cache != (Cache) NULL);
2161 cache_info=(CacheInfo *) image->cache;
2162 assert(cache_info->signature == MagickCoreSignature);
2163 assert(
id < (
int) cache_info->number_threads);
2164 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2165 1UL,1UL,cache_info->nexus_info[
id],exception);
2166 GetMagickPixelPacket(image,pixel);
2167 if (pixels == (
const PixelPacket *) NULL)
2168 return(MagickFalse);
2169 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2170 SetMagickPixelPacket(image,pixels,indexes,pixel);
2209MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2210 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2211 PixelPacket *pixel,ExceptionInfo *exception)
2214 *magick_restrict cache_info;
2217 id = GetOpenMPThreadId();
2220 *magick_restrict pixels;
2222 assert(image != (
const Image *) NULL);
2223 assert(image->signature == MagickCoreSignature);
2224 assert(image->cache != (Cache) NULL);
2225 cache_info=(CacheInfo *) image->cache;
2226 assert(cache_info->signature == MagickCoreSignature);
2227 *pixel=image->background_color;
2228 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2229 (GetOneVirtualPixelFromHandler) NULL)
2230 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2231 virtual_pixel_method,x,y,pixel,exception));
2232 assert(
id < (
int) cache_info->number_threads);
2233 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2234 cache_info->nexus_info[
id],exception);
2235 if (pixels == (
const PixelPacket *) NULL)
2236 return(MagickFalse);
2272MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2273 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2276 *magick_restrict cache_info;
2279 id = GetOpenMPThreadId();
2282 *magick_restrict pixels;
2284 assert(image != (
const Image *) NULL);
2285 assert(image->signature == MagickCoreSignature);
2286 assert(image->cache != (Cache) NULL);
2287 cache_info=(CacheInfo *) image->cache;
2288 assert(cache_info->signature == MagickCoreSignature);
2289 *pixel=image->background_color;
2290 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2291 (GetOneVirtualPixelFromHandler) NULL)
2292 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2293 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2294 assert(
id < (
int) cache_info->number_threads);
2295 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2296 1UL,1UL,cache_info->nexus_info[
id],exception);
2297 if (pixels == (
const PixelPacket *) NULL)
2298 return(MagickFalse);
2337static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2338 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2339 PixelPacket *pixel,ExceptionInfo *exception)
2342 *magick_restrict cache_info;
2345 id = GetOpenMPThreadId();
2348 *magick_restrict pixels;
2350 assert(image != (
const Image *) NULL);
2351 assert(image->signature == MagickCoreSignature);
2352 assert(image->cache != (Cache) NULL);
2353 cache_info=(CacheInfo *) image->cache;
2354 assert(cache_info->signature == MagickCoreSignature);
2355 assert(
id < (
int) cache_info->number_threads);
2356 *pixel=image->background_color;
2357 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2358 cache_info->nexus_info[
id],exception);
2359 if (pixels == (
const PixelPacket *) NULL)
2360 return(MagickFalse);
2390MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2393 *magick_restrict cache_info;
2395 assert(cache != (Cache) NULL);
2396 cache_info=(CacheInfo *) cache;
2397 assert(cache_info->signature == MagickCoreSignature);
2398 if (IsEventLogging() != MagickFalse)
2399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2400 cache_info->filename);
2401 return(cache_info->channels);
2426MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2429 *magick_restrict cache_info;
2431 assert(cache != (Cache) NULL);
2432 cache_info=(CacheInfo *) cache;
2433 assert(cache_info->signature == MagickCoreSignature);
2434 if (IsEventLogging() != MagickFalse)
2435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2436 cache_info->filename);
2437 return(cache_info->colorspace);
2463MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2466 *magick_restrict cache_info;
2468 assert(image != (
const Image *) NULL);
2469 assert(image->signature == MagickCoreSignature);
2470 assert(image->cache != (Cache) NULL);
2471 cache_info=(CacheInfo *) image->cache;
2472 assert(cache_info->signature == MagickCoreSignature);
2473 return(cache_info->cache_filename);
2498MagickExport
void GetPixelCacheMethods(CacheMethods *cache_methods)
2500 assert(cache_methods != (CacheMethods *) NULL);
2501 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2502 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2503 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2504 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2505 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2506 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2507 cache_methods->get_authentic_indexes_from_handler=
2508 GetAuthenticIndexesFromCache;
2509 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2510 cache_methods->get_one_authentic_pixel_from_handler=
2511 GetOneAuthenticPixelFromCache;
2512 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2513 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2514 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2541MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2542 NexusInfo *nexus_info)
2545 *magick_restrict cache_info;
2550 assert(cache != NULL);
2551 cache_info=(CacheInfo *) cache;
2552 assert(cache_info->signature == MagickCoreSignature);
2553 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2555 return((MagickSizeType) cache_info->columns*cache_info->rows);
2586MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2587 ExceptionInfo *exception)
2590 *magick_restrict cache_info;
2592 assert(image != (
const Image *) NULL);
2593 assert(image->signature == MagickCoreSignature);
2594 assert(image->cache != (Cache) NULL);
2595 assert(length != (MagickSizeType *) NULL);
2596 assert(exception != (ExceptionInfo *) NULL);
2597 assert(exception->signature == MagickCoreSignature);
2598 cache_info=(CacheInfo *) image->cache;
2599 assert(cache_info->signature == MagickCoreSignature);
2601 *length=cache_info->length;
2602 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2603 return((
void *) NULL);
2604 return((
void *) cache_info->pixels);
2631MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2634 *magick_restrict cache_info;
2636 assert(cache != (Cache) NULL);
2637 cache_info=(CacheInfo *) cache;
2638 assert(cache_info->signature == MagickCoreSignature);
2639 if (IsEventLogging() != MagickFalse)
2640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2641 cache_info->filename);
2642 return(cache_info->storage_class);
2672MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2675 assert(image != (Image *) NULL);
2676 assert(image->signature == MagickCoreSignature);
2677 if (IsEventLogging() != MagickFalse)
2678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2679 *width=2048UL/
sizeof(PixelPacket);
2680 if (GetImagePixelCacheType(image) == DiskCache)
2681 *width=8192UL/
sizeof(PixelPacket);
2709MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2712 *magick_restrict cache_info;
2714 assert(image != (Image *) NULL);
2715 assert(image->signature == MagickCoreSignature);
2716 assert(image->cache != (Cache) NULL);
2717 cache_info=(CacheInfo *) image->cache;
2718 assert(cache_info->signature == MagickCoreSignature);
2719 return(cache_info->virtual_pixel_method);
2745static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2748 *magick_restrict cache_info;
2751 id = GetOpenMPThreadId();
2753 assert(image != (
const Image *) NULL);
2754 assert(image->signature == MagickCoreSignature);
2755 assert(image->cache != (Cache) NULL);
2756 cache_info=(CacheInfo *) image->cache;
2757 assert(cache_info->signature == MagickCoreSignature);
2758 assert(
id < (
int) cache_info->number_threads);
2759 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2788MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2789 NexusInfo *nexus_info)
2792 *magick_restrict cache_info;
2794 assert(cache != (Cache) NULL);
2795 cache_info=(CacheInfo *) cache;
2796 assert(cache_info->signature == MagickCoreSignature);
2797 if (cache_info->storage_class == UndefinedClass)
2798 return((IndexPacket *) NULL);
2799 return(nexus_info->indexes);
2827MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2830 *magick_restrict cache_info;
2833 id = GetOpenMPThreadId();
2835 assert(image != (
const Image *) NULL);
2836 assert(image->signature == MagickCoreSignature);
2837 assert(image->cache != (Cache) NULL);
2838 cache_info=(CacheInfo *) image->cache;
2839 assert(cache_info->signature == MagickCoreSignature);
2840 if (cache_info->methods.get_virtual_indexes_from_handler !=
2841 (GetVirtualIndexesFromHandler) NULL)
2846 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2847 if (indexes != (IndexPacket *) NULL)
2850 assert(
id < (
int) cache_info->number_threads);
2851 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2894 0, 48, 12, 60, 3, 51, 15, 63,
2895 32, 16, 44, 28, 35, 19, 47, 31,
2896 8, 56, 4, 52, 11, 59, 7, 55,
2897 40, 24, 36, 20, 43, 27, 39, 23,
2898 2, 50, 14, 62, 1, 49, 13, 61,
2899 34, 18, 46, 30, 33, 17, 45, 29,
2900 10, 58, 6, 54, 9, 57, 5, 53,
2901 42, 26, 38, 22, 41, 25, 37, 21
2904static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2909 index=x+DitherMatrix[x & 0x07]-32L;
2912 if (index >= (ssize_t) columns)
2913 return((ssize_t) columns-1L);
2917static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2922 index=y+DitherMatrix[y & 0x07]-32L;
2925 if (index >= (ssize_t) rows)
2926 return((ssize_t) rows-1L);
2930static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2934 if (x >= (ssize_t) columns)
2935 return((ssize_t) (columns-1));
2939static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2943 if (y >= (ssize_t) rows)
2944 return((ssize_t) (rows-1));
2948static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2951 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2952 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2953 return(MagickFalse);
2957static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2959 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2962static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2964 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2967static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2968 const size_t extent)
2973 modulo.quotient=offset;
2977 modulo.quotient=offset/((ssize_t) extent);
2978 modulo.remainder=offset % ((ssize_t) extent);
2980 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2983 modulo.remainder+=((ssize_t) extent);
2988MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2989 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2990 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2991 ExceptionInfo *exception)
2994 *magick_restrict cache_info;
2997 *magick_restrict virtual_indexes;
3004 *magick_restrict indexes;
3014 *magick_restrict virtual_nexus;
3017 *magick_restrict pixels,
3028 assert(image != (
const Image *) NULL);
3029 assert(image->signature == MagickCoreSignature);
3030 assert(image->cache != (Cache) NULL);
3031 cache_info=(CacheInfo *) image->cache;
3032 assert(cache_info->signature == MagickCoreSignature);
3033 if (cache_info->type == UndefinedCache)
3034 return((
const PixelPacket *) NULL);
3035#if defined(MAGICKCORE_OPENCL_SUPPORT)
3036 CopyOpenCLBuffer(cache_info);
3038 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3039 (image->clip_mask != (Image *) NULL) || (image->mask != (Image *) NULL) ?
3040 MagickTrue : MagickFalse,nexus_info,exception);
3041 if (pixels == (PixelPacket *) NULL)
3042 return((
const PixelPacket *) NULL);
3043 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3044 return((
const PixelPacket *) NULL);
3045 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3046 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3047 return((
const PixelPacket *) NULL);
3048 offset+=nexus_info->region.x;
3049 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3050 nexus_info->region.width-1L;
3051 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3052 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3053 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3054 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3062 if (nexus_info->authentic_pixel_cache != MagickFalse)
3064 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3065 if (status == MagickFalse)
3066 return((
const PixelPacket *) NULL);
3067 if ((cache_info->storage_class == PseudoClass) ||
3068 (cache_info->colorspace == CMYKColorspace))
3070 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3071 if (status == MagickFalse)
3072 return((
const PixelPacket *) NULL);
3079 virtual_nexus=nexus_info->virtual_nexus;
3081 indexes=nexus_info->indexes;
3082 switch (virtual_pixel_method)
3084 case BlackVirtualPixelMethod:
3086 SetPixelRed(&virtual_pixel,0);
3087 SetPixelGreen(&virtual_pixel,0);
3088 SetPixelBlue(&virtual_pixel,0);
3089 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3092 case GrayVirtualPixelMethod:
3094 SetPixelRed(&virtual_pixel,QuantumRange/2);
3095 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3096 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3097 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3100 case TransparentVirtualPixelMethod:
3102 SetPixelRed(&virtual_pixel,0);
3103 SetPixelGreen(&virtual_pixel,0);
3104 SetPixelBlue(&virtual_pixel,0);
3105 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3108 case MaskVirtualPixelMethod:
3109 case WhiteVirtualPixelMethod:
3111 SetPixelRed(&virtual_pixel,QuantumRange);
3112 SetPixelGreen(&virtual_pixel,QuantumRange);
3113 SetPixelBlue(&virtual_pixel,QuantumRange);
3114 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3119 virtual_pixel=image->background_color;
3123 virtual_index=(IndexPacket) 0;
3124 for (v=0; v < (ssize_t) rows; v++)
3130 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3131 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3132 y_offset=EdgeY(y_offset,cache_info->rows);
3133 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3139 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3140 (ssize_t) columns-u);
3141 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3142 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3152 length=(MagickSizeType) 1;
3153 switch (virtual_pixel_method)
3155 case BackgroundVirtualPixelMethod:
3156 case ConstantVirtualPixelMethod:
3157 case BlackVirtualPixelMethod:
3158 case GrayVirtualPixelMethod:
3159 case TransparentVirtualPixelMethod:
3160 case MaskVirtualPixelMethod:
3161 case WhiteVirtualPixelMethod:
3164 virtual_indexes=(&virtual_index);
3167 case EdgeVirtualPixelMethod:
3170 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3171 EdgeX(x_offset,cache_info->columns),
3172 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3174 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3178 case RandomVirtualPixelMethod:
3180 if (cache_info->random_info == (RandomInfo *) NULL)
3181 cache_info->random_info=AcquireRandomInfo();
3182 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3183 RandomX(cache_info->random_info,cache_info->columns),
3184 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3185 virtual_nexus,exception);
3186 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3190 case DitherVirtualPixelMethod:
3192 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3193 DitherX(x_offset,cache_info->columns),
3194 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3196 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3200 case TileVirtualPixelMethod:
3202 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3203 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3204 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3205 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3207 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3211 case MirrorVirtualPixelMethod:
3213 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3214 if ((x_modulo.quotient & 0x01) == 1L)
3215 x_modulo.remainder=(ssize_t) cache_info->columns-
3216 x_modulo.remainder-1L;
3217 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3218 if ((y_modulo.quotient & 0x01) == 1L)
3219 y_modulo.remainder=(ssize_t) cache_info->rows-
3220 y_modulo.remainder-1L;
3221 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3222 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3224 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3228 case CheckerTileVirtualPixelMethod:
3230 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3231 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3232 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3235 virtual_indexes=(&virtual_index);
3238 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3239 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3241 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3245 case HorizontalTileVirtualPixelMethod:
3247 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3250 virtual_indexes=(&virtual_index);
3253 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3254 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3255 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3256 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3258 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3262 case VerticalTileVirtualPixelMethod:
3264 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3267 virtual_indexes=(&virtual_index);
3270 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3271 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3272 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3273 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3275 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3279 case HorizontalTileEdgeVirtualPixelMethod:
3281 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3282 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3283 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3284 virtual_nexus,exception);
3285 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3289 case VerticalTileEdgeVirtualPixelMethod:
3291 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3292 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3293 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3294 virtual_nexus,exception);
3295 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3300 if (p == (
const PixelPacket *) NULL)
3303 if ((indexes != (IndexPacket *) NULL) &&
3304 (virtual_indexes != (
const IndexPacket *) NULL))
3305 *indexes++=(*virtual_indexes);
3311 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3312 (
size_t) length,1UL,virtual_nexus,exception);
3313 if (p == (
const PixelPacket *) NULL)
3315 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3316 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3317 q+=(ptrdiff_t) length;
3318 if ((indexes != (IndexPacket *) NULL) &&
3319 (virtual_indexes != (
const IndexPacket *) NULL))
3321 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3322 sizeof(*virtual_indexes));
3326 if (u < (ssize_t) columns)
3332 if (v < (ssize_t) rows)
3333 return((
const PixelPacket *) NULL);
3371static const PixelPacket *GetVirtualPixelCache(
const Image *image,
3372 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3373 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3376 *magick_restrict cache_info;
3379 id = GetOpenMPThreadId();
3381 assert(image != (
const Image *) NULL);
3382 assert(image->signature == MagickCoreSignature);
3383 assert(image->cache != (Cache) NULL);
3384 cache_info=(CacheInfo *) image->cache;
3385 assert(cache_info->signature == MagickCoreSignature);
3386 assert(
id < (
int) cache_info->number_threads);
3387 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3388 cache_info->nexus_info[
id],exception));
3414MagickExport
const PixelPacket *GetVirtualPixelQueue(
const Image *image)
3417 *magick_restrict cache_info;
3420 id = GetOpenMPThreadId();
3422 assert(image != (
const Image *) NULL);
3423 assert(image->signature == MagickCoreSignature);
3424 assert(image->cache != (Cache) NULL);
3425 cache_info=(CacheInfo *) image->cache;
3426 assert(cache_info->signature == MagickCoreSignature);
3427 if (cache_info->methods.get_virtual_pixels_handler !=
3428 (GetVirtualPixelsHandler) NULL)
3429 return(cache_info->methods.get_virtual_pixels_handler(image));
3430 assert(
id < (
int) cache_info->number_threads);
3431 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3482MagickExport
const PixelPacket *GetVirtualPixels(
const Image *image,
3483 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3484 ExceptionInfo *exception)
3487 *magick_restrict cache_info;
3490 id = GetOpenMPThreadId();
3492 assert(image != (
const Image *) NULL);
3493 assert(image->signature == MagickCoreSignature);
3494 assert(image->cache != (Cache) NULL);
3495 cache_info=(CacheInfo *) image->cache;
3496 assert(cache_info->signature == MagickCoreSignature);
3497 if (cache_info->methods.get_virtual_pixel_handler !=
3498 (GetVirtualPixelHandler) NULL)
3499 return(cache_info->methods.get_virtual_pixel_handler(image,
3500 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3501 assert(
id < (
int) cache_info->number_threads);
3502 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3503 columns,rows,cache_info->nexus_info[
id],exception));
3529static const PixelPacket *GetVirtualPixelsCache(
const Image *image)
3532 *magick_restrict cache_info;
3535 id = GetOpenMPThreadId();
3537 assert(image != (
const Image *) NULL);
3538 assert(image->signature == MagickCoreSignature);
3539 assert(image->cache != (Cache) NULL);
3540 cache_info=(CacheInfo *) image->cache;
3541 assert(cache_info->signature == MagickCoreSignature);
3542 assert(
id < (
int) cache_info->number_threads);
3543 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3572MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3573 NexusInfo *nexus_info)
3576 *magick_restrict cache_info;
3578 assert(cache != (Cache) NULL);
3579 cache_info=(CacheInfo *) cache;
3580 assert(cache_info->signature == MagickCoreSignature);
3581 if (cache_info->storage_class == UndefinedClass)
3582 return((PixelPacket *) NULL);
3583 return((
const PixelPacket *) nexus_info->pixels);
3616static inline void ApplyPixelCompositeMask(
const MagickPixelPacket *p,
3617 const MagickRealType alpha,
const MagickPixelPacket *q,
3618 const MagickRealType beta,MagickPixelPacket *composite)
3623 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3628 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3629 gamma=MagickSafeReciprocal(gamma);
3630 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3631 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3632 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3633 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3634 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3637static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3638 ExceptionInfo *exception)
3641 *magick_restrict cache_info;
3647 *magick_restrict nexus_indexes,
3648 *magick_restrict indexes;
3658 **magick_restrict mask_nexus;
3670 if (IsEventLogging() != MagickFalse)
3671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3672 if ((image->mask == (Image *) NULL) || (image->storage_class == PseudoClass))
3674 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3676 cache_info=(CacheInfo *) image->cache;
3677 if (cache_info == (Cache) NULL)
3678 return(MagickFalse);
3679 mask_nexus=AcquirePixelCacheNexus(1);
3680 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3681 nexus_info->virtual_nexus,exception);
3682 indexes=nexus_info->virtual_nexus->indexes;
3683 q=nexus_info->pixels;
3684 nexus_indexes=nexus_info->indexes;
3685 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3686 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3687 nexus_info->region.height,mask_nexus[0],&image->exception);
3688 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL) ||
3689 (r == (
const PixelPacket *) NULL))
3690 return(MagickFalse);
3692 GetMagickPixelPacket(image,&alpha);
3693 GetMagickPixelPacket(image,&beta);
3694 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3699 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3701 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3702 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3703 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3704 alpha.opacity,&beta);
3705 SetPixelRed(q,ClampToQuantum(beta.red));
3706 SetPixelGreen(q,ClampToQuantum(beta.green));
3707 SetPixelBlue(q,ClampToQuantum(beta.blue));
3708 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3709 if (cache_info->active_index_channel != MagickFalse)
3710 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3717 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3752static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3753 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3758 if ((count == 0) || (quantum == 0))
3760 length=count*quantum;
3761 if (quantum != (length/count))
3768 return(MagickFalse);
3771static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3780 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3782 if (*cache_info->cache_filename ==
'\0')
3783 file=AcquireUniqueFileResource(cache_info->cache_filename);
3789 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3794 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3795 O_BINARY | O_EXCL,S_MODE);
3797 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3803 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3806 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3811 return(MagickFalse);
3812 (void) AcquireMagickResource(FileResource,1);
3813 if (cache_info->file != -1)
3814 (void) ClosePixelCacheOnDisk(cache_info);
3815 cache_info->file=file;
3816 cache_info->disk_mode=mode;
3820static inline MagickOffsetType WritePixelCacheRegion(
3821 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3822 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3830#if !defined(MAGICKCORE_HAVE_PWRITE)
3831 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3832 return((MagickOffsetType) -1);
3834 for (i=0; i < (MagickOffsetType) length; i+=count)
3836#if !defined(MAGICKCORE_HAVE_PWRITE)
3837 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3838 (MagickSizeType) i,MagickMaxBufferExtent));
3840 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3841 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3853static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3856 *magick_restrict cache_info;
3861 cache_info=(CacheInfo *) image->cache;
3862 if (cache_info->debug != MagickFalse)
3865 format[MaxTextExtent],
3866 message[MaxTextExtent];
3868 (void) FormatMagickSize(length,MagickFalse,format);
3869 (void) FormatLocaleString(message,MaxTextExtent,
3870 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3871 cache_info->cache_filename,cache_info->file,format);
3872 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3874 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3876 return(MagickFalse);
3877 if ((MagickSizeType) offset < length)
3883 extent=(MagickOffsetType) length-1;
3884 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3887 return(MagickFalse);
3888#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3889 if (cache_info->synchronize != MagickFalse)
3890 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3891 return(MagickFalse);
3894 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3896 return(MagickFalse);
3900static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3901 ExceptionInfo *exception)
3904 *magick_restrict cache_info,
3908 format[MaxTextExtent],
3909 message[MaxTextExtent];
3926 assert(image != (
const Image *) NULL);
3927 assert(image->signature == MagickCoreSignature);
3928 assert(image->cache != (Cache) NULL);
3929 if (IsEventLogging() != MagickFalse)
3930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3931 if (cache_anonymous_memory < 0)
3939 cache_anonymous_memory=0;
3940 value=GetPolicyValue(
"pixel-cache-memory");
3941 if (value == (
char *) NULL)
3942 value=GetPolicyValue(
"cache:memory-map");
3943 if (LocaleCompare(value,
"anonymous") == 0)
3945#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3946 cache_anonymous_memory=1;
3948 (void) ThrowMagickException(exception,GetMagickModule(),
3949 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3950 "'%s' (policy requires anonymous memory mapping)",image->filename);
3953 value=DestroyString(value);
3955 if ((image->columns == 0) || (image->rows == 0))
3956 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3957 cache_info=(CacheInfo *) image->cache;
3958 assert(cache_info->signature == MagickCoreSignature);
3959 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3960 ((MagickSizeType) image->rows > cache_info->height_limit))
3961 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3963 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3965 length=GetImageListLength(image);
3966 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3967 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3970 source_info=(*cache_info);
3971 source_info.file=(-1);
3972 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3973 image->filename,(
double) image->scene);
3974 cache_info->storage_class=image->storage_class;
3975 cache_info->colorspace=image->colorspace;
3976 cache_info->rows=image->rows;
3977 cache_info->columns=image->columns;
3978 cache_info->channels=image->channels;
3979 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3980 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3981 cache_info->mode=mode;
3982 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3983 packet_size=
sizeof(PixelPacket);
3984 if (cache_info->active_index_channel != MagickFalse)
3985 packet_size+=
sizeof(IndexPacket);
3986 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3988 cache_info->storage_class=UndefinedClass;
3989 cache_info->length=0;
3990 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3993 columns=(size_t) (length/cache_info->rows/packet_size);
3994 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3995 ((ssize_t) cache_info->rows < 0))
3997 cache_info->storage_class=UndefinedClass;
3998 cache_info->length=0;
3999 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
4002 cache_info->length=length;
4003 if (image->ping != MagickFalse)
4005 cache_info->type=PingCache;
4008 status=AcquireMagickResource(AreaResource,(MagickSizeType)
4009 cache_info->columns*cache_info->rows);
4010 if (cache_info->mode == PersistMode)
4012 length=number_pixels*(
sizeof(PixelPacket)+
sizeof(IndexPacket));
4013 if ((status != MagickFalse) &&
4014 (length == (MagickSizeType) ((
size_t) length)) &&
4015 ((cache_info->type == UndefinedCache) ||
4016 (cache_info->type == MemoryCache)))
4018 status=AcquireMagickResource(MemoryResource,cache_info->length);
4019 if (status != MagickFalse)
4022 if (cache_anonymous_memory <= 0)
4024 cache_info->mapped=MagickFalse;
4025 cache_info->pixels=(PixelPacket *) MagickAssumeAligned(
4026 AcquireAlignedMemory(1,(
size_t) cache_info->length));
4030 cache_info->mapped=MagickTrue;
4031 cache_info->pixels=(PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
4032 cache_info->length);
4034 if (cache_info->pixels == (PixelPacket *) NULL)
4036 cache_info->mapped=source_info.mapped;
4037 cache_info->pixels=source_info.pixels;
4044 cache_info->colorspace=image->colorspace;
4045 cache_info->type=MemoryCache;
4046 cache_info->indexes=(IndexPacket *) NULL;
4047 if (cache_info->active_index_channel != MagickFalse)
4048 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4050 if ((source_info.storage_class != UndefinedClass) &&
4053 status&=ClonePixelCacheRepository(cache_info,&source_info,
4055 RelinquishPixelCachePixels(&source_info);
4057 if (cache_info->debug != MagickFalse)
4059 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4060 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4062 (void) FormatLocaleString(message,MaxTextExtent,
4063 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4064 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4065 type,(
double) cache_info->columns,(
double) cache_info->rows,
4067 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4070 cache_info->storage_class=image->storage_class;
4073 if ((source_info.storage_class != UndefinedClass) &&
4075 RelinquishPixelCachePixels(&source_info);
4076 cache_info->type=UndefinedCache;
4077 return(MagickFalse);
4083 status=AcquireMagickResource(DiskResource,cache_info->length);
4084 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4086 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4094 server_info=AcquireDistributeCacheInfo(exception);
4095 if (server_info != (DistributeCacheInfo *) NULL)
4097 status=OpenDistributePixelCache(server_info,image);
4098 if (status == MagickFalse)
4100 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4101 GetDistributeCacheHostname(server_info));
4102 server_info=DestroyDistributeCacheInfo(server_info);
4110 cache_info->type=DistributedCache;
4111 cache_info->storage_class=image->storage_class;
4112 cache_info->colorspace=image->colorspace;
4113 cache_info->server_info=server_info;
4114 (void) FormatLocaleString(cache_info->cache_filename,
4115 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4116 (DistributeCacheInfo *) cache_info->server_info),
4117 GetDistributeCachePort((DistributeCacheInfo *)
4118 cache_info->server_info));
4119 if ((source_info.storage_class != UndefinedClass) &&
4122 status=ClonePixelCacheRepository(cache_info,&source_info,
4124 RelinquishPixelCachePixels(&source_info);
4126 if (cache_info->debug != MagickFalse)
4128 (void) FormatMagickSize(cache_info->length,MagickFalse,
4130 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4132 (void) FormatLocaleString(message,MaxTextExtent,
4133 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4134 cache_info->cache_filename,GetDistributeCacheFile(
4135 (DistributeCacheInfo *) cache_info->server_info),type,
4136 (
double) cache_info->columns,(
double) cache_info->rows,
4138 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4143 if ((source_info.storage_class != UndefinedClass) &&
4145 RelinquishPixelCachePixels(&source_info);
4146 cache_info->type=UndefinedCache;
4147 return(MagickFalse);
4152 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4153 RelinquishPixelCachePixels(&source_info);
4154 cache_info->type=UndefinedCache;
4155 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4156 "CacheResourcesExhausted",
"`%s'",image->filename);
4157 return(MagickFalse);
4162 if (status == MagickFalse)
4164 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4165 RelinquishPixelCachePixels(&source_info);
4166 cache_info->type=UndefinedCache;
4167 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4168 "CacheResourcesExhausted",
"`%s'",image->filename);
4169 return(MagickFalse);
4171 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4172 (cache_info->mode != PersistMode))
4174 (void) ClosePixelCacheOnDisk(cache_info);
4175 *cache_info->cache_filename=
'\0';
4177 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4179 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4180 RelinquishPixelCachePixels(&source_info);
4181 cache_info->type=UndefinedCache;
4182 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4184 return(MagickFalse);
4186 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4187 cache_info->length);
4188 if (status == MagickFalse)
4190 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4191 RelinquishPixelCachePixels(&source_info);
4192 cache_info->type=UndefinedCache;
4193 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4195 return(MagickFalse);
4197 cache_info->storage_class=image->storage_class;
4198 cache_info->colorspace=image->colorspace;
4199 cache_info->type=DiskCache;
4200 length=number_pixels*(
sizeof(PixelPacket)+
sizeof(IndexPacket));
4201 if (length == (MagickSizeType) ((
size_t) length))
4203 status=AcquireMagickResource(MapResource,cache_info->length);
4204 if (status != MagickFalse)
4206 cache_info->pixels=(PixelPacket *) MapBlob(cache_info->file,mode,
4207 cache_info->offset,(
size_t) cache_info->length);
4208 if (cache_info->pixels == (PixelPacket *) NULL)
4210 cache_info->mapped=source_info.mapped;
4211 cache_info->pixels=source_info.pixels;
4212 RelinquishMagickResource(MapResource,cache_info->length);
4219 (void) ClosePixelCacheOnDisk(cache_info);
4220 cache_info->type=MapCache;
4221 cache_info->mapped=MagickTrue;
4222 cache_info->indexes=(IndexPacket *) NULL;
4223 if (cache_info->active_index_channel != MagickFalse)
4224 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4226 if ((source_info.storage_class != UndefinedClass) &&
4229 status=ClonePixelCacheRepository(cache_info,&source_info,
4231 RelinquishPixelCachePixels(&source_info);
4233 if (cache_info->debug != MagickFalse)
4235 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4236 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4238 (void) FormatLocaleString(message,MaxTextExtent,
4239 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4240 cache_info->filename,cache_info->cache_filename,
4241 cache_info->file,type,(
double) cache_info->columns,
4242 (
double) cache_info->rows,format);
4243 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4248 if ((source_info.storage_class != UndefinedClass) &&
4250 RelinquishPixelCachePixels(&source_info);
4251 cache_info->type=UndefinedCache;
4252 return(MagickFalse);
4259 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4261 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4262 RelinquishPixelCachePixels(&source_info);
4264 if (cache_info->debug != MagickFalse)
4266 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4267 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4269 (void) FormatLocaleString(message,MaxTextExtent,
4270 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4271 cache_info->cache_filename,cache_info->file,type,(
double)
4272 cache_info->columns,(
double) cache_info->rows,format);
4273 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4277 cache_info->type=UndefinedCache;
4278 return(MagickFalse);
4320MagickExport MagickBooleanType PersistPixelCache(Image *image,
4321 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4322 ExceptionInfo *exception)
4325 *magick_restrict cache_info,
4326 *magick_restrict clone_info;
4334 assert(image != (Image *) NULL);
4335 assert(image->signature == MagickCoreSignature);
4336 if (IsEventLogging() != MagickFalse)
4337 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4338 assert(image->cache != (
void *) NULL);
4339 assert(filename != (
const char *) NULL);
4340 assert(offset != (MagickOffsetType *) NULL);
4341 page_size=GetMagickPageSize();
4342 cache_info=(CacheInfo *) image->cache;
4343 assert(cache_info->signature == MagickCoreSignature);
4344#if defined(MAGICKCORE_OPENCL_SUPPORT)
4345 CopyOpenCLBuffer(cache_info);
4347 if (attach != MagickFalse)
4352 if (cache_info->debug != MagickFalse)
4353 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4354 "attach persistent cache");
4355 (void) CopyMagickString(cache_info->cache_filename,filename,
4357 cache_info->type=MapCache;
4358 cache_info->offset=(*offset);
4359 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4360 return(MagickFalse);
4361 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4362 ((MagickOffsetType) cache_info->length % page_size));
4368 status=AcquireMagickResource(DiskResource,cache_info->length);
4369 if (status == MagickFalse)
4371 cache_info->type=UndefinedCache;
4372 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4373 "CacheResourcesExhausted",
"`%s'",image->filename);
4374 return(MagickFalse);
4376 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4377 clone_info->type=DiskCache;
4378 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4379 clone_info->file=(-1);
4380 clone_info->storage_class=cache_info->storage_class;
4381 clone_info->colorspace=cache_info->colorspace;
4382 clone_info->columns=cache_info->columns;
4383 clone_info->rows=cache_info->rows;
4384 clone_info->active_index_channel=cache_info->active_index_channel;
4385 clone_info->mode=PersistMode;
4386 clone_info->length=cache_info->length;
4387 clone_info->channels=cache_info->channels;
4388 clone_info->offset=(*offset);
4389 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4390 if (status != MagickFalse)
4391 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4392 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4393 ((MagickOffsetType) cache_info->length % page_size));
4394 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4436MagickExport PixelPacket *QueueAuthenticPixel(Image *image,
const ssize_t x,
4437 const ssize_t y,
const size_t columns,
const size_t rows,
4438 const MagickBooleanType clone,NexusInfo *nexus_info,
4439 ExceptionInfo *exception)
4441 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4445MagickExport PixelPacket *QueueAuthenticPixelCacheNexus(Image *image,
4446 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4447 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4450 *magick_restrict cache_info;
4459 *magick_restrict pixels;
4464 assert(image != (
const Image *) NULL);
4465 assert(image->signature == MagickCoreSignature);
4466 assert(image->cache != (Cache) NULL);
4467 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4468 if (cache_info == (Cache) NULL)
4469 return((PixelPacket *) NULL);
4470 assert(cache_info->signature == MagickCoreSignature);
4471 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4472 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4473 (y >= (ssize_t) cache_info->rows))
4475 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4476 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4477 return((PixelPacket *) NULL);
4479 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4480 return((PixelPacket *) NULL);
4481 offset=y*(MagickOffsetType) cache_info->columns+x;
4483 return((PixelPacket *) NULL);
4484 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4485 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4486 (MagickOffsetType) columns-1;
4487 if ((MagickSizeType) offset >= number_pixels)
4488 return((PixelPacket *) NULL);
4492 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4493 (image->clip_mask != (Image *) NULL) || (image->mask != (Image *) NULL) ?
4494 MagickTrue : MagickFalse,nexus_info,exception);
4531static PixelPacket *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4532 const ssize_t y,
const size_t columns,
const size_t rows,
4533 ExceptionInfo *exception)
4536 *magick_restrict cache_info;
4539 id = GetOpenMPThreadId();
4541 assert(image != (
const Image *) NULL);
4542 assert(image->signature == MagickCoreSignature);
4543 assert(image->cache != (Cache) NULL);
4544 cache_info=(CacheInfo *) image->cache;
4545 assert(cache_info->signature == MagickCoreSignature);
4546 assert(
id < (
int) cache_info->number_threads);
4547 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4548 cache_info->nexus_info[
id],exception));
4607MagickExport PixelPacket *QueueAuthenticPixels(Image *image,
const ssize_t x,
4608 const ssize_t y,
const size_t columns,
const size_t rows,
4609 ExceptionInfo *exception)
4612 *magick_restrict cache_info;
4615 id = GetOpenMPThreadId();
4617 assert(image != (Image *) NULL);
4618 assert(image->signature == MagickCoreSignature);
4619 assert(image->cache != (Cache) NULL);
4620 cache_info=(CacheInfo *) image->cache;
4621 assert(cache_info->signature == MagickCoreSignature);
4622 if (cache_info->methods.queue_authentic_pixels_handler !=
4623 (QueueAuthenticPixelsHandler) NULL)
4624 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4626 assert(
id < (
int) cache_info->number_threads);
4627 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4628 cache_info->nexus_info[
id],exception));
4660static inline MagickOffsetType ReadPixelCacheRegion(
4661 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4662 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4670#if !defined(MAGICKCORE_HAVE_PREAD)
4671 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4672 return((MagickOffsetType) -1);
4674 for (i=0; i < (MagickOffsetType) length; i+=count)
4676#if !defined(MAGICKCORE_HAVE_PREAD)
4677 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4678 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4680 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4681 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4693static MagickBooleanType ReadPixelCacheIndexes(
4694 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4695 ExceptionInfo *exception)
4714 if (cache_info->active_index_channel == MagickFalse)
4715 return(MagickFalse);
4716 if (nexus_info->authentic_pixel_cache != MagickFalse)
4718 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4719 return(MagickFalse);
4720 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4721 nexus_info->region.x;
4722 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4723 rows=nexus_info->region.height;
4725 q=nexus_info->indexes;
4727 switch (cache_info->type)
4738 if ((cache_info->columns == nexus_info->region.width) &&
4739 (extent == (MagickSizeType) ((
size_t) extent)))
4744 p=cache_info->indexes+offset;
4745 for (y=0; y < (ssize_t) rows; y++)
4747 (void) memcpy(q,p,(
size_t) length);
4748 p+=(ptrdiff_t) cache_info->columns;
4749 q+=(ptrdiff_t) nexus_info->region.width;
4758 LockSemaphoreInfo(cache_info->file_semaphore);
4759 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4761 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4762 cache_info->cache_filename);
4763 UnlockSemaphoreInfo(cache_info->file_semaphore);
4764 return(MagickFalse);
4766 if ((cache_info->columns == nexus_info->region.width) &&
4767 (extent <= MagickMaxBufferExtent))
4772 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4773 for (y=0; y < (ssize_t) rows; y++)
4775 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4776 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(PixelPacket)+
4777 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4778 if (count < (MagickOffsetType) length)
4780 offset+=(MagickOffsetType) cache_info->columns;
4781 q+=(ptrdiff_t) nexus_info->region.width;
4783 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4784 (void) ClosePixelCacheOnDisk(cache_info);
4785 UnlockSemaphoreInfo(cache_info->file_semaphore);
4788 case DistributedCache:
4796 LockSemaphoreInfo(cache_info->file_semaphore);
4797 region=nexus_info->region;
4798 if ((cache_info->columns != nexus_info->region.width) ||
4799 (extent > MagickMaxBufferExtent))
4806 for (y=0; y < (ssize_t) rows; y++)
4808 count=ReadDistributePixelCacheIndexes((DistributeCacheInfo *)
4809 cache_info->server_info,®ion,length,(
unsigned char *) q);
4810 if (count != (MagickOffsetType) length)
4812 q+=(ptrdiff_t) nexus_info->region.width;
4815 UnlockSemaphoreInfo(cache_info->file_semaphore);
4821 if (y < (ssize_t) rows)
4823 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4824 cache_info->cache_filename);
4825 return(MagickFalse);
4827 if ((cache_info->debug != MagickFalse) &&
4828 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4829 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4830 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4831 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4832 nexus_info->region.x,(
double) nexus_info->region.y);
4864static MagickBooleanType ReadPixelCachePixels(
4865 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4866 ExceptionInfo *exception)
4885 if (nexus_info->authentic_pixel_cache != MagickFalse)
4887 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4888 return(MagickFalse);
4889 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4890 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4891 return(MagickFalse);
4892 offset+=nexus_info->region.x;
4893 length=(MagickSizeType) nexus_info->region.width*
sizeof(PixelPacket);
4894 if ((length/
sizeof(PixelPacket)) != nexus_info->region.width)
4895 return(MagickFalse);
4896 rows=nexus_info->region.height;
4898 if ((extent == 0) || ((extent/length) != rows))
4899 return(MagickFalse);
4900 q=nexus_info->pixels;
4902 switch (cache_info->type)
4913 if ((cache_info->columns == nexus_info->region.width) &&
4914 (extent == (MagickSizeType) ((
size_t) extent)))
4919 p=cache_info->pixels+offset;
4920 for (y=0; y < (ssize_t) rows; y++)
4922 (void) memcpy(q,p,(
size_t) length);
4923 p+=(ptrdiff_t) cache_info->columns;
4924 q+=(ptrdiff_t) nexus_info->region.width;
4933 LockSemaphoreInfo(cache_info->file_semaphore);
4934 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4936 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4937 cache_info->cache_filename);
4938 UnlockSemaphoreInfo(cache_info->file_semaphore);
4939 return(MagickFalse);
4941 if ((cache_info->columns == nexus_info->region.width) &&
4942 (extent <= MagickMaxBufferExtent))
4947 for (y=0; y < (ssize_t) rows; y++)
4949 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4950 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4951 if (count < (MagickOffsetType) length)
4953 offset+=(MagickOffsetType) cache_info->columns;
4954 q+=(ptrdiff_t) nexus_info->region.width;
4956 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4957 (void) ClosePixelCacheOnDisk(cache_info);
4958 UnlockSemaphoreInfo(cache_info->file_semaphore);
4961 case DistributedCache:
4969 LockSemaphoreInfo(cache_info->file_semaphore);
4970 region=nexus_info->region;
4971 if ((cache_info->columns != nexus_info->region.width) ||
4972 (extent > MagickMaxBufferExtent))
4979 for (y=0; y < (ssize_t) rows; y++)
4981 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4982 cache_info->server_info,®ion,length,(
unsigned char *) q);
4983 if (count != (MagickOffsetType) length)
4985 q+=(ptrdiff_t) nexus_info->region.width;
4988 UnlockSemaphoreInfo(cache_info->file_semaphore);
4994 if (y < (ssize_t) rows)
4996 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4997 cache_info->cache_filename);
4998 return(MagickFalse);
5000 if ((cache_info->debug != MagickFalse) &&
5001 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5002 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5003 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5004 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5005 nexus_info->region.x,(
double) nexus_info->region.y);
5032MagickExport Cache ReferencePixelCache(Cache cache)
5035 *magick_restrict cache_info;
5037 assert(cache != (Cache *) NULL);
5038 cache_info=(CacheInfo *) cache;
5039 assert(cache_info->signature == MagickCoreSignature);
5040 LockSemaphoreInfo(cache_info->semaphore);
5041 cache_info->reference_count++;
5042 UnlockSemaphoreInfo(cache_info->semaphore);
5064MagickPrivate
void ResetCacheAnonymousMemory(
void)
5066 cache_anonymous_memory=0;
5093MagickExport
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5096 *magick_restrict cache_info;
5098 GetOneAuthenticPixelFromHandler
5099 get_one_authentic_pixel_from_handler;
5101 GetOneVirtualPixelFromHandler
5102 get_one_virtual_pixel_from_handler;
5107 assert(cache != (Cache) NULL);
5108 assert(cache_methods != (CacheMethods *) NULL);
5109 cache_info=(CacheInfo *) cache;
5110 assert(cache_info->signature == MagickCoreSignature);
5111 if (IsEventLogging() != MagickFalse)
5112 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5113 cache_info->filename);
5114 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5115 cache_info->methods.get_virtual_pixel_handler=
5116 cache_methods->get_virtual_pixel_handler;
5117 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5118 cache_info->methods.destroy_pixel_handler=
5119 cache_methods->destroy_pixel_handler;
5120 if (cache_methods->get_virtual_indexes_from_handler !=
5121 (GetVirtualIndexesFromHandler) NULL)
5122 cache_info->methods.get_virtual_indexes_from_handler=
5123 cache_methods->get_virtual_indexes_from_handler;
5124 if (cache_methods->get_authentic_pixels_handler !=
5125 (GetAuthenticPixelsHandler) NULL)
5126 cache_info->methods.get_authentic_pixels_handler=
5127 cache_methods->get_authentic_pixels_handler;
5128 if (cache_methods->queue_authentic_pixels_handler !=
5129 (QueueAuthenticPixelsHandler) NULL)
5130 cache_info->methods.queue_authentic_pixels_handler=
5131 cache_methods->queue_authentic_pixels_handler;
5132 if (cache_methods->sync_authentic_pixels_handler !=
5133 (SyncAuthenticPixelsHandler) NULL)
5134 cache_info->methods.sync_authentic_pixels_handler=
5135 cache_methods->sync_authentic_pixels_handler;
5136 if (cache_methods->get_authentic_pixels_from_handler !=
5137 (GetAuthenticPixelsFromHandler) NULL)
5138 cache_info->methods.get_authentic_pixels_from_handler=
5139 cache_methods->get_authentic_pixels_from_handler;
5140 if (cache_methods->get_authentic_indexes_from_handler !=
5141 (GetAuthenticIndexesFromHandler) NULL)
5142 cache_info->methods.get_authentic_indexes_from_handler=
5143 cache_methods->get_authentic_indexes_from_handler;
5144 get_one_virtual_pixel_from_handler=
5145 cache_info->methods.get_one_virtual_pixel_from_handler;
5146 if (get_one_virtual_pixel_from_handler !=
5147 (GetOneVirtualPixelFromHandler) NULL)
5148 cache_info->methods.get_one_virtual_pixel_from_handler=
5149 cache_methods->get_one_virtual_pixel_from_handler;
5150 get_one_authentic_pixel_from_handler=
5151 cache_methods->get_one_authentic_pixel_from_handler;
5152 if (get_one_authentic_pixel_from_handler !=
5153 (GetOneAuthenticPixelFromHandler) NULL)
5154 cache_info->methods.get_one_authentic_pixel_from_handler=
5155 cache_methods->get_one_authentic_pixel_from_handler;
5196static inline MagickBooleanType AcquireCacheNexusPixels(
5197 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5198 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5200 if (length != (MagickSizeType) ((
size_t) length))
5202 (void) ThrowMagickException(exception,GetMagickModule(),
5203 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5204 cache_info->filename);
5205 return(MagickFalse);
5207 nexus_info->length=0;
5208 nexus_info->mapped=MagickFalse;
5209 if (cache_anonymous_memory <= 0)
5211 nexus_info->cache=(PixelPacket *) MagickAssumeAligned(
5212 AcquireAlignedMemory(1,(
size_t) length));
5213 if (nexus_info->cache != (PixelPacket *) NULL)
5214 (void) memset(nexus_info->cache,0,(
size_t) length);
5218 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5219 if (nexus_info->cache != (PixelPacket *) NULL)
5220 nexus_info->mapped=MagickTrue;
5222 if (nexus_info->cache == (PixelPacket *) NULL)
5224 (void) ThrowMagickException(exception,GetMagickModule(),
5225 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5226 cache_info->filename);
5227 return(MagickFalse);
5229 nexus_info->length=length;
5233static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5236 if (nexus_info->length < CACHE_LINE_SIZE)
5238 if (mode == ReadMode)
5240 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5244 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5247static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5250 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5251 return(MagickFalse);
5252 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5253 return(MagickFalse);
5257static PixelPacket *SetPixelCacheNexusPixels(
5258 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5259 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5260 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5261 ExceptionInfo *exception)
5270 assert(cache_info != (
const CacheInfo *) NULL);
5271 assert(cache_info->signature == MagickCoreSignature);
5272 if (cache_info->type == UndefinedCache)
5273 return((PixelPacket *) NULL);
5274 assert(nexus_info->signature == MagickCoreSignature);
5275 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5276 if ((width == 0) || (height == 0))
5278 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5279 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5280 return((PixelPacket *) NULL);
5282 if (((MagickSizeType) width > cache_info->width_limit) ||
5283 ((MagickSizeType) height > cache_info->height_limit))
5285 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5286 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5287 return((PixelPacket *) NULL);
5289 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5290 (ValidatePixelOffset(y,height) == MagickFalse))
5292 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5293 "InvalidPixel",
"`%s'",cache_info->filename);
5294 return((PixelPacket *) NULL);
5296 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5297 (buffered == MagickFalse))
5299 if (((x >= 0) && (y >= 0) &&
5300 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5301 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5302 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5310 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5311 return((PixelPacket *) NULL);
5312 offset=y*(MagickOffsetType) cache_info->columns+x;
5313 nexus_info->pixels=cache_info->pixels+offset;
5314 nexus_info->indexes=(IndexPacket *) NULL;
5315 if (cache_info->active_index_channel != MagickFalse)
5316 nexus_info->indexes=cache_info->indexes+offset;
5317 nexus_info->region.width=width;
5318 nexus_info->region.height=height;
5319 nexus_info->region.x=x;
5320 nexus_info->region.y=y;
5321 nexus_info->authentic_pixel_cache=MagickTrue;
5322 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5323 return(nexus_info->pixels);
5329 number_pixels=(MagickSizeType) width*height;
5330 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5331 cache_info->rows))*
sizeof(PixelPacket);
5332 if (cache_info->active_index_channel != MagickFalse)
5333 length+=number_pixels*
sizeof(IndexPacket);
5335 if (nexus_info->cache == (PixelPacket *) NULL)
5336 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5338 if (nexus_info->length < length)
5340 RelinquishCacheNexusPixels(nexus_info);
5341 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5343 if (status == MagickFalse)
5345 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5346 return((PixelPacket *) NULL);
5348 nexus_info->pixels=nexus_info->cache;
5349 nexus_info->indexes=(IndexPacket *) NULL;
5350 if (cache_info->active_index_channel != MagickFalse)
5351 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5352 nexus_info->region.width=width;
5353 nexus_info->region.height=height;
5354 nexus_info->region.x=x;
5355 nexus_info->region.y=y;
5356 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5357 MagickTrue : MagickFalse;
5358 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5359 return(nexus_info->pixels);
5390static MagickBooleanType SetCacheAlphaChannel(Image *image,
5391 const Quantum opacity)
5394 *magick_restrict image_view;
5402 assert(image != (Image *) NULL);
5403 assert(image->signature == MagickCoreSignature);
5404 if (IsEventLogging() != MagickFalse)
5405 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5406 assert(image->cache != (Cache) NULL);
5407 image->matte=MagickTrue;
5409 image_view=AcquireVirtualCacheView(image,&image->exception);
5410#if defined(MAGICKCORE_OPENMP_SUPPORT)
5411 #pragma omp parallel for schedule(static) shared(status) \
5412 magick_number_threads(image,image,image->rows,2)
5414 for (y=0; y < (ssize_t) image->rows; y++)
5422 if (status == MagickFalse)
5424 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5426 if (q == (PixelPacket *) NULL)
5431 for (x=0; x < (ssize_t) image->columns; x++)
5436 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5438 image_view=DestroyCacheView(image_view);
5442MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5443 const VirtualPixelMethod virtual_pixel_method)
5446 *magick_restrict cache_info;
5451 assert(image != (Image *) NULL);
5452 assert(image->signature == MagickCoreSignature);
5453 if (IsEventLogging() != MagickFalse)
5454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5455 assert(image->cache != (Cache) NULL);
5456 cache_info=(CacheInfo *) image->cache;
5457 assert(cache_info->signature == MagickCoreSignature);
5458 method=cache_info->virtual_pixel_method;
5459 cache_info->virtual_pixel_method=virtual_pixel_method;
5460 if ((image->columns != 0) && (image->rows != 0))
5461 switch (virtual_pixel_method)
5463 case BackgroundVirtualPixelMethod:
5465 if ((image->background_color.opacity != OpaqueOpacity) &&
5466 (image->matte == MagickFalse))
5467 (void) SetCacheAlphaChannel((Image *) image,OpaqueOpacity);
5468 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5469 (IsGrayColorspace(image->colorspace) != MagickFalse))
5470 (void) SetImageColorspace((Image *) image,sRGBColorspace);
5473 case TransparentVirtualPixelMethod:
5475 if (image->matte == MagickFalse)
5476 (void) SetCacheAlphaChannel((Image *) image,OpaqueOpacity);
5485#if defined(MAGICKCORE_OPENCL_SUPPORT)
5509static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5514 assert(cache_info != (CacheInfo *)NULL);
5515 if ((cache_info->type != MemoryCache) ||
5516 (cache_info->opencl == (OpenCLCacheInfo *)NULL))
5521 LockSemaphoreInfo(cache_info->semaphore);
5522 if (cache_info->opencl != (OpenCLCacheInfo *)NULL)
5530 clEnv=GetDefaultOpenCLEnv();
5531 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5532 if (events != (cl_event *) NULL)
5546 context=GetOpenCLContext(clEnv);
5547 queue=AcquireOpenCLCommandQueue(clEnv);
5548 pixels=(PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5549 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5550 cache_info->length,event_count,events,NULL,&status);
5551 assert(pixels == cache_info->pixels);
5552 events=(cl_event *) RelinquishMagickMemory(events);
5553 RelinquishOpenCLCommandQueue(clEnv,queue);
5555 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5557 UnlockSemaphoreInfo(cache_info->semaphore);
5560MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5563 *magick_restrict cache_info;
5565 assert(image != (Image *)NULL);
5566 cache_info = (CacheInfo *)image->cache;
5567 CopyOpenCLBuffer(cache_info);
5600MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5601 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5604 *magick_restrict cache_info;
5612 assert(image != (Image *) NULL);
5613 assert(image->signature == MagickCoreSignature);
5614 if (image->cache == (Cache) NULL)
5615 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5616 cache_info=(CacheInfo *) image->cache;
5617 assert(cache_info->signature == MagickCoreSignature);
5618 if (cache_info->type == UndefinedCache)
5619 return(MagickFalse);
5620 if ((image->storage_class == DirectClass) &&
5621 (image->clip_mask != (Image *) NULL) &&
5622 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5623 return(MagickFalse);
5624 if ((image->storage_class == DirectClass) &&
5625 (image->mask != (Image *) NULL) &&
5626 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5627 return(MagickFalse);
5628 if (nexus_info->authentic_pixel_cache != MagickFalse)
5630 if (image->taint == MagickFalse)
5631 image->taint=MagickTrue;
5634 assert(cache_info->signature == MagickCoreSignature);
5635 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5636 if ((cache_info->active_index_channel != MagickFalse) &&
5637 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5638 return(MagickFalse);
5639 if ((status != MagickFalse) && (image->taint == MagickFalse))
5640 image->taint=MagickTrue;
5671static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5672 ExceptionInfo *exception)
5675 *magick_restrict cache_info;
5678 id = GetOpenMPThreadId();
5683 assert(image != (Image *) NULL);
5684 assert(image->signature == MagickCoreSignature);
5685 assert(image->cache != (Cache) NULL);
5686 cache_info=(CacheInfo *) image->cache;
5687 assert(cache_info->signature == MagickCoreSignature);
5688 assert(
id < (
int) cache_info->number_threads);
5689 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5721MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5722 ExceptionInfo *exception)
5725 *magick_restrict cache_info;
5728 id = GetOpenMPThreadId();
5733 assert(image != (Image *) NULL);
5734 assert(image->signature == MagickCoreSignature);
5735 assert(image->cache != (Cache) NULL);
5736 cache_info=(CacheInfo *) image->cache;
5737 assert(cache_info->signature == MagickCoreSignature);
5738 if (cache_info->methods.sync_authentic_pixels_handler !=
5739 (SyncAuthenticPixelsHandler) NULL)
5740 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5741 assert(
id < (
int) cache_info->number_threads);
5742 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5774MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5775 ExceptionInfo *exception)
5778 *magick_restrict cache_info;
5780 assert(image != (Image *) NULL);
5781 assert(exception != (ExceptionInfo *) NULL);
5782 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5783 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5814static MagickBooleanType WritePixelCacheIndexes(CacheInfo *cache_info,
5815 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5834 if (cache_info->active_index_channel == MagickFalse)
5835 return(MagickFalse);
5836 if (nexus_info->authentic_pixel_cache != MagickFalse)
5838 if (nexus_info->indexes == (IndexPacket *) NULL)
5839 return(MagickFalse);
5840 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5841 return(MagickFalse);
5842 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5843 nexus_info->region.x;
5844 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5845 rows=nexus_info->region.height;
5846 extent=(MagickSizeType) length*rows;
5847 p=nexus_info->indexes;
5849 switch (cache_info->type)
5860 if ((cache_info->columns == nexus_info->region.width) &&
5861 (extent == (MagickSizeType) ((
size_t) extent)))
5866 q=cache_info->indexes+offset;
5867 for (y=0; y < (ssize_t) rows; y++)
5869 (void) memcpy(q,p,(
size_t) length);
5870 p+=(ptrdiff_t) nexus_info->region.width;
5871 q+=(ptrdiff_t) cache_info->columns;
5880 LockSemaphoreInfo(cache_info->file_semaphore);
5881 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5883 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5884 cache_info->cache_filename);
5885 UnlockSemaphoreInfo(cache_info->file_semaphore);
5886 return(MagickFalse);
5888 if ((cache_info->columns == nexus_info->region.width) &&
5889 (extent <= MagickMaxBufferExtent))
5894 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5895 for (y=0; y < (ssize_t) rows; y++)
5897 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5898 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(PixelPacket)+
5899 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5901 if (count < (MagickOffsetType) length)
5903 p+=(ptrdiff_t) nexus_info->region.width;
5904 offset+=(MagickOffsetType) cache_info->columns;
5906 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5907 (void) ClosePixelCacheOnDisk(cache_info);
5908 UnlockSemaphoreInfo(cache_info->file_semaphore);
5911 case DistributedCache:
5919 LockSemaphoreInfo(cache_info->file_semaphore);
5920 region=nexus_info->region;
5921 if ((cache_info->columns != nexus_info->region.width) ||
5922 (extent > MagickMaxBufferExtent))
5929 for (y=0; y < (ssize_t) rows; y++)
5931 count=WriteDistributePixelCacheIndexes((DistributeCacheInfo *)
5932 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5933 if (count != (MagickOffsetType) length)
5935 p+=(ptrdiff_t) nexus_info->region.width;
5938 UnlockSemaphoreInfo(cache_info->file_semaphore);
5944 if (y < (ssize_t) rows)
5946 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5947 cache_info->cache_filename);
5948 return(MagickFalse);
5950 if ((cache_info->debug != MagickFalse) &&
5951 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5952 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5953 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5954 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5955 nexus_info->region.x,(
double) nexus_info->region.y);
5987static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5988 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
6007 if (nexus_info->authentic_pixel_cache != MagickFalse)
6009 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
6010 return(MagickFalse);
6011 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
6012 nexus_info->region.x;
6013 length=(MagickSizeType) nexus_info->region.width*
sizeof(PixelPacket);
6014 rows=nexus_info->region.height;
6016 p=nexus_info->pixels;
6018 switch (cache_info->type)
6029 if ((cache_info->columns == nexus_info->region.width) &&
6030 (extent == (MagickSizeType) ((
size_t) extent)))
6035 q=cache_info->pixels+offset;
6036 for (y=0; y < (ssize_t) rows; y++)
6038 (void) memcpy(q,p,(
size_t) length);
6039 p+=(ptrdiff_t) nexus_info->region.width;
6040 q+=(ptrdiff_t) cache_info->columns;
6049 LockSemaphoreInfo(cache_info->file_semaphore);
6050 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6052 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6053 cache_info->cache_filename);
6054 UnlockSemaphoreInfo(cache_info->file_semaphore);
6055 return(MagickFalse);
6057 if ((cache_info->columns == nexus_info->region.width) &&
6058 (extent <= MagickMaxBufferExtent))
6063 for (y=0; y < (ssize_t) rows; y++)
6065 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6066 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6067 if (count < (MagickOffsetType) length)
6069 p+=(ptrdiff_t) nexus_info->region.width;
6070 offset+=(MagickOffsetType) cache_info->columns;
6072 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6073 (void) ClosePixelCacheOnDisk(cache_info);
6074 UnlockSemaphoreInfo(cache_info->file_semaphore);
6077 case DistributedCache:
6085 LockSemaphoreInfo(cache_info->file_semaphore);
6086 region=nexus_info->region;
6087 if ((cache_info->columns != nexus_info->region.width) ||
6088 (extent > MagickMaxBufferExtent))
6095 for (y=0; y < (ssize_t) rows; y++)
6097 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6098 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6099 if (count != (MagickOffsetType) length)
6101 p+=(ptrdiff_t) nexus_info->region.width;
6104 UnlockSemaphoreInfo(cache_info->file_semaphore);
6110 if (y < (ssize_t) rows)
6112 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6113 cache_info->cache_filename);
6114 return(MagickFalse);
6116 if ((cache_info->debug != MagickFalse) &&
6117 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6118 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6119 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6120 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6121 nexus_info->region.x,(
double) nexus_info->region.y);