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_utf8(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 (ValidatePixelCacheMorphology(image) == MagickFalse)
1942 status=OpenPixelCache(image,IOMode,exception);
1943 cache_info=(CacheInfo *) image->cache;
1944 if (cache_info->file != -1)
1945 (void) ClosePixelCacheOnDisk(cache_info);
1948 UnlockSemaphoreInfo(image->semaphore);
1949 if (status == MagickFalse)
1950 return((Cache) NULL);
1951 return(image->cache);
1978MagickExport CacheType GetPixelCacheType(
const Image *image)
1980 return(GetImagePixelCacheType(image));
1983MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1986 *magick_restrict cache_info;
1988 assert(image != (Image *) NULL);
1989 assert(image->signature == MagickCoreSignature);
1990 assert(image->cache != (Cache) NULL);
1991 cache_info=(CacheInfo *) image->cache;
1992 assert(cache_info->signature == MagickCoreSignature);
1993 return(cache_info->type);
2026MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2027 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2030 *magick_restrict cache_info;
2033 *magick_restrict pixels;
2035 assert(image != (Image *) NULL);
2036 assert(image->signature == MagickCoreSignature);
2037 assert(image->cache != (Cache) NULL);
2038 cache_info=(CacheInfo *) image->cache;
2039 assert(cache_info->signature == MagickCoreSignature);
2040 *pixel=image->background_color;
2041 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2042 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2043 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2044 if (pixels == (PixelPacket *) NULL)
2045 return(MagickFalse);
2081static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2082 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2085 *magick_restrict cache_info;
2088 id = GetOpenMPThreadId();
2091 *magick_restrict pixels;
2093 assert(image != (
const Image *) NULL);
2094 assert(image->signature == MagickCoreSignature);
2095 assert(image->cache != (Cache) NULL);
2096 cache_info=(CacheInfo *) image->cache;
2097 assert(cache_info->signature == MagickCoreSignature);
2098 *pixel=image->background_color;
2099 assert(
id < (
int) cache_info->number_threads);
2100 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2101 cache_info->nexus_info[
id],exception);
2102 if (pixels == (PixelPacket *) NULL)
2103 return(MagickFalse);
2140MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2141 const ssize_t x,
const ssize_t y,MagickPixelPacket *pixel,
2142 ExceptionInfo *exception)
2145 *magick_restrict cache_info;
2148 id = GetOpenMPThreadId();
2151 *magick_restrict indexes;
2154 *magick_restrict pixels;
2156 assert(image != (
const Image *) NULL);
2157 assert(image->signature == MagickCoreSignature);
2158 assert(image->cache != (Cache) NULL);
2159 cache_info=(CacheInfo *) image->cache;
2160 assert(cache_info->signature == MagickCoreSignature);
2161 assert(
id < (
int) cache_info->number_threads);
2162 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2163 1UL,1UL,cache_info->nexus_info[
id],exception);
2164 GetMagickPixelPacket(image,pixel);
2165 if (pixels == (
const PixelPacket *) NULL)
2166 return(MagickFalse);
2167 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2168 SetMagickPixelPacket(image,pixels,indexes,pixel);
2207MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2208 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2209 PixelPacket *pixel,ExceptionInfo *exception)
2212 *magick_restrict cache_info;
2215 id = GetOpenMPThreadId();
2218 *magick_restrict pixels;
2220 assert(image != (
const Image *) NULL);
2221 assert(image->signature == MagickCoreSignature);
2222 assert(image->cache != (Cache) NULL);
2223 cache_info=(CacheInfo *) image->cache;
2224 assert(cache_info->signature == MagickCoreSignature);
2225 *pixel=image->background_color;
2226 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2227 (GetOneVirtualPixelFromHandler) NULL)
2228 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2229 virtual_pixel_method,x,y,pixel,exception));
2230 assert(
id < (
int) cache_info->number_threads);
2231 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2232 cache_info->nexus_info[
id],exception);
2233 if (pixels == (
const PixelPacket *) NULL)
2234 return(MagickFalse);
2270MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2271 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2274 *magick_restrict cache_info;
2277 id = GetOpenMPThreadId();
2280 *magick_restrict pixels;
2282 assert(image != (
const Image *) NULL);
2283 assert(image->signature == MagickCoreSignature);
2284 assert(image->cache != (Cache) NULL);
2285 cache_info=(CacheInfo *) image->cache;
2286 assert(cache_info->signature == MagickCoreSignature);
2287 *pixel=image->background_color;
2288 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2289 (GetOneVirtualPixelFromHandler) NULL)
2290 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2291 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2292 assert(
id < (
int) cache_info->number_threads);
2293 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2294 1UL,1UL,cache_info->nexus_info[
id],exception);
2295 if (pixels == (
const PixelPacket *) NULL)
2296 return(MagickFalse);
2335static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2336 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2337 PixelPacket *pixel,ExceptionInfo *exception)
2340 *magick_restrict cache_info;
2343 id = GetOpenMPThreadId();
2346 *magick_restrict pixels;
2348 assert(image != (
const Image *) NULL);
2349 assert(image->signature == MagickCoreSignature);
2350 assert(image->cache != (Cache) NULL);
2351 cache_info=(CacheInfo *) image->cache;
2352 assert(cache_info->signature == MagickCoreSignature);
2353 assert(
id < (
int) cache_info->number_threads);
2354 *pixel=image->background_color;
2355 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2356 cache_info->nexus_info[
id],exception);
2357 if (pixels == (
const PixelPacket *) NULL)
2358 return(MagickFalse);
2388MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2391 *magick_restrict cache_info;
2393 assert(cache != (Cache) NULL);
2394 cache_info=(CacheInfo *) cache;
2395 assert(cache_info->signature == MagickCoreSignature);
2396 if (IsEventLogging() != MagickFalse)
2397 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2398 cache_info->filename);
2399 return(cache_info->channels);
2424MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2427 *magick_restrict cache_info;
2429 assert(cache != (Cache) NULL);
2430 cache_info=(CacheInfo *) cache;
2431 assert(cache_info->signature == MagickCoreSignature);
2432 if (IsEventLogging() != MagickFalse)
2433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2434 cache_info->filename);
2435 return(cache_info->colorspace);
2461MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2464 *magick_restrict cache_info;
2466 assert(image != (
const Image *) NULL);
2467 assert(image->signature == MagickCoreSignature);
2468 assert(image->cache != (Cache) NULL);
2469 cache_info=(CacheInfo *) image->cache;
2470 assert(cache_info->signature == MagickCoreSignature);
2471 return(cache_info->cache_filename);
2496MagickExport
void GetPixelCacheMethods(CacheMethods *cache_methods)
2498 assert(cache_methods != (CacheMethods *) NULL);
2499 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2500 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2501 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2502 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2503 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2504 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2505 cache_methods->get_authentic_indexes_from_handler=
2506 GetAuthenticIndexesFromCache;
2507 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2508 cache_methods->get_one_authentic_pixel_from_handler=
2509 GetOneAuthenticPixelFromCache;
2510 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2511 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2512 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2539MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2540 NexusInfo *nexus_info)
2543 *magick_restrict cache_info;
2548 assert(cache != NULL);
2549 cache_info=(CacheInfo *) cache;
2550 assert(cache_info->signature == MagickCoreSignature);
2551 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2553 return((MagickSizeType) cache_info->columns*cache_info->rows);
2584MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2585 ExceptionInfo *exception)
2588 *magick_restrict cache_info;
2590 assert(image != (
const Image *) NULL);
2591 assert(image->signature == MagickCoreSignature);
2592 assert(image->cache != (Cache) NULL);
2593 assert(length != (MagickSizeType *) NULL);
2594 assert(exception != (ExceptionInfo *) NULL);
2595 assert(exception->signature == MagickCoreSignature);
2596 cache_info=(CacheInfo *) image->cache;
2597 assert(cache_info->signature == MagickCoreSignature);
2599 *length=cache_info->length;
2600 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2601 return((
void *) NULL);
2602 return((
void *) cache_info->pixels);
2629MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2632 *magick_restrict cache_info;
2634 assert(cache != (Cache) NULL);
2635 cache_info=(CacheInfo *) cache;
2636 assert(cache_info->signature == MagickCoreSignature);
2637 if (IsEventLogging() != MagickFalse)
2638 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2639 cache_info->filename);
2640 return(cache_info->storage_class);
2670MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2673 assert(image != (Image *) NULL);
2674 assert(image->signature == MagickCoreSignature);
2675 if (IsEventLogging() != MagickFalse)
2676 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2677 *width=2048UL/
sizeof(PixelPacket);
2678 if (GetImagePixelCacheType(image) == DiskCache)
2679 *width=8192UL/
sizeof(PixelPacket);
2707MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2710 *magick_restrict cache_info;
2712 assert(image != (Image *) NULL);
2713 assert(image->signature == MagickCoreSignature);
2714 assert(image->cache != (Cache) NULL);
2715 cache_info=(CacheInfo *) image->cache;
2716 assert(cache_info->signature == MagickCoreSignature);
2717 return(cache_info->virtual_pixel_method);
2743static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2746 *magick_restrict cache_info;
2749 id = GetOpenMPThreadId();
2751 assert(image != (
const Image *) NULL);
2752 assert(image->signature == MagickCoreSignature);
2753 assert(image->cache != (Cache) NULL);
2754 cache_info=(CacheInfo *) image->cache;
2755 assert(cache_info->signature == MagickCoreSignature);
2756 assert(
id < (
int) cache_info->number_threads);
2757 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2786MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2787 NexusInfo *nexus_info)
2790 *magick_restrict cache_info;
2792 assert(cache != (Cache) NULL);
2793 cache_info=(CacheInfo *) cache;
2794 assert(cache_info->signature == MagickCoreSignature);
2795 if (cache_info->storage_class == UndefinedClass)
2796 return((IndexPacket *) NULL);
2797 return(nexus_info->indexes);
2825MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2828 *magick_restrict cache_info;
2831 id = GetOpenMPThreadId();
2833 assert(image != (
const Image *) NULL);
2834 assert(image->signature == MagickCoreSignature);
2835 assert(image->cache != (Cache) NULL);
2836 cache_info=(CacheInfo *) image->cache;
2837 assert(cache_info->signature == MagickCoreSignature);
2838 if (cache_info->methods.get_virtual_indexes_from_handler !=
2839 (GetVirtualIndexesFromHandler) NULL)
2844 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2845 if (indexes != (IndexPacket *) NULL)
2848 assert(
id < (
int) cache_info->number_threads);
2849 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2892 0, 48, 12, 60, 3, 51, 15, 63,
2893 32, 16, 44, 28, 35, 19, 47, 31,
2894 8, 56, 4, 52, 11, 59, 7, 55,
2895 40, 24, 36, 20, 43, 27, 39, 23,
2896 2, 50, 14, 62, 1, 49, 13, 61,
2897 34, 18, 46, 30, 33, 17, 45, 29,
2898 10, 58, 6, 54, 9, 57, 5, 53,
2899 42, 26, 38, 22, 41, 25, 37, 21
2902static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2907 index=x+DitherMatrix[x & 0x07]-32L;
2910 if (index >= (ssize_t) columns)
2911 return((ssize_t) columns-1L);
2915static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2920 index=y+DitherMatrix[y & 0x07]-32L;
2923 if (index >= (ssize_t) rows)
2924 return((ssize_t) rows-1L);
2928static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2932 if (x >= (ssize_t) columns)
2933 return((ssize_t) (columns-1));
2937static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2941 if (y >= (ssize_t) rows)
2942 return((ssize_t) (rows-1));
2946static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2949 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2950 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2951 return(MagickFalse);
2955static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2957 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2960static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2962 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2965static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2966 const size_t extent)
2971 modulo.quotient=offset;
2975 modulo.quotient=offset/((ssize_t) extent);
2976 modulo.remainder=offset % ((ssize_t) extent);
2978 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2981 modulo.remainder+=((ssize_t) extent);
2986MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2987 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2988 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2989 ExceptionInfo *exception)
2992 *magick_restrict cache_info;
2995 *magick_restrict virtual_indexes;
3002 *magick_restrict indexes;
3012 *magick_restrict virtual_nexus;
3015 *magick_restrict pixels,
3026 assert(image != (
const Image *) NULL);
3027 assert(image->signature == MagickCoreSignature);
3028 assert(image->cache != (Cache) NULL);
3029 cache_info=(CacheInfo *) image->cache;
3030 assert(cache_info->signature == MagickCoreSignature);
3031 if (cache_info->type == UndefinedCache)
3032 return((
const PixelPacket *) NULL);
3033#if defined(MAGICKCORE_OPENCL_SUPPORT)
3034 CopyOpenCLBuffer(cache_info);
3036 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3037 (image->clip_mask != (Image *) NULL) || (image->mask != (Image *) NULL) ?
3038 MagickTrue : MagickFalse,nexus_info,exception);
3039 if (pixels == (PixelPacket *) NULL)
3040 return((
const PixelPacket *) NULL);
3041 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3042 return((
const PixelPacket *) NULL);
3043 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3044 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3045 return((
const PixelPacket *) NULL);
3046 offset+=nexus_info->region.x;
3047 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3048 nexus_info->region.width-1L;
3049 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3050 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3051 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3052 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3060 if (nexus_info->authentic_pixel_cache != MagickFalse)
3062 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3063 if (status == MagickFalse)
3064 return((
const PixelPacket *) NULL);
3065 if ((cache_info->storage_class == PseudoClass) ||
3066 (cache_info->colorspace == CMYKColorspace))
3068 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3069 if (status == MagickFalse)
3070 return((
const PixelPacket *) NULL);
3077 virtual_nexus=nexus_info->virtual_nexus;
3079 indexes=nexus_info->indexes;
3080 switch (virtual_pixel_method)
3082 case BlackVirtualPixelMethod:
3084 SetPixelRed(&virtual_pixel,0);
3085 SetPixelGreen(&virtual_pixel,0);
3086 SetPixelBlue(&virtual_pixel,0);
3087 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3090 case GrayVirtualPixelMethod:
3092 SetPixelRed(&virtual_pixel,QuantumRange/2);
3093 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3094 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3095 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3098 case TransparentVirtualPixelMethod:
3100 SetPixelRed(&virtual_pixel,0);
3101 SetPixelGreen(&virtual_pixel,0);
3102 SetPixelBlue(&virtual_pixel,0);
3103 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3106 case MaskVirtualPixelMethod:
3107 case WhiteVirtualPixelMethod:
3109 SetPixelRed(&virtual_pixel,QuantumRange);
3110 SetPixelGreen(&virtual_pixel,QuantumRange);
3111 SetPixelBlue(&virtual_pixel,QuantumRange);
3112 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3117 virtual_pixel=image->background_color;
3121 virtual_index=(IndexPacket) 0;
3122 for (v=0; v < (ssize_t) rows; v++)
3128 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3129 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3130 y_offset=EdgeY(y_offset,cache_info->rows);
3131 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3137 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3138 (ssize_t) columns-u);
3139 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3140 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3150 length=(MagickSizeType) 1;
3151 switch (virtual_pixel_method)
3153 case BackgroundVirtualPixelMethod:
3154 case ConstantVirtualPixelMethod:
3155 case BlackVirtualPixelMethod:
3156 case GrayVirtualPixelMethod:
3157 case TransparentVirtualPixelMethod:
3158 case MaskVirtualPixelMethod:
3159 case WhiteVirtualPixelMethod:
3162 virtual_indexes=(&virtual_index);
3165 case EdgeVirtualPixelMethod:
3168 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3169 EdgeX(x_offset,cache_info->columns),
3170 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3172 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3176 case RandomVirtualPixelMethod:
3178 if (cache_info->random_info == (RandomInfo *) NULL)
3179 cache_info->random_info=AcquireRandomInfo();
3180 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3181 RandomX(cache_info->random_info,cache_info->columns),
3182 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3183 virtual_nexus,exception);
3184 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3188 case DitherVirtualPixelMethod:
3190 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3191 DitherX(x_offset,cache_info->columns),
3192 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3194 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3198 case TileVirtualPixelMethod:
3200 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3201 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3202 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3203 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3205 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3209 case MirrorVirtualPixelMethod:
3211 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3212 if ((x_modulo.quotient & 0x01) == 1L)
3213 x_modulo.remainder=(ssize_t) cache_info->columns-
3214 x_modulo.remainder-1L;
3215 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3216 if ((y_modulo.quotient & 0x01) == 1L)
3217 y_modulo.remainder=(ssize_t) cache_info->rows-
3218 y_modulo.remainder-1L;
3219 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3220 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3222 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3226 case CheckerTileVirtualPixelMethod:
3228 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3229 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3230 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3233 virtual_indexes=(&virtual_index);
3236 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3237 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3239 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3243 case HorizontalTileVirtualPixelMethod:
3245 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3248 virtual_indexes=(&virtual_index);
3251 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3252 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3253 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3254 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3256 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3260 case VerticalTileVirtualPixelMethod:
3262 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3265 virtual_indexes=(&virtual_index);
3268 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3269 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3270 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3271 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3273 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3277 case HorizontalTileEdgeVirtualPixelMethod:
3279 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3280 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3281 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3282 virtual_nexus,exception);
3283 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3287 case VerticalTileEdgeVirtualPixelMethod:
3289 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3290 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3291 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3292 virtual_nexus,exception);
3293 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3298 if (p == (
const PixelPacket *) NULL)
3301 if ((indexes != (IndexPacket *) NULL) &&
3302 (virtual_indexes != (
const IndexPacket *) NULL))
3303 *indexes++=(*virtual_indexes);
3309 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3310 (
size_t) length,1UL,virtual_nexus,exception);
3311 if (p == (
const PixelPacket *) NULL)
3313 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3314 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3315 q+=(ptrdiff_t) length;
3316 if ((indexes != (IndexPacket *) NULL) &&
3317 (virtual_indexes != (
const IndexPacket *) NULL))
3319 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3320 sizeof(*virtual_indexes));
3324 if (u < (ssize_t) columns)
3330 if (v < (ssize_t) rows)
3331 return((
const PixelPacket *) NULL);
3369static const PixelPacket *GetVirtualPixelCache(
const Image *image,
3370 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3371 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3374 *magick_restrict cache_info;
3377 id = GetOpenMPThreadId();
3379 assert(image != (
const Image *) NULL);
3380 assert(image->signature == MagickCoreSignature);
3381 assert(image->cache != (Cache) NULL);
3382 cache_info=(CacheInfo *) image->cache;
3383 assert(cache_info->signature == MagickCoreSignature);
3384 assert(
id < (
int) cache_info->number_threads);
3385 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3386 cache_info->nexus_info[
id],exception));
3412MagickExport
const PixelPacket *GetVirtualPixelQueue(
const Image *image)
3415 *magick_restrict cache_info;
3418 id = GetOpenMPThreadId();
3420 assert(image != (
const Image *) NULL);
3421 assert(image->signature == MagickCoreSignature);
3422 assert(image->cache != (Cache) NULL);
3423 cache_info=(CacheInfo *) image->cache;
3424 assert(cache_info->signature == MagickCoreSignature);
3425 if (cache_info->methods.get_virtual_pixels_handler !=
3426 (GetVirtualPixelsHandler) NULL)
3427 return(cache_info->methods.get_virtual_pixels_handler(image));
3428 assert(
id < (
int) cache_info->number_threads);
3429 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3480MagickExport
const PixelPacket *GetVirtualPixels(
const Image *image,
3481 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3482 ExceptionInfo *exception)
3485 *magick_restrict cache_info;
3488 id = GetOpenMPThreadId();
3490 assert(image != (
const Image *) NULL);
3491 assert(image->signature == MagickCoreSignature);
3492 assert(image->cache != (Cache) NULL);
3493 cache_info=(CacheInfo *) image->cache;
3494 assert(cache_info->signature == MagickCoreSignature);
3495 if (cache_info->methods.get_virtual_pixel_handler !=
3496 (GetVirtualPixelHandler) NULL)
3497 return(cache_info->methods.get_virtual_pixel_handler(image,
3498 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3499 assert(
id < (
int) cache_info->number_threads);
3500 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3501 columns,rows,cache_info->nexus_info[
id],exception));
3527static const PixelPacket *GetVirtualPixelsCache(
const Image *image)
3530 *magick_restrict cache_info;
3533 id = GetOpenMPThreadId();
3535 assert(image != (
const Image *) NULL);
3536 assert(image->signature == MagickCoreSignature);
3537 assert(image->cache != (Cache) NULL);
3538 cache_info=(CacheInfo *) image->cache;
3539 assert(cache_info->signature == MagickCoreSignature);
3540 assert(
id < (
int) cache_info->number_threads);
3541 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3570MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3571 NexusInfo *nexus_info)
3574 *magick_restrict cache_info;
3576 assert(cache != (Cache) NULL);
3577 cache_info=(CacheInfo *) cache;
3578 assert(cache_info->signature == MagickCoreSignature);
3579 if (cache_info->storage_class == UndefinedClass)
3580 return((PixelPacket *) NULL);
3581 return((
const PixelPacket *) nexus_info->pixels);
3614static inline void ApplyPixelCompositeMask(
const MagickPixelPacket *p,
3615 const MagickRealType alpha,
const MagickPixelPacket *q,
3616 const MagickRealType beta,MagickPixelPacket *composite)
3621 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3626 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3627 gamma=MagickSafeReciprocal(gamma);
3628 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3629 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3630 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3631 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3632 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3635static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3636 ExceptionInfo *exception)
3639 *magick_restrict cache_info;
3645 *magick_restrict nexus_indexes,
3646 *magick_restrict indexes;
3656 **magick_restrict mask_nexus;
3668 if (IsEventLogging() != MagickFalse)
3669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3670 if ((image->mask == (Image *) NULL) || (image->storage_class == PseudoClass))
3672 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3674 cache_info=(CacheInfo *) image->cache;
3675 if (cache_info == (Cache) NULL)
3676 return(MagickFalse);
3677 mask_nexus=AcquirePixelCacheNexus(1);
3678 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3679 nexus_info->virtual_nexus,exception);
3680 indexes=nexus_info->virtual_nexus->indexes;
3681 q=nexus_info->pixels;
3682 nexus_indexes=nexus_info->indexes;
3683 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3684 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3685 nexus_info->region.height,mask_nexus[0],&image->exception);
3686 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL) ||
3687 (r == (
const PixelPacket *) NULL))
3688 return(MagickFalse);
3690 GetMagickPixelPacket(image,&alpha);
3691 GetMagickPixelPacket(image,&beta);
3692 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3697 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3699 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3700 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3701 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3702 alpha.opacity,&beta);
3703 SetPixelRed(q,ClampToQuantum(beta.red));
3704 SetPixelGreen(q,ClampToQuantum(beta.green));
3705 SetPixelBlue(q,ClampToQuantum(beta.blue));
3706 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3707 if (cache_info->active_index_channel != MagickFalse)
3708 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3715 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3750static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3751 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3756 if ((count == 0) || (quantum == 0))
3758 length=count*quantum;
3759 if (quantum != (length/count))
3766 return(MagickFalse);
3769static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3778 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3780 if (*cache_info->cache_filename ==
'\0')
3781 file=AcquireUniqueFileResource(cache_info->cache_filename);
3787 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3792 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3793 O_BINARY | O_EXCL,S_MODE);
3795 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3801 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3804 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3809 return(MagickFalse);
3810 (void) AcquireMagickResource(FileResource,1);
3811 if (cache_info->file != -1)
3812 (void) ClosePixelCacheOnDisk(cache_info);
3813 cache_info->file=file;
3814 cache_info->disk_mode=mode;
3818static inline MagickOffsetType WritePixelCacheRegion(
3819 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3820 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3828#if !defined(MAGICKCORE_HAVE_PWRITE)
3829 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3830 return((MagickOffsetType) -1);
3832 for (i=0; i < (MagickOffsetType) length; i+=count)
3834#if !defined(MAGICKCORE_HAVE_PWRITE)
3835 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3836 (MagickSizeType) i,MagickMaxBufferExtent));
3838 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3839 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3851static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3854 *magick_restrict cache_info;
3859 cache_info=(CacheInfo *) image->cache;
3860 if (cache_info->debug != MagickFalse)
3863 format[MaxTextExtent],
3864 message[MaxTextExtent];
3866 (void) FormatMagickSize(length,MagickFalse,format);
3867 (void) FormatLocaleString(message,MaxTextExtent,
3868 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3869 cache_info->cache_filename,cache_info->file,format);
3870 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3872 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3874 return(MagickFalse);
3875 if ((MagickSizeType) offset < length)
3881 extent=(MagickOffsetType) length-1;
3882 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3885 return(MagickFalse);
3886#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3887 if (cache_info->synchronize != MagickFalse)
3888 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3889 return(MagickFalse);
3892 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3894 return(MagickFalse);
3898static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3899 ExceptionInfo *exception)
3902 *magick_restrict cache_info,
3906 format[MaxTextExtent],
3907 message[MaxTextExtent];
3924 assert(image != (
const Image *) NULL);
3925 assert(image->signature == MagickCoreSignature);
3926 assert(image->cache != (Cache) NULL);
3927 if (IsEventLogging() != MagickFalse)
3928 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3929 if (cache_anonymous_memory < 0)
3937 cache_anonymous_memory=0;
3938 value=GetPolicyValue(
"pixel-cache-memory");
3939 if (value == (
char *) NULL)
3940 value=GetPolicyValue(
"cache:memory-map");
3941 if (LocaleCompare(value,
"anonymous") == 0)
3943#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3944 cache_anonymous_memory=1;
3946 (void) ThrowMagickException(exception,GetMagickModule(),
3947 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3948 "'%s' (policy requires anonymous memory mapping)",image->filename);
3951 value=DestroyString(value);
3953 if ((image->columns == 0) || (image->rows == 0))
3954 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3955 cache_info=(CacheInfo *) image->cache;
3956 assert(cache_info->signature == MagickCoreSignature);
3957 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3958 ((MagickSizeType) image->rows > cache_info->height_limit))
3959 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3961 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3963 length=GetImageListLength(image);
3964 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3965 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3968 source_info=(*cache_info);
3969 source_info.file=(-1);
3970 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3971 image->filename,(
double) image->scene);
3972 cache_info->storage_class=image->storage_class;
3973 cache_info->colorspace=image->colorspace;
3974 cache_info->rows=image->rows;
3975 cache_info->columns=image->columns;
3976 cache_info->channels=image->channels;
3977 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3978 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3979 cache_info->mode=mode;
3980 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3981 packet_size=
sizeof(PixelPacket);
3982 if (cache_info->active_index_channel != MagickFalse)
3983 packet_size+=
sizeof(IndexPacket);
3984 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3986 cache_info->storage_class=UndefinedClass;
3987 cache_info->length=0;
3988 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3991 columns=(size_t) (length/cache_info->rows/packet_size);
3992 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3993 ((ssize_t) cache_info->rows < 0))
3995 cache_info->storage_class=UndefinedClass;
3996 cache_info->length=0;
3997 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
4000 cache_info->length=length;
4001 if (image->ping != MagickFalse)
4003 cache_info->type=PingCache;
4006 status=AcquireMagickResource(AreaResource,(MagickSizeType)
4007 cache_info->columns*cache_info->rows);
4008 if (cache_info->mode == PersistMode)
4010 length=number_pixels*(
sizeof(PixelPacket)+
sizeof(IndexPacket));
4011 if ((status != MagickFalse) &&
4012 (length == (MagickSizeType) ((
size_t) length)) &&
4013 ((cache_info->type == UndefinedCache) ||
4014 (cache_info->type == MemoryCache)))
4016 status=AcquireMagickResource(MemoryResource,cache_info->length);
4017 if (status != MagickFalse)
4020 if (cache_anonymous_memory <= 0)
4022 cache_info->mapped=MagickFalse;
4023 cache_info->pixels=(PixelPacket *) MagickAssumeAligned(
4024 AcquireAlignedMemory(1,(
size_t) cache_info->length));
4028 cache_info->mapped=MagickTrue;
4029 cache_info->pixels=(PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
4030 cache_info->length);
4032 if (cache_info->pixels == (PixelPacket *) NULL)
4034 cache_info->mapped=source_info.mapped;
4035 cache_info->pixels=source_info.pixels;
4042 cache_info->colorspace=image->colorspace;
4043 cache_info->type=MemoryCache;
4044 cache_info->indexes=(IndexPacket *) NULL;
4045 if (cache_info->active_index_channel != MagickFalse)
4046 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4048 if ((source_info.storage_class != UndefinedClass) &&
4051 status&=ClonePixelCacheRepository(cache_info,&source_info,
4053 RelinquishPixelCachePixels(&source_info);
4055 if (cache_info->debug != MagickFalse)
4057 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4058 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4060 (void) FormatLocaleString(message,MaxTextExtent,
4061 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4062 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4063 type,(
double) cache_info->columns,(
double) cache_info->rows,
4065 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4068 cache_info->storage_class=image->storage_class;
4071 if ((source_info.storage_class != UndefinedClass) &&
4073 RelinquishPixelCachePixels(&source_info);
4074 cache_info->type=UndefinedCache;
4075 return(MagickFalse);
4081 status=AcquireMagickResource(DiskResource,cache_info->length);
4082 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4084 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4092 server_info=AcquireDistributeCacheInfo(exception);
4093 if (server_info != (DistributeCacheInfo *) NULL)
4095 status=OpenDistributePixelCache(server_info,image);
4096 if (status == MagickFalse)
4098 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4099 GetDistributeCacheHostname(server_info));
4100 server_info=DestroyDistributeCacheInfo(server_info);
4108 cache_info->type=DistributedCache;
4109 cache_info->storage_class=image->storage_class;
4110 cache_info->colorspace=image->colorspace;
4111 cache_info->server_info=server_info;
4112 (void) FormatLocaleString(cache_info->cache_filename,
4113 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4114 (DistributeCacheInfo *) cache_info->server_info),
4115 GetDistributeCachePort((DistributeCacheInfo *)
4116 cache_info->server_info));
4117 if ((source_info.storage_class != UndefinedClass) &&
4120 status=ClonePixelCacheRepository(cache_info,&source_info,
4122 RelinquishPixelCachePixels(&source_info);
4124 if (cache_info->debug != MagickFalse)
4126 (void) FormatMagickSize(cache_info->length,MagickFalse,
4128 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4130 (void) FormatLocaleString(message,MaxTextExtent,
4131 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4132 cache_info->cache_filename,GetDistributeCacheFile(
4133 (DistributeCacheInfo *) cache_info->server_info),type,
4134 (
double) cache_info->columns,(
double) cache_info->rows,
4136 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4141 if ((source_info.storage_class != UndefinedClass) &&
4143 RelinquishPixelCachePixels(&source_info);
4144 cache_info->type=UndefinedCache;
4145 return(MagickFalse);
4150 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4151 RelinquishPixelCachePixels(&source_info);
4152 cache_info->type=UndefinedCache;
4153 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4154 "CacheResourcesExhausted",
"`%s'",image->filename);
4155 return(MagickFalse);
4160 if (status == MagickFalse)
4162 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4163 RelinquishPixelCachePixels(&source_info);
4164 cache_info->type=UndefinedCache;
4165 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4166 "CacheResourcesExhausted",
"`%s'",image->filename);
4167 return(MagickFalse);
4169 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4170 (cache_info->mode != PersistMode))
4172 (void) ClosePixelCacheOnDisk(cache_info);
4173 *cache_info->cache_filename=
'\0';
4175 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4177 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4178 RelinquishPixelCachePixels(&source_info);
4179 cache_info->type=UndefinedCache;
4180 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4182 return(MagickFalse);
4184 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4185 cache_info->length);
4186 if (status == MagickFalse)
4188 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4189 RelinquishPixelCachePixels(&source_info);
4190 cache_info->type=UndefinedCache;
4191 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4193 return(MagickFalse);
4195 cache_info->storage_class=image->storage_class;
4196 cache_info->colorspace=image->colorspace;
4197 cache_info->type=DiskCache;
4198 length=number_pixels*(
sizeof(PixelPacket)+
sizeof(IndexPacket));
4199 if (length == (MagickSizeType) ((
size_t) length))
4201 status=AcquireMagickResource(MapResource,cache_info->length);
4202 if (status != MagickFalse)
4204 cache_info->pixels=(PixelPacket *) MapBlob(cache_info->file,mode,
4205 cache_info->offset,(
size_t) cache_info->length);
4206 if (cache_info->pixels == (PixelPacket *) NULL)
4208 cache_info->mapped=source_info.mapped;
4209 cache_info->pixels=source_info.pixels;
4210 RelinquishMagickResource(MapResource,cache_info->length);
4217 (void) ClosePixelCacheOnDisk(cache_info);
4218 cache_info->type=MapCache;
4219 cache_info->mapped=MagickTrue;
4220 cache_info->indexes=(IndexPacket *) NULL;
4221 if (cache_info->active_index_channel != MagickFalse)
4222 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4224 if ((source_info.storage_class != UndefinedClass) &&
4227 status=ClonePixelCacheRepository(cache_info,&source_info,
4229 RelinquishPixelCachePixels(&source_info);
4231 if (cache_info->debug != MagickFalse)
4233 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4234 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4236 (void) FormatLocaleString(message,MaxTextExtent,
4237 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4238 cache_info->filename,cache_info->cache_filename,
4239 cache_info->file,type,(
double) cache_info->columns,
4240 (
double) cache_info->rows,format);
4241 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4246 if ((source_info.storage_class != UndefinedClass) &&
4248 RelinquishPixelCachePixels(&source_info);
4249 cache_info->type=UndefinedCache;
4250 return(MagickFalse);
4257 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4259 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4260 RelinquishPixelCachePixels(&source_info);
4262 if (cache_info->debug != MagickFalse)
4264 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4265 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4267 (void) FormatLocaleString(message,MaxTextExtent,
4268 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4269 cache_info->cache_filename,cache_info->file,type,(
double)
4270 cache_info->columns,(
double) cache_info->rows,format);
4271 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4275 cache_info->type=UndefinedCache;
4276 return(MagickFalse);
4318MagickExport MagickBooleanType PersistPixelCache(Image *image,
4319 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4320 ExceptionInfo *exception)
4323 *magick_restrict cache_info,
4324 *magick_restrict clone_info;
4332 assert(image != (Image *) NULL);
4333 assert(image->signature == MagickCoreSignature);
4334 if (IsEventLogging() != MagickFalse)
4335 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4336 assert(image->cache != (
void *) NULL);
4337 assert(filename != (
const char *) NULL);
4338 assert(offset != (MagickOffsetType *) NULL);
4339 page_size=GetMagickPageSize();
4340 cache_info=(CacheInfo *) image->cache;
4341 assert(cache_info->signature == MagickCoreSignature);
4342#if defined(MAGICKCORE_OPENCL_SUPPORT)
4343 CopyOpenCLBuffer(cache_info);
4345 if (attach != MagickFalse)
4350 if (cache_info->debug != MagickFalse)
4351 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4352 "attach persistent cache");
4353 (void) CopyMagickString(cache_info->cache_filename,filename,
4355 cache_info->type=MapCache;
4356 cache_info->offset=(*offset);
4357 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4358 return(MagickFalse);
4359 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4360 ((MagickOffsetType) cache_info->length % page_size));
4366 status=AcquireMagickResource(DiskResource,cache_info->length);
4367 if (status == MagickFalse)
4369 cache_info->type=UndefinedCache;
4370 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4371 "CacheResourcesExhausted",
"`%s'",image->filename);
4372 return(MagickFalse);
4374 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4375 clone_info->type=DiskCache;
4376 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4377 clone_info->file=(-1);
4378 clone_info->storage_class=cache_info->storage_class;
4379 clone_info->colorspace=cache_info->colorspace;
4380 clone_info->columns=cache_info->columns;
4381 clone_info->rows=cache_info->rows;
4382 clone_info->active_index_channel=cache_info->active_index_channel;
4383 clone_info->mode=PersistMode;
4384 clone_info->length=cache_info->length;
4385 clone_info->channels=cache_info->channels;
4386 clone_info->offset=(*offset);
4387 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4388 if (status != MagickFalse)
4389 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4390 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4391 ((MagickOffsetType) cache_info->length % page_size));
4392 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4434MagickExport PixelPacket *QueueAuthenticPixel(Image *image,
const ssize_t x,
4435 const ssize_t y,
const size_t columns,
const size_t rows,
4436 const MagickBooleanType clone,NexusInfo *nexus_info,
4437 ExceptionInfo *exception)
4439 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4443MagickExport PixelPacket *QueueAuthenticPixelCacheNexus(Image *image,
4444 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4445 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4448 *magick_restrict cache_info;
4457 *magick_restrict pixels;
4462 assert(image != (
const Image *) NULL);
4463 assert(image->signature == MagickCoreSignature);
4464 assert(image->cache != (Cache) NULL);
4465 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4466 if (cache_info == (Cache) NULL)
4467 return((PixelPacket *) NULL);
4468 assert(cache_info->signature == MagickCoreSignature);
4469 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4470 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4471 (y >= (ssize_t) cache_info->rows))
4473 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4474 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4475 return((PixelPacket *) NULL);
4477 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4478 return((PixelPacket *) NULL);
4479 offset=y*(MagickOffsetType) cache_info->columns+x;
4481 return((PixelPacket *) NULL);
4482 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4483 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4484 (MagickOffsetType) columns-1;
4485 if ((MagickSizeType) offset >= number_pixels)
4486 return((PixelPacket *) NULL);
4490 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4491 (image->clip_mask != (Image *) NULL) || (image->mask != (Image *) NULL) ?
4492 MagickTrue : MagickFalse,nexus_info,exception);
4529static PixelPacket *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4530 const ssize_t y,
const size_t columns,
const size_t rows,
4531 ExceptionInfo *exception)
4534 *magick_restrict cache_info;
4537 id = GetOpenMPThreadId();
4539 assert(image != (
const Image *) NULL);
4540 assert(image->signature == MagickCoreSignature);
4541 assert(image->cache != (Cache) NULL);
4542 cache_info=(CacheInfo *) image->cache;
4543 assert(cache_info->signature == MagickCoreSignature);
4544 assert(
id < (
int) cache_info->number_threads);
4545 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4546 cache_info->nexus_info[
id],exception));
4605MagickExport PixelPacket *QueueAuthenticPixels(Image *image,
const ssize_t x,
4606 const ssize_t y,
const size_t columns,
const size_t rows,
4607 ExceptionInfo *exception)
4610 *magick_restrict cache_info;
4613 id = GetOpenMPThreadId();
4615 assert(image != (Image *) NULL);
4616 assert(image->signature == MagickCoreSignature);
4617 assert(image->cache != (Cache) NULL);
4618 cache_info=(CacheInfo *) image->cache;
4619 assert(cache_info->signature == MagickCoreSignature);
4620 if (cache_info->methods.queue_authentic_pixels_handler !=
4621 (QueueAuthenticPixelsHandler) NULL)
4622 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4624 assert(
id < (
int) cache_info->number_threads);
4625 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4626 cache_info->nexus_info[
id],exception));
4658static inline MagickOffsetType ReadPixelCacheRegion(
4659 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4660 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4668#if !defined(MAGICKCORE_HAVE_PREAD)
4669 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4670 return((MagickOffsetType) -1);
4672 for (i=0; i < (MagickOffsetType) length; i+=count)
4674#if !defined(MAGICKCORE_HAVE_PREAD)
4675 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4676 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4678 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4679 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4691static MagickBooleanType ReadPixelCacheIndexes(
4692 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4693 ExceptionInfo *exception)
4712 if (cache_info->active_index_channel == MagickFalse)
4713 return(MagickFalse);
4714 if (nexus_info->authentic_pixel_cache != MagickFalse)
4716 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4717 return(MagickFalse);
4718 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4719 nexus_info->region.x;
4720 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4721 rows=nexus_info->region.height;
4723 q=nexus_info->indexes;
4725 switch (cache_info->type)
4736 if ((cache_info->columns == nexus_info->region.width) &&
4737 (extent == (MagickSizeType) ((
size_t) extent)))
4742 p=cache_info->indexes+offset;
4743 for (y=0; y < (ssize_t) rows; y++)
4745 (void) memcpy(q,p,(
size_t) length);
4746 p+=(ptrdiff_t) cache_info->columns;
4747 q+=(ptrdiff_t) nexus_info->region.width;
4756 LockSemaphoreInfo(cache_info->file_semaphore);
4757 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4759 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4760 cache_info->cache_filename);
4761 UnlockSemaphoreInfo(cache_info->file_semaphore);
4762 return(MagickFalse);
4764 if ((cache_info->columns == nexus_info->region.width) &&
4765 (extent <= MagickMaxBufferExtent))
4770 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4771 for (y=0; y < (ssize_t) rows; y++)
4773 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4774 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(PixelPacket)+
4775 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4776 if (count < (MagickOffsetType) length)
4778 offset+=(MagickOffsetType) cache_info->columns;
4779 q+=(ptrdiff_t) nexus_info->region.width;
4781 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4782 (void) ClosePixelCacheOnDisk(cache_info);
4783 UnlockSemaphoreInfo(cache_info->file_semaphore);
4786 case DistributedCache:
4794 LockSemaphoreInfo(cache_info->file_semaphore);
4795 region=nexus_info->region;
4796 if ((cache_info->columns != nexus_info->region.width) ||
4797 (extent > MagickMaxBufferExtent))
4804 for (y=0; y < (ssize_t) rows; y++)
4806 count=ReadDistributePixelCacheIndexes((DistributeCacheInfo *)
4807 cache_info->server_info,®ion,length,(
unsigned char *) q);
4808 if (count != (MagickOffsetType) length)
4810 q+=(ptrdiff_t) nexus_info->region.width;
4813 UnlockSemaphoreInfo(cache_info->file_semaphore);
4819 if (y < (ssize_t) rows)
4821 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4822 cache_info->cache_filename);
4823 return(MagickFalse);
4825 if ((cache_info->debug != MagickFalse) &&
4826 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4827 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4828 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4829 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4830 nexus_info->region.x,(
double) nexus_info->region.y);
4862static MagickBooleanType ReadPixelCachePixels(
4863 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4864 ExceptionInfo *exception)
4883 if (nexus_info->authentic_pixel_cache != MagickFalse)
4885 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4886 return(MagickFalse);
4887 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4888 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4889 return(MagickFalse);
4890 offset+=nexus_info->region.x;
4891 length=(MagickSizeType) nexus_info->region.width*
sizeof(PixelPacket);
4892 if ((length/
sizeof(PixelPacket)) != nexus_info->region.width)
4893 return(MagickFalse);
4894 rows=nexus_info->region.height;
4896 if ((extent == 0) || ((extent/length) != rows))
4897 return(MagickFalse);
4898 q=nexus_info->pixels;
4900 switch (cache_info->type)
4911 if ((cache_info->columns == nexus_info->region.width) &&
4912 (extent == (MagickSizeType) ((
size_t) extent)))
4917 p=cache_info->pixels+offset;
4918 for (y=0; y < (ssize_t) rows; y++)
4920 (void) memcpy(q,p,(
size_t) length);
4921 p+=(ptrdiff_t) cache_info->columns;
4922 q+=(ptrdiff_t) nexus_info->region.width;
4931 LockSemaphoreInfo(cache_info->file_semaphore);
4932 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4934 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4935 cache_info->cache_filename);
4936 UnlockSemaphoreInfo(cache_info->file_semaphore);
4937 return(MagickFalse);
4939 if ((cache_info->columns == nexus_info->region.width) &&
4940 (extent <= MagickMaxBufferExtent))
4945 for (y=0; y < (ssize_t) rows; y++)
4947 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4948 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4949 if (count < (MagickOffsetType) length)
4951 offset+=(MagickOffsetType) cache_info->columns;
4952 q+=(ptrdiff_t) nexus_info->region.width;
4954 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4955 (void) ClosePixelCacheOnDisk(cache_info);
4956 UnlockSemaphoreInfo(cache_info->file_semaphore);
4959 case DistributedCache:
4967 LockSemaphoreInfo(cache_info->file_semaphore);
4968 region=nexus_info->region;
4969 if ((cache_info->columns != nexus_info->region.width) ||
4970 (extent > MagickMaxBufferExtent))
4977 for (y=0; y < (ssize_t) rows; y++)
4979 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4980 cache_info->server_info,®ion,length,(
unsigned char *) q);
4981 if (count != (MagickOffsetType) length)
4983 q+=(ptrdiff_t) nexus_info->region.width;
4986 UnlockSemaphoreInfo(cache_info->file_semaphore);
4992 if (y < (ssize_t) rows)
4994 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4995 cache_info->cache_filename);
4996 return(MagickFalse);
4998 if ((cache_info->debug != MagickFalse) &&
4999 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5000 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5001 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5002 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5003 nexus_info->region.x,(
double) nexus_info->region.y);
5030MagickExport Cache ReferencePixelCache(Cache cache)
5033 *magick_restrict cache_info;
5035 assert(cache != (Cache *) NULL);
5036 cache_info=(CacheInfo *) cache;
5037 assert(cache_info->signature == MagickCoreSignature);
5038 LockSemaphoreInfo(cache_info->semaphore);
5039 cache_info->reference_count++;
5040 UnlockSemaphoreInfo(cache_info->semaphore);
5062MagickPrivate
void ResetCacheAnonymousMemory(
void)
5064 cache_anonymous_memory=0;
5091MagickExport
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5094 *magick_restrict cache_info;
5096 GetOneAuthenticPixelFromHandler
5097 get_one_authentic_pixel_from_handler;
5099 GetOneVirtualPixelFromHandler
5100 get_one_virtual_pixel_from_handler;
5105 assert(cache != (Cache) NULL);
5106 assert(cache_methods != (CacheMethods *) NULL);
5107 cache_info=(CacheInfo *) cache;
5108 assert(cache_info->signature == MagickCoreSignature);
5109 if (IsEventLogging() != MagickFalse)
5110 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5111 cache_info->filename);
5112 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5113 cache_info->methods.get_virtual_pixel_handler=
5114 cache_methods->get_virtual_pixel_handler;
5115 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5116 cache_info->methods.destroy_pixel_handler=
5117 cache_methods->destroy_pixel_handler;
5118 if (cache_methods->get_virtual_indexes_from_handler !=
5119 (GetVirtualIndexesFromHandler) NULL)
5120 cache_info->methods.get_virtual_indexes_from_handler=
5121 cache_methods->get_virtual_indexes_from_handler;
5122 if (cache_methods->get_authentic_pixels_handler !=
5123 (GetAuthenticPixelsHandler) NULL)
5124 cache_info->methods.get_authentic_pixels_handler=
5125 cache_methods->get_authentic_pixels_handler;
5126 if (cache_methods->queue_authentic_pixels_handler !=
5127 (QueueAuthenticPixelsHandler) NULL)
5128 cache_info->methods.queue_authentic_pixels_handler=
5129 cache_methods->queue_authentic_pixels_handler;
5130 if (cache_methods->sync_authentic_pixels_handler !=
5131 (SyncAuthenticPixelsHandler) NULL)
5132 cache_info->methods.sync_authentic_pixels_handler=
5133 cache_methods->sync_authentic_pixels_handler;
5134 if (cache_methods->get_authentic_pixels_from_handler !=
5135 (GetAuthenticPixelsFromHandler) NULL)
5136 cache_info->methods.get_authentic_pixels_from_handler=
5137 cache_methods->get_authentic_pixels_from_handler;
5138 if (cache_methods->get_authentic_indexes_from_handler !=
5139 (GetAuthenticIndexesFromHandler) NULL)
5140 cache_info->methods.get_authentic_indexes_from_handler=
5141 cache_methods->get_authentic_indexes_from_handler;
5142 get_one_virtual_pixel_from_handler=
5143 cache_info->methods.get_one_virtual_pixel_from_handler;
5144 if (get_one_virtual_pixel_from_handler !=
5145 (GetOneVirtualPixelFromHandler) NULL)
5146 cache_info->methods.get_one_virtual_pixel_from_handler=
5147 cache_methods->get_one_virtual_pixel_from_handler;
5148 get_one_authentic_pixel_from_handler=
5149 cache_methods->get_one_authentic_pixel_from_handler;
5150 if (get_one_authentic_pixel_from_handler !=
5151 (GetOneAuthenticPixelFromHandler) NULL)
5152 cache_info->methods.get_one_authentic_pixel_from_handler=
5153 cache_methods->get_one_authentic_pixel_from_handler;
5194static inline MagickBooleanType AcquireCacheNexusPixels(
5195 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5196 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5198 if (length != (MagickSizeType) ((
size_t) length))
5200 (void) ThrowMagickException(exception,GetMagickModule(),
5201 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5202 cache_info->filename);
5203 return(MagickFalse);
5205 nexus_info->length=0;
5206 nexus_info->mapped=MagickFalse;
5207 if (cache_anonymous_memory <= 0)
5209 nexus_info->cache=(PixelPacket *) MagickAssumeAligned(
5210 AcquireAlignedMemory(1,(
size_t) length));
5211 if (nexus_info->cache != (PixelPacket *) NULL)
5212 (void) memset(nexus_info->cache,0,(
size_t) length);
5216 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5217 if (nexus_info->cache != (PixelPacket *) NULL)
5218 nexus_info->mapped=MagickTrue;
5220 if (nexus_info->cache == (PixelPacket *) NULL)
5222 (void) ThrowMagickException(exception,GetMagickModule(),
5223 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5224 cache_info->filename);
5225 return(MagickFalse);
5227 nexus_info->length=length;
5231static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5234 if (nexus_info->length < CACHE_LINE_SIZE)
5236 if (mode == ReadMode)
5238 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5242 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5245static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5248 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5249 return(MagickFalse);
5250 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5251 return(MagickFalse);
5255static PixelPacket *SetPixelCacheNexusPixels(
5256 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5257 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5258 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5259 ExceptionInfo *exception)
5268 assert(cache_info != (
const CacheInfo *) NULL);
5269 assert(cache_info->signature == MagickCoreSignature);
5270 if (cache_info->type == UndefinedCache)
5271 return((PixelPacket *) NULL);
5272 assert(nexus_info->signature == MagickCoreSignature);
5273 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5274 if ((width == 0) || (height == 0))
5276 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5277 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5278 return((PixelPacket *) NULL);
5280 if (((MagickSizeType) width > cache_info->width_limit) ||
5281 ((MagickSizeType) height > cache_info->height_limit))
5283 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5284 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5285 return((PixelPacket *) NULL);
5287 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5288 (ValidatePixelOffset(y,height) == MagickFalse))
5290 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5291 "InvalidPixel",
"`%s'",cache_info->filename);
5292 return((PixelPacket *) NULL);
5294 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5295 (buffered == MagickFalse))
5297 if (((x >= 0) && (y >= 0) &&
5298 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5299 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5300 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5308 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5309 return((PixelPacket *) NULL);
5310 offset=y*(MagickOffsetType) cache_info->columns+x;
5311 nexus_info->pixels=cache_info->pixels+offset;
5312 nexus_info->indexes=(IndexPacket *) NULL;
5313 if (cache_info->active_index_channel != MagickFalse)
5314 nexus_info->indexes=cache_info->indexes+offset;
5315 nexus_info->region.width=width;
5316 nexus_info->region.height=height;
5317 nexus_info->region.x=x;
5318 nexus_info->region.y=y;
5319 nexus_info->authentic_pixel_cache=MagickTrue;
5320 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5321 return(nexus_info->pixels);
5327 number_pixels=(MagickSizeType) width*height;
5328 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5329 cache_info->rows))*
sizeof(PixelPacket);
5330 if (cache_info->active_index_channel != MagickFalse)
5331 length+=number_pixels*
sizeof(IndexPacket);
5333 if (nexus_info->cache == (PixelPacket *) NULL)
5334 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5336 if (nexus_info->length < length)
5338 RelinquishCacheNexusPixels(nexus_info);
5339 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5341 if (status == MagickFalse)
5343 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5344 return((PixelPacket *) NULL);
5346 nexus_info->pixels=nexus_info->cache;
5347 nexus_info->indexes=(IndexPacket *) NULL;
5348 if (cache_info->active_index_channel != MagickFalse)
5349 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5350 nexus_info->region.width=width;
5351 nexus_info->region.height=height;
5352 nexus_info->region.x=x;
5353 nexus_info->region.y=y;
5354 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5355 MagickTrue : MagickFalse;
5356 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5357 return(nexus_info->pixels);
5388static MagickBooleanType SetCacheAlphaChannel(Image *image,
5389 const Quantum opacity)
5392 *magick_restrict image_view;
5400 assert(image != (Image *) NULL);
5401 assert(image->signature == MagickCoreSignature);
5402 if (IsEventLogging() != MagickFalse)
5403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5404 assert(image->cache != (Cache) NULL);
5405 image->matte=MagickTrue;
5407 image_view=AcquireVirtualCacheView(image,&image->exception);
5408#if defined(MAGICKCORE_OPENMP_SUPPORT)
5409 #pragma omp parallel for schedule(static) shared(status) \
5410 magick_number_threads(image,image,image->rows,2)
5412 for (y=0; y < (ssize_t) image->rows; y++)
5420 if (status == MagickFalse)
5422 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5424 if (q == (PixelPacket *) NULL)
5429 for (x=0; x < (ssize_t) image->columns; x++)
5434 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5436 image_view=DestroyCacheView(image_view);
5440MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5441 const VirtualPixelMethod virtual_pixel_method)
5444 *magick_restrict cache_info;
5449 assert(image != (Image *) NULL);
5450 assert(image->signature == MagickCoreSignature);
5451 if (IsEventLogging() != MagickFalse)
5452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5453 assert(image->cache != (Cache) NULL);
5454 cache_info=(CacheInfo *) image->cache;
5455 assert(cache_info->signature == MagickCoreSignature);
5456 method=cache_info->virtual_pixel_method;
5457 cache_info->virtual_pixel_method=virtual_pixel_method;
5458 if ((image->columns != 0) && (image->rows != 0))
5459 switch (virtual_pixel_method)
5461 case BackgroundVirtualPixelMethod:
5463 if ((image->background_color.opacity != OpaqueOpacity) &&
5464 (image->matte == MagickFalse))
5465 (void) SetCacheAlphaChannel((Image *) image,OpaqueOpacity);
5466 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5467 (IsGrayColorspace(image->colorspace) != MagickFalse))
5468 (void) SetImageColorspace((Image *) image,sRGBColorspace);
5471 case TransparentVirtualPixelMethod:
5473 if (image->matte == MagickFalse)
5474 (void) SetCacheAlphaChannel((Image *) image,OpaqueOpacity);
5483#if defined(MAGICKCORE_OPENCL_SUPPORT)
5507static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5512 assert(cache_info != (CacheInfo *)NULL);
5513 if ((cache_info->type != MemoryCache) ||
5514 (cache_info->opencl == (OpenCLCacheInfo *)NULL))
5519 LockSemaphoreInfo(cache_info->semaphore);
5520 if (cache_info->opencl != (OpenCLCacheInfo *)NULL)
5528 clEnv=GetDefaultOpenCLEnv();
5529 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5530 if (events != (cl_event *) NULL)
5544 context=GetOpenCLContext(clEnv);
5545 queue=AcquireOpenCLCommandQueue(clEnv);
5546 pixels=(PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5547 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5548 cache_info->length,event_count,events,NULL,&status);
5549 assert(pixels == cache_info->pixels);
5550 events=(cl_event *) RelinquishMagickMemory(events);
5551 RelinquishOpenCLCommandQueue(clEnv,queue);
5553 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5555 UnlockSemaphoreInfo(cache_info->semaphore);
5558MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5561 *magick_restrict cache_info;
5563 assert(image != (Image *)NULL);
5564 cache_info = (CacheInfo *)image->cache;
5565 CopyOpenCLBuffer(cache_info);
5598MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5599 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5602 *magick_restrict cache_info;
5610 assert(image != (Image *) NULL);
5611 assert(image->signature == MagickCoreSignature);
5612 if (image->cache == (Cache) NULL)
5613 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5614 cache_info=(CacheInfo *) image->cache;
5615 assert(cache_info->signature == MagickCoreSignature);
5616 if (cache_info->type == UndefinedCache)
5617 return(MagickFalse);
5618 if ((image->storage_class == DirectClass) &&
5619 (image->clip_mask != (Image *) NULL) &&
5620 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5621 return(MagickFalse);
5622 if ((image->storage_class == DirectClass) &&
5623 (image->mask != (Image *) NULL) &&
5624 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5625 return(MagickFalse);
5626 if (nexus_info->authentic_pixel_cache != MagickFalse)
5628 if (image->taint == MagickFalse)
5629 image->taint=MagickTrue;
5632 assert(cache_info->signature == MagickCoreSignature);
5633 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5634 if ((cache_info->active_index_channel != MagickFalse) &&
5635 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5636 return(MagickFalse);
5637 if ((status != MagickFalse) && (image->taint == MagickFalse))
5638 image->taint=MagickTrue;
5669static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5670 ExceptionInfo *exception)
5673 *magick_restrict cache_info;
5676 id = GetOpenMPThreadId();
5681 assert(image != (Image *) NULL);
5682 assert(image->signature == MagickCoreSignature);
5683 assert(image->cache != (Cache) NULL);
5684 cache_info=(CacheInfo *) image->cache;
5685 assert(cache_info->signature == MagickCoreSignature);
5686 assert(
id < (
int) cache_info->number_threads);
5687 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5719MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5720 ExceptionInfo *exception)
5723 *magick_restrict cache_info;
5726 id = GetOpenMPThreadId();
5731 assert(image != (Image *) NULL);
5732 assert(image->signature == MagickCoreSignature);
5733 assert(image->cache != (Cache) NULL);
5734 cache_info=(CacheInfo *) image->cache;
5735 assert(cache_info->signature == MagickCoreSignature);
5736 if (cache_info->methods.sync_authentic_pixels_handler !=
5737 (SyncAuthenticPixelsHandler) NULL)
5738 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5739 assert(
id < (
int) cache_info->number_threads);
5740 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5772MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5773 ExceptionInfo *exception)
5776 *magick_restrict cache_info;
5778 assert(image != (Image *) NULL);
5779 assert(exception != (ExceptionInfo *) NULL);
5780 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5781 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5812static MagickBooleanType WritePixelCacheIndexes(CacheInfo *cache_info,
5813 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5832 if (cache_info->active_index_channel == MagickFalse)
5833 return(MagickFalse);
5834 if (nexus_info->authentic_pixel_cache != MagickFalse)
5836 if (nexus_info->indexes == (IndexPacket *) NULL)
5837 return(MagickFalse);
5838 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5839 return(MagickFalse);
5840 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5841 nexus_info->region.x;
5842 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5843 rows=nexus_info->region.height;
5844 extent=(MagickSizeType) length*rows;
5845 p=nexus_info->indexes;
5847 switch (cache_info->type)
5858 if ((cache_info->columns == nexus_info->region.width) &&
5859 (extent == (MagickSizeType) ((
size_t) extent)))
5864 q=cache_info->indexes+offset;
5865 for (y=0; y < (ssize_t) rows; y++)
5867 (void) memcpy(q,p,(
size_t) length);
5868 p+=(ptrdiff_t) nexus_info->region.width;
5869 q+=(ptrdiff_t) cache_info->columns;
5878 LockSemaphoreInfo(cache_info->file_semaphore);
5879 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5881 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5882 cache_info->cache_filename);
5883 UnlockSemaphoreInfo(cache_info->file_semaphore);
5884 return(MagickFalse);
5886 if ((cache_info->columns == nexus_info->region.width) &&
5887 (extent <= MagickMaxBufferExtent))
5892 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5893 for (y=0; y < (ssize_t) rows; y++)
5895 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5896 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(PixelPacket)+
5897 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5899 if (count < (MagickOffsetType) length)
5901 p+=(ptrdiff_t) nexus_info->region.width;
5902 offset+=(MagickOffsetType) cache_info->columns;
5904 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5905 (void) ClosePixelCacheOnDisk(cache_info);
5906 UnlockSemaphoreInfo(cache_info->file_semaphore);
5909 case DistributedCache:
5917 LockSemaphoreInfo(cache_info->file_semaphore);
5918 region=nexus_info->region;
5919 if ((cache_info->columns != nexus_info->region.width) ||
5920 (extent > MagickMaxBufferExtent))
5927 for (y=0; y < (ssize_t) rows; y++)
5929 count=WriteDistributePixelCacheIndexes((DistributeCacheInfo *)
5930 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5931 if (count != (MagickOffsetType) length)
5933 p+=(ptrdiff_t) nexus_info->region.width;
5936 UnlockSemaphoreInfo(cache_info->file_semaphore);
5942 if (y < (ssize_t) rows)
5944 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5945 cache_info->cache_filename);
5946 return(MagickFalse);
5948 if ((cache_info->debug != MagickFalse) &&
5949 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5950 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5951 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5952 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5953 nexus_info->region.x,(
double) nexus_info->region.y);
5985static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5986 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
6005 if (nexus_info->authentic_pixel_cache != MagickFalse)
6007 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
6008 return(MagickFalse);
6009 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
6010 nexus_info->region.x;
6011 length=(MagickSizeType) nexus_info->region.width*
sizeof(PixelPacket);
6012 rows=nexus_info->region.height;
6014 p=nexus_info->pixels;
6016 switch (cache_info->type)
6027 if ((cache_info->columns == nexus_info->region.width) &&
6028 (extent == (MagickSizeType) ((
size_t) extent)))
6033 q=cache_info->pixels+offset;
6034 for (y=0; y < (ssize_t) rows; y++)
6036 (void) memcpy(q,p,(
size_t) length);
6037 p+=(ptrdiff_t) nexus_info->region.width;
6038 q+=(ptrdiff_t) cache_info->columns;
6047 LockSemaphoreInfo(cache_info->file_semaphore);
6048 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6050 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6051 cache_info->cache_filename);
6052 UnlockSemaphoreInfo(cache_info->file_semaphore);
6053 return(MagickFalse);
6055 if ((cache_info->columns == nexus_info->region.width) &&
6056 (extent <= MagickMaxBufferExtent))
6061 for (y=0; y < (ssize_t) rows; y++)
6063 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6064 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6065 if (count < (MagickOffsetType) length)
6067 p+=(ptrdiff_t) nexus_info->region.width;
6068 offset+=(MagickOffsetType) cache_info->columns;
6070 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6071 (void) ClosePixelCacheOnDisk(cache_info);
6072 UnlockSemaphoreInfo(cache_info->file_semaphore);
6075 case DistributedCache:
6083 LockSemaphoreInfo(cache_info->file_semaphore);
6084 region=nexus_info->region;
6085 if ((cache_info->columns != nexus_info->region.width) ||
6086 (extent > MagickMaxBufferExtent))
6093 for (y=0; y < (ssize_t) rows; y++)
6095 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6096 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6097 if (count != (MagickOffsetType) length)
6099 p+=(ptrdiff_t) nexus_info->region.width;
6102 UnlockSemaphoreInfo(cache_info->file_semaphore);
6108 if (y < (ssize_t) rows)
6110 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6111 cache_info->cache_filename);
6112 return(MagickFalse);
6114 if ((cache_info->debug != MagickFalse) &&
6115 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6116 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6117 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6118 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6119 nexus_info->region.x,(
double) nexus_info->region.y);