43#include "magick/studio.h"
44#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
47#include "magick/cache-private.h"
48#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/colorspace-private.h"
51#include "magick/composite-private.h"
52#include "magick/distribute-cache-private.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/geometry.h"
56#include "magick/list.h"
57#include "magick/log.h"
58#include "magick/magick.h"
59#include "magick/memory_.h"
60#include "magick/memory-private.h"
61#include "magick/nt-base-private.h"
62#include "magick/option.h"
63#include "magick/pixel.h"
64#include "magick/pixel-accessor.h"
65#include "magick/pixel-private.h"
66#include "magick/policy.h"
67#include "magick/quantum.h"
68#include "magick/random_.h"
69#include "magick/registry.h"
70#include "magick/resource_.h"
71#include "magick/semaphore.h"
72#include "magick/splay-tree.h"
73#include "magick/string_.h"
74#include "magick/string-private.h"
75#include "magick/thread-private.h"
76#include "magick/timer-private.h"
77#include "magick/utility.h"
78#include "magick/utility-private.h"
79#if defined(MAGICKCORE_ZLIB_DELEGATE)
86#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
87#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
88 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
103#if defined(__cplusplus) || defined(c_plusplus)
108 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
111static const IndexPacket
112 *GetVirtualIndexesFromCache(
const Image *);
114static const PixelPacket
115 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
116 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
117 *GetVirtualPixelsCache(
const Image *);
119static MagickBooleanType
120 GetOneAuthenticPixelFromCache(Image *,
const ssize_t,
const ssize_t,
121 PixelPacket *,ExceptionInfo *),
122 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
123 const ssize_t,
const ssize_t,PixelPacket *,ExceptionInfo *),
124 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
125 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
126 ReadPixelCacheIndexes(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
128 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
130 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
131 WritePixelCacheIndexes(CacheInfo *,NexusInfo *magick_restrict,
133 WritePixelCachePixels(CacheInfo *,NexusInfo *magick_restrict,
137 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
138 const size_t,ExceptionInfo *),
139 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
140 const size_t,ExceptionInfo *),
141 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
142 const ssize_t,
const ssize_t,
const size_t,
const size_t,
143 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
146#if defined(MAGICKCORE_OPENCL_SUPPORT)
148 CopyOpenCLBuffer(CacheInfo *magick_restrict);
151#if defined(__cplusplus) || defined(c_plusplus)
162 cache_anonymous_memory = (-1);
164#if defined(MAGICKCORE_OPENCL_SUPPORT)
165static inline OpenCLCacheInfo *RelinquishOpenCLCacheInfo(MagickCLEnv clEnv,
166 OpenCLCacheInfo *info)
171 for (i=0; i < (ssize_t) info->event_count; i++)
172 clEnv->library->clReleaseEvent(info->events[i]);
173 info->events=(cl_event *) RelinquishMagickMemory(info->events);
174 DestroySemaphoreInfo(&info->events_semaphore);
175 if (info->buffer != (cl_mem) NULL)
177 clEnv->library->clReleaseMemObject(info->buffer);
178 info->buffer=(cl_mem) NULL;
180 return((OpenCLCacheInfo *) RelinquishMagickMemory(info));
183static void CL_API_CALL RelinquishPixelCachePixelsDelayed(
184 cl_event magick_unused(event),cl_int magick_unused(event_command_exec_status),
199 magick_unreferenced(event);
200 magick_unreferenced(event_command_exec_status);
201 info=(OpenCLCacheInfo *) user_data;
202 clEnv=GetDefaultOpenCLEnv();
203 for (i=(ssize_t)info->event_count-1; i >= 0; i--)
211 status=clEnv->library->clGetEventInfo(info->events[i],
212 CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),&event_status,NULL);
213 if ((status == CL_SUCCESS) && (event_status > CL_COMPLETE))
215 clEnv->library->clSetEventCallback(info->events[i],CL_COMPLETE,
216 &RelinquishPixelCachePixelsDelayed,info);
221 RelinquishMagickResource(MemoryResource,info->length);
222 (void) RelinquishOpenCLCacheInfo(clEnv,info);
223 (void) RelinquishAlignedMemory(pixels);
226static MagickBooleanType RelinquishOpenCLBuffer(
227 CacheInfo *magick_restrict cache_info)
232 assert(cache_info != (CacheInfo *) NULL);
233 if (cache_info->opencl == (OpenCLCacheInfo *) NULL)
235 RelinquishPixelCachePixelsDelayed((cl_event) NULL,0,cache_info->opencl);
239static cl_event *CopyOpenCLEvents(OpenCLCacheInfo *opencl_info,
240 cl_uint *event_count)
248 assert(opencl_info != (OpenCLCacheInfo *) NULL);
249 events=(cl_event *) NULL;
250 LockSemaphoreInfo(opencl_info->events_semaphore);
251 *event_count=opencl_info->event_count;
252 if (*event_count > 0)
254 events=(cl_event *) AcquireQuantumMemory(*event_count,
sizeof(*events));
255 if (events == (cl_event *) NULL)
259 for (i=0; i < opencl_info->event_count; i++)
260 events[i]=opencl_info->events[i];
263 UnlockSemaphoreInfo(opencl_info->events_semaphore);
268#if defined(MAGICKCORE_OPENCL_SUPPORT)
294extern MagickPrivate
void AddOpenCLEvent(
const Image *image,cl_event event)
297 *magick_restrict cache_info;
302 assert(image != (
const Image *) NULL);
303 assert(event != (cl_event) NULL);
304 cache_info=(CacheInfo *)image->cache;
305 assert(cache_info->opencl != (OpenCLCacheInfo *) NULL);
306 clEnv=GetDefaultOpenCLEnv();
307 if (clEnv->library->clRetainEvent(event) != CL_SUCCESS)
309 clEnv->library->clWaitForEvents(1,&event);
312 LockSemaphoreInfo(cache_info->opencl->events_semaphore);
313 if (cache_info->opencl->events == (cl_event *) NULL)
315 cache_info->opencl->events=(cl_event *) AcquireMagickMemory(
sizeof(
316 *cache_info->opencl->events));
317 cache_info->opencl->event_count=1;
320 cache_info->opencl->events=(cl_event *) ResizeQuantumMemory(
321 cache_info->opencl->events,++cache_info->opencl->event_count,
322 sizeof(*cache_info->opencl->events));
323 if (cache_info->opencl->events == (cl_event *) NULL)
324 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
325 cache_info->opencl->events[cache_info->opencl->event_count-1]=event;
326 UnlockSemaphoreInfo(cache_info->opencl->events_semaphore);
352MagickExport Cache AcquirePixelCache(
const size_t number_threads)
355 *magick_restrict cache_info;
360 cache_info=(CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
361 if (cache_info == (CacheInfo *) NULL)
362 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
363 (void) memset(cache_info,0,
sizeof(*cache_info));
364 cache_info->type=UndefinedCache;
365 cache_info->mode=IOMode;
366 cache_info->disk_mode=IOMode;
367 cache_info->colorspace=sRGBColorspace;
368 cache_info->channels=4;
369 cache_info->file=(-1);
370 cache_info->id=GetMagickThreadId();
371 cache_info->number_threads=number_threads;
372 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
373 cache_info->number_threads=GetOpenMPMaximumThreads();
374 if (cache_info->number_threads == 0)
375 cache_info->number_threads=1;
376 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
377 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
378 if (value != (
const char *) NULL)
380 cache_info->synchronize=IsStringTrue(value);
381 value=DestroyString(value);
383 value=GetPolicyValue(
"cache:synchronize");
384 if (value != (
const char *) NULL)
386 cache_info->synchronize=IsStringTrue(value);
387 value=DestroyString(value);
389 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
390 (MagickSizeType) MAGICK_SSIZE_MAX);
391 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
392 (MagickSizeType) MAGICK_SSIZE_MAX);
393 cache_info->semaphore=AllocateSemaphoreInfo();
394 cache_info->reference_count=1;
395 cache_info->file_semaphore=AllocateSemaphoreInfo();
396 cache_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue : MagickFalse;
397 cache_info->signature=MagickCoreSignature;
398 return((Cache ) cache_info);
423MagickExport NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
426 **magick_restrict nexus_info;
431 nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
432 number_threads,
sizeof(*nexus_info)));
433 if (nexus_info == (NexusInfo **) NULL)
434 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
435 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
436 2*
sizeof(**nexus_info));
437 if (*nexus_info == (NexusInfo *) NULL)
438 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
439 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
440 for (i=0; i < (ssize_t) (2*number_threads); i++)
442 nexus_info[i]=(*nexus_info+i);
443 if (i < (ssize_t) number_threads)
444 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
445 nexus_info[i]->signature=MagickCoreSignature;
478MagickExport
const void *AcquirePixelCachePixels(
const Image *image,
479 MagickSizeType *length,ExceptionInfo *exception)
482 *magick_restrict cache_info;
484 assert(image != (
const Image *) NULL);
485 assert(image->signature == MagickCoreSignature);
486 assert(exception != (ExceptionInfo *) NULL);
487 assert(exception->signature == MagickCoreSignature);
488 assert(image->cache != (Cache) NULL);
489 cache_info=(CacheInfo *) image->cache;
490 assert(cache_info->signature == MagickCoreSignature);
493 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
494 return((
const void *) NULL);
495 *length=cache_info->length;
496 return((
const void *) cache_info->pixels);
517MagickExport MagickBooleanType CacheComponentGenesis(
void)
520 cache_semaphore=AllocateSemaphoreInfo();
542MagickExport
void CacheComponentTerminus(
void)
545 ActivateSemaphoreInfo(&cache_semaphore);
547 DestroySemaphoreInfo(&cache_semaphore);
579static MagickBooleanType ClipPixelCacheNexus(Image *image,
580 NexusInfo *nexus_info,ExceptionInfo *exception)
583 *magick_restrict cache_info;
589 *magick_restrict nexus_indexes,
590 *magick_restrict indexes;
596 **magick_restrict clip_nexus;
608 if (IsEventLogging() != MagickFalse)
609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
610 if ((image->clip_mask == (Image *) NULL) ||
611 (image->storage_class == PseudoClass))
613 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
615 cache_info=(CacheInfo *) image->cache;
616 if (cache_info == (Cache) NULL)
618 clip_nexus=AcquirePixelCacheNexus(1);
619 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
620 nexus_info->region.width,nexus_info->region.height,
621 nexus_info->virtual_nexus,exception);
622 indexes=nexus_info->virtual_nexus->indexes;
623 q=nexus_info->pixels;
624 nexus_indexes=nexus_info->indexes;
625 r=GetVirtualPixelCacheNexus(image->clip_mask,MaskVirtualPixelMethod,
626 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
627 nexus_info->region.height,clip_nexus[0],exception);
628 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL) ||
629 (r == (
const PixelPacket *) NULL))
632 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
637 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
642 mask_alpha=QuantumScale*GetPixelIntensity(image,r);
643 if (fabs(mask_alpha) >= MagickEpsilon)
645 SetPixelRed(q,MagickOver_((MagickRealType) p->red,(MagickRealType)
646 GetPixelOpacity(p),(MagickRealType) q->red,(MagickRealType)
647 GetPixelOpacity(q)));
648 SetPixelGreen(q,MagickOver_((MagickRealType) p->green,(MagickRealType)
649 GetPixelOpacity(p),(MagickRealType) q->green,(MagickRealType)
650 GetPixelOpacity(q)));
651 SetPixelBlue(q,MagickOver_((MagickRealType) p->blue,(MagickRealType)
652 GetPixelOpacity(p),(MagickRealType) q->blue,(MagickRealType)
653 GetPixelOpacity(q)));
654 SetPixelOpacity(q,GetPixelOpacity(p));
655 if (cache_info->active_index_channel != MagickFalse)
656 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
664 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
690MagickExport Cache ClonePixelCache(
const Cache cache)
693 *magick_restrict clone_info;
696 *magick_restrict cache_info;
698 assert(cache != NULL);
699 cache_info=(
const CacheInfo *) cache;
700 assert(cache_info->signature == MagickCoreSignature);
701 if (IsEventLogging() != MagickFalse)
702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
703 cache_info->filename);
704 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
705 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
706 return((Cache ) clone_info);
734MagickExport
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
737 *magick_restrict cache_info,
738 *magick_restrict source_info;
740 assert(clone != (Cache) NULL);
741 source_info=(CacheInfo *) clone;
742 assert(source_info->signature == MagickCoreSignature);
743 if (IsEventLogging() != MagickFalse)
744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
745 source_info->filename);
746 assert(cache != (Cache) NULL);
747 cache_info=(CacheInfo *) cache;
748 assert(cache_info->signature == MagickCoreSignature);
749 source_info->methods=cache_info->methods;
781static MagickBooleanType ClonePixelCacheOnDisk(
782 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
802 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
803 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
805 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
806 (lseek(clone_info->file,0,SEEK_SET) < 0))
808 quantum=(size_t) MagickMaxBufferExtent;
809 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
811#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
812 if (cache_info->length < 0x7ffff000)
814 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
815 (
size_t) cache_info->length);
816 if (count == (ssize_t) cache_info->length)
818 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
819 (lseek(clone_info->file,0,SEEK_SET) < 0))
823 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
825 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
826 if (buffer == (
unsigned char *) NULL)
827 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
829 while ((count=read(cache_info->file,buffer,quantum)) > 0)
834 number_bytes=write(clone_info->file,buffer,(
size_t) count);
835 if (number_bytes != count)
837 extent+=(size_t) number_bytes;
839 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
840 if (extent != cache_info->length)
845static inline int GetCacheNumberThreads(
const CacheInfo *source,
846 const CacheInfo *destination,
const size_t chunk,
const int factor)
849 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
851 workload_factor = 64UL << factor;
856 number_threads=(chunk <= workload_factor) ? 1 :
857 (chunk >= (workload_factor << 6)) ? max_threads :
858 1+(chunk-workload_factor)*(max_threads-1)/(((workload_factor << 6))-1);
862 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
863 ((destination->type != MemoryCache) && (destination->type != MapCache)))
864 number_threads=MagickMin(number_threads,4);
865 return((
int) number_threads);
868static MagickBooleanType ClonePixelCacheRepository(
869 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
870 ExceptionInfo *exception)
872#define cache_number_threads(source,destination,chunk,factor) \
873 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
879 **magick_restrict cache_nexus,
880 **magick_restrict clone_nexus;
888 assert(cache_info != (CacheInfo *) NULL);
889 assert(clone_info != (CacheInfo *) NULL);
890 assert(exception != (ExceptionInfo *) NULL);
891 if (cache_info->type == PingCache)
893 if ((cache_info->storage_class == clone_info->storage_class) &&
894 (cache_info->colorspace == clone_info->colorspace) &&
895 (cache_info->channels == clone_info->channels) &&
896 (cache_info->columns == clone_info->columns) &&
897 (cache_info->rows == clone_info->rows) &&
898 (cache_info->active_index_channel == clone_info->active_index_channel))
903 if (((cache_info->type == MemoryCache) ||
904 (cache_info->type == MapCache)) &&
905 ((clone_info->type == MemoryCache) ||
906 (clone_info->type == MapCache)))
908 (void) memcpy(clone_info->pixels,cache_info->pixels,
909 cache_info->columns*cache_info->rows*
sizeof(*cache_info->pixels));
910 if ((cache_info->active_index_channel != MagickFalse) &&
911 (clone_info->active_index_channel != MagickFalse))
912 (void) memcpy(clone_info->indexes,cache_info->indexes,
913 cache_info->columns*cache_info->rows*
914 sizeof(*cache_info->indexes));
917 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
918 return(ClonePixelCacheOnDisk(cache_info,clone_info));
923 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
924 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
925 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
926 sizeof(*cache_info->pixels);
928#if defined(MAGICKCORE_OPENMP_SUPPORT)
929 #pragma omp parallel for schedule(static) shared(status) \
930 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
932 for (y=0; y < (ssize_t) cache_info->rows; y++)
935 id = GetOpenMPThreadId();
940 if (status == MagickFalse)
942 if (y >= (ssize_t) clone_info->rows)
944 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
945 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
946 if (pixels == (PixelPacket *) NULL)
948 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
949 if (status == MagickFalse)
951 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
952 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
953 if (pixels == (PixelPacket *) NULL)
955 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
956 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length);
957 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
959 if ((cache_info->active_index_channel != MagickFalse) &&
960 (clone_info->active_index_channel != MagickFalse))
965 length=(size_t) MagickMin(cache_info->columns,clone_info->columns)*
966 sizeof(*cache_info->indexes);
967#if defined(MAGICKCORE_OPENMP_SUPPORT)
968 #pragma omp parallel for schedule(static) shared(status) \
969 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
971 for (y=0; y < (ssize_t) cache_info->rows; y++)
974 id = GetOpenMPThreadId();
979 if (status == MagickFalse)
981 if (y >= (ssize_t) clone_info->rows)
983 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
984 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
985 if (pixels == (PixelPacket *) NULL)
987 status=ReadPixelCacheIndexes(cache_info,cache_nexus[
id],exception);
988 if (status == MagickFalse)
990 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
991 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
992 if (pixels == (PixelPacket *) NULL)
994 (void) memcpy(clone_nexus[
id]->indexes,cache_nexus[
id]->indexes,length);
995 status=WritePixelCacheIndexes(clone_info,clone_nexus[
id],exception);
998 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
999 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
1000 if (cache_info->debug != MagickFalse)
1003 message[MaxTextExtent];
1005 (void) FormatLocaleString(message,MaxTextExtent,
"%s => %s",
1006 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
1007 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
1008 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1035static void DestroyImagePixelCache(Image *image)
1037 assert(image != (Image *) NULL);
1038 assert(image->signature == MagickCoreSignature);
1039 if (IsEventLogging() != MagickFalse)
1040 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1041 if (image->cache != (
void *) NULL)
1042 image->cache=DestroyPixelCache(image->cache);
1067MagickExport
void DestroyImagePixels(Image *image)
1070 *magick_restrict cache_info;
1072 assert(image != (
const Image *) NULL);
1073 assert(image->signature == MagickCoreSignature);
1074 if (IsEventLogging() != MagickFalse)
1075 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1076 assert(image->cache != (Cache) NULL);
1077 cache_info=(CacheInfo *) image->cache;
1078 assert(cache_info->signature == MagickCoreSignature);
1079 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
1081 cache_info->methods.destroy_pixel_handler(image);
1084 image->cache=DestroyPixelCache(image->cache);
1110static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
1116 if (cache_info->file != -1)
1118 status=close(cache_info->file);
1119 cache_info->file=(-1);
1120 RelinquishMagickResource(FileResource,1);
1122 return(status == -1 ? MagickFalse : MagickTrue);
1125static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1127 switch (cache_info->type)
1131 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1132#if defined(MAGICKCORE_OPENCL_SUPPORT)
1133 if (RelinquishOpenCLBuffer(cache_info) != MagickFalse)
1135 cache_info->pixels=(PixelPacket *) NULL;
1139 if (cache_info->mapped == MagickFalse)
1140 cache_info->pixels=(PixelPacket *) RelinquishAlignedMemory(
1141 cache_info->pixels);
1144 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1145 cache_info->pixels=(PixelPacket *) NULL;
1147 RelinquishMagickResource(MemoryResource,cache_info->length);
1152 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1153 cache_info->pixels=(PixelPacket *) NULL;
1154 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1155 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1156 *cache_info->cache_filename=
'\0';
1157 RelinquishMagickResource(MapResource,cache_info->length);
1162 if (cache_info->file != -1)
1163 (void) ClosePixelCacheOnDisk(cache_info);
1164 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1165 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1166 *cache_info->cache_filename=
'\0';
1167 RelinquishMagickResource(DiskResource,cache_info->length);
1170 case DistributedCache:
1172 *cache_info->cache_filename=
'\0';
1173 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1174 cache_info->server_info);
1180 cache_info->type=UndefinedCache;
1181 cache_info->mapped=MagickFalse;
1182 cache_info->indexes=(IndexPacket *) NULL;
1185MagickExport Cache DestroyPixelCache(Cache cache)
1188 *magick_restrict cache_info;
1190 assert(cache != (Cache) NULL);
1191 cache_info=(CacheInfo *) cache;
1192 assert(cache_info->signature == MagickCoreSignature);
1193 if (IsEventLogging() != MagickFalse)
1194 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1195 cache_info->filename);
1196 LockSemaphoreInfo(cache_info->semaphore);
1197 cache_info->reference_count--;
1198 if (cache_info->reference_count != 0)
1200 UnlockSemaphoreInfo(cache_info->semaphore);
1201 return((Cache) NULL);
1203 UnlockSemaphoreInfo(cache_info->semaphore);
1204 if (cache_info->debug != MagickFalse)
1207 message[MaxTextExtent];
1209 (void) FormatLocaleString(message,MaxTextExtent,
"destroy %s",
1210 cache_info->filename);
1211 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1213 RelinquishPixelCachePixels(cache_info);
1214 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1215 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1216 cache_info->server_info);
1217 if (cache_info->nexus_info != (NexusInfo **) NULL)
1218 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1219 cache_info->number_threads);
1220 if (cache_info->random_info != (RandomInfo *) NULL)
1221 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1223 DestroySemaphoreInfo(&cache_info->file_semaphore);
1225 DestroySemaphoreInfo(&cache_info->semaphore);
1226 cache_info->signature=(~MagickCoreSignature);
1227 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1258static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1260 if (nexus_info->mapped == MagickFalse)
1261 (void) RelinquishAlignedMemory(nexus_info->cache);
1263 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1264 nexus_info->cache=(PixelPacket *) NULL;
1265 nexus_info->pixels=(PixelPacket *) NULL;
1266 nexus_info->indexes=(IndexPacket *) NULL;
1267 nexus_info->length=0;
1268 nexus_info->mapped=MagickFalse;
1271MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1272 const size_t number_threads)
1277 assert(nexus_info != (NexusInfo **) NULL);
1278 for (i=0; i < (ssize_t) (2*number_threads); i++)
1280 if (nexus_info[i]->cache != (PixelPacket *) NULL)
1281 RelinquishCacheNexusPixels(nexus_info[i]);
1282 nexus_info[i]->signature=(~MagickCoreSignature);
1284 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1285 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1312static IndexPacket *GetAuthenticIndexesFromCache(
const Image *image)
1315 *magick_restrict cache_info;
1318 id = GetOpenMPThreadId();
1320 assert(image != (
const Image *) NULL);
1321 assert(image->signature == MagickCoreSignature);
1322 assert(image->cache != (Cache) NULL);
1323 cache_info=(CacheInfo *) image->cache;
1324 assert(cache_info->signature == MagickCoreSignature);
1325 assert(
id < (
int) cache_info->number_threads);
1326 return(cache_info->nexus_info[
id]->indexes);
1354MagickExport IndexPacket *GetAuthenticIndexQueue(
const Image *image)
1357 *magick_restrict cache_info;
1360 id = GetOpenMPThreadId();
1362 assert(image != (
const Image *) NULL);
1363 assert(image->signature == MagickCoreSignature);
1364 assert(image->cache != (Cache) NULL);
1365 cache_info=(CacheInfo *) image->cache;
1366 assert(cache_info->signature == MagickCoreSignature);
1367 if (cache_info->methods.get_authentic_indexes_from_handler !=
1368 (GetAuthenticIndexesFromHandler) NULL)
1369 return(cache_info->methods.get_authentic_indexes_from_handler(image));
1370 assert(
id < (
int) cache_info->number_threads);
1371 return(cache_info->nexus_info[
id]->indexes);
1374#if defined(MAGICKCORE_OPENCL_SUPPORT)
1398MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1399 ExceptionInfo *exception)
1402 *magick_restrict cache_info;
1413 assert(image != (
const Image *) NULL);
1414 cache_info=(CacheInfo *)image->cache;
1415 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1417 SyncImagePixelCache((Image *) image,exception);
1418 cache_info=(CacheInfo *)image->cache;
1420 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1421 return((cl_mem) NULL);
1422 LockSemaphoreInfo(cache_info->semaphore);
1423 clEnv=GetDefaultOpenCLEnv();
1424 if (cache_info->opencl == (OpenCLCacheInfo *) NULL)
1426 assert(cache_info->pixels != NULL);
1427 context=GetOpenCLContext(clEnv);
1428 cache_info->opencl=(OpenCLCacheInfo *) AcquireCriticalMemory(
1429 sizeof(*cache_info->opencl));
1430 (void) memset(cache_info->opencl,0,
sizeof(*cache_info->opencl));
1431 cache_info->opencl->events_semaphore=AllocateSemaphoreInfo();
1432 cache_info->opencl->length=cache_info->length;
1433 cache_info->opencl->pixels=cache_info->pixels;
1434 cache_info->opencl->buffer=clEnv->library->clCreateBuffer(context,
1435 CL_MEM_USE_HOST_PTR,cache_info->length,cache_info->pixels,&status);
1436 if (status != CL_SUCCESS)
1437 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
1439 if (cache_info->opencl != (OpenCLCacheInfo *) NULL)
1440 clEnv->library->clRetainMemObject(cache_info->opencl->buffer);
1441 UnlockSemaphoreInfo(cache_info->semaphore);
1442 if (cache_info->opencl == (OpenCLCacheInfo *) NULL)
1443 return((cl_mem) NULL);
1444 return(cache_info->opencl->buffer);
1483MagickExport PixelPacket *GetAuthenticPixelCacheNexus(Image *image,
1484 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
1485 NexusInfo *nexus_info,ExceptionInfo *exception)
1488 *magick_restrict cache_info;
1491 *magick_restrict pixels;
1496 assert(image != (Image *) NULL);
1497 assert(image->signature == MagickCoreSignature);
1498 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1499 nexus_info,exception);
1500 if (pixels == (PixelPacket *) NULL)
1501 return((PixelPacket *) NULL);
1502 cache_info=(CacheInfo *) image->cache;
1503 assert(cache_info->signature == MagickCoreSignature);
1504 if (nexus_info->authentic_pixel_cache != MagickFalse)
1506 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1507 return((PixelPacket *) NULL);
1508 if (cache_info->active_index_channel != MagickFalse)
1509 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
1510 return((PixelPacket *) NULL);
1537static PixelPacket *GetAuthenticPixelsFromCache(
const Image *image)
1540 *magick_restrict cache_info;
1543 id = GetOpenMPThreadId();
1545 assert(image != (
const Image *) NULL);
1546 assert(image->signature == MagickCoreSignature);
1547 assert(image->cache != (Cache) NULL);
1548 cache_info=(CacheInfo *) image->cache;
1549 assert(cache_info->signature == MagickCoreSignature);
1550 assert(
id < (
int) cache_info->number_threads);
1551 return(cache_info->nexus_info[
id]->pixels);
1577MagickExport PixelPacket *GetAuthenticPixelQueue(
const Image *image)
1580 *magick_restrict cache_info;
1583 id = GetOpenMPThreadId();
1585 assert(image != (
const Image *) NULL);
1586 assert(image->signature == MagickCoreSignature);
1587 assert(image->cache != (Cache) NULL);
1588 cache_info=(CacheInfo *) image->cache;
1589 assert(cache_info->signature == MagickCoreSignature);
1590 if (cache_info->methods.get_authentic_pixels_from_handler !=
1591 (GetAuthenticPixelsFromHandler) NULL)
1592 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1593 assert(
id < (
int) cache_info->number_threads);
1594 return(cache_info->nexus_info[
id]->pixels);
1643MagickExport PixelPacket *GetAuthenticPixels(Image *image,
const ssize_t x,
1644 const ssize_t y,
const size_t columns,
const size_t rows,
1645 ExceptionInfo *exception)
1648 *magick_restrict cache_info;
1651 id = GetOpenMPThreadId();
1653 assert(image != (Image *) NULL);
1654 assert(image->signature == MagickCoreSignature);
1655 assert(image->cache != (Cache) NULL);
1656 cache_info=(CacheInfo *) image->cache;
1657 assert(cache_info->signature == MagickCoreSignature);
1658 if (cache_info->methods.get_authentic_pixels_handler !=
1659 (GetAuthenticPixelsHandler) NULL)
1660 return(cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1662 assert(
id < (
int) cache_info->number_threads);
1663 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1664 cache_info->nexus_info[
id],exception));
1698static PixelPacket *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1699 const ssize_t y,
const size_t columns,
const size_t rows,
1700 ExceptionInfo *exception)
1703 *magick_restrict cache_info;
1706 id = GetOpenMPThreadId();
1708 assert(image != (
const Image *) NULL);
1709 assert(image->signature == MagickCoreSignature);
1710 assert(image->cache != (Cache) NULL);
1711 cache_info=(CacheInfo *) image->cache;
1712 if (cache_info == (Cache) NULL)
1713 return((PixelPacket *) NULL);
1714 assert(cache_info->signature == MagickCoreSignature);
1715 assert(
id < (
int) cache_info->number_threads);
1716 return(GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1717 cache_info->nexus_info[
id],exception));
1743MagickExport MagickSizeType GetImageExtent(
const Image *image)
1746 *magick_restrict cache_info;
1749 id = GetOpenMPThreadId();
1751 assert(image != (Image *) NULL);
1752 assert(image->signature == MagickCoreSignature);
1753 if (IsEventLogging() != MagickFalse)
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1755 assert(image->cache != (Cache) NULL);
1756 cache_info=(CacheInfo *) image->cache;
1757 assert(cache_info->signature == MagickCoreSignature);
1758 assert(
id < (
int) cache_info->number_threads);
1759 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1762#if defined(MAGICKCORE_OPENCL_SUPPORT)
1790extern MagickPrivate cl_event *GetOpenCLEvents(
const Image *image,
1791 cl_uint *event_count)
1794 *magick_restrict cache_info;
1799 assert(image != (
const Image *) NULL);
1800 assert(event_count != (cl_uint *) NULL);
1801 cache_info=(CacheInfo *) image->cache;
1803 events=(cl_event *) NULL;
1804 if (cache_info->opencl != (OpenCLCacheInfo *) NULL)
1805 events=CopyOpenCLEvents(cache_info->opencl,event_count);
1840static inline MagickBooleanType ValidatePixelCacheMorphology(
1841 const Image *magick_restrict image)
1844 *magick_restrict cache_info;
1849 cache_info=(CacheInfo *) image->cache;
1850 if ((image->storage_class != cache_info->storage_class) ||
1851 (image->colorspace != cache_info->colorspace) ||
1852 (image->channels != cache_info->channels) ||
1853 (image->columns != cache_info->columns) ||
1854 (image->rows != cache_info->rows) ||
1855 (cache_info->nexus_info == (NexusInfo **) NULL))
1856 return(MagickFalse);
1860static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1861 ExceptionInfo *exception)
1864 *magick_restrict cache_info;
1868 status = MagickTrue;
1870 static MagickSizeType
1871 cpu_throttle = MagickResourceInfinity,
1874 if (IsImageTTLExpired(image) != MagickFalse)
1879 (void) ThrowMagickException(exception,GetMagickModule(),
1880 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1881 return((Cache) NULL);
1883 if (cpu_throttle == MagickResourceInfinity)
1884 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1885 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1886 MagickDelay(cpu_throttle);
1887 LockSemaphoreInfo(image->semaphore);
1888 assert(image->cache != (Cache) NULL);
1889 cache_info=(CacheInfo *) image->cache;
1890#if defined(MAGICKCORE_OPENCL_SUPPORT)
1891 CopyOpenCLBuffer(cache_info);
1893 destroy=MagickFalse;
1894 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1896 LockSemaphoreInfo(cache_info->semaphore);
1897 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1908 clone_image=(*image);
1909 clone_image.semaphore=AllocateSemaphoreInfo();
1910 clone_image.reference_count=1;
1911 clone_image.cache=ClonePixelCache(cache_info);
1912 clone_info=(CacheInfo *) clone_image.cache;
1913 status=OpenPixelCache(&clone_image,IOMode,exception);
1914 if (status == MagickFalse)
1915 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1918 if (clone != MagickFalse)
1919 status=ClonePixelCacheRepository(clone_info,cache_info,
1921 if (status == MagickFalse)
1922 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1926 image->cache=clone_info;
1929 DestroySemaphoreInfo(&clone_image.semaphore);
1931 UnlockSemaphoreInfo(cache_info->semaphore);
1933 if (destroy != MagickFalse)
1934 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1935 if (status != MagickFalse)
1940 if (image->type != UndefinedType)
1941 image->type=UndefinedType;
1942 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1944 status=OpenPixelCache(image,IOMode,exception);
1945 cache_info=(CacheInfo *) image->cache;
1946 if (cache_info->file != -1)
1947 (void) ClosePixelCacheOnDisk(cache_info);
1950 UnlockSemaphoreInfo(image->semaphore);
1951 if (status == MagickFalse)
1952 return((Cache) NULL);
1953 return(image->cache);
1980MagickExport CacheType GetPixelCacheType(
const Image *image)
1982 return(GetImagePixelCacheType(image));
1985MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1988 *magick_restrict cache_info;
1990 assert(image != (Image *) NULL);
1991 assert(image->signature == MagickCoreSignature);
1992 assert(image->cache != (Cache) NULL);
1993 cache_info=(CacheInfo *) image->cache;
1994 assert(cache_info->signature == MagickCoreSignature);
1995 return(cache_info->type);
2028MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
2029 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2032 *magick_restrict cache_info;
2035 *magick_restrict pixels;
2037 assert(image != (Image *) NULL);
2038 assert(image->signature == MagickCoreSignature);
2039 assert(image->cache != (Cache) NULL);
2040 cache_info=(CacheInfo *) image->cache;
2041 assert(cache_info->signature == MagickCoreSignature);
2042 *pixel=image->background_color;
2043 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
2044 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
2045 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2046 if (pixels == (PixelPacket *) NULL)
2047 return(MagickFalse);
2083static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2084 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2087 *magick_restrict cache_info;
2090 id = GetOpenMPThreadId();
2093 *magick_restrict pixels;
2095 assert(image != (
const Image *) NULL);
2096 assert(image->signature == MagickCoreSignature);
2097 assert(image->cache != (Cache) NULL);
2098 cache_info=(CacheInfo *) image->cache;
2099 assert(cache_info->signature == MagickCoreSignature);
2100 *pixel=image->background_color;
2101 assert(
id < (
int) cache_info->number_threads);
2102 pixels=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,
2103 cache_info->nexus_info[
id],exception);
2104 if (pixels == (PixelPacket *) NULL)
2105 return(MagickFalse);
2142MagickExport MagickBooleanType GetOneVirtualMagickPixel(
const Image *image,
2143 const ssize_t x,
const ssize_t y,MagickPixelPacket *pixel,
2144 ExceptionInfo *exception)
2147 *magick_restrict cache_info;
2150 id = GetOpenMPThreadId();
2153 *magick_restrict indexes;
2156 *magick_restrict pixels;
2158 assert(image != (
const Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(image->cache != (Cache) NULL);
2161 cache_info=(CacheInfo *) image->cache;
2162 assert(cache_info->signature == MagickCoreSignature);
2163 assert(
id < (
int) cache_info->number_threads);
2164 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2165 1UL,1UL,cache_info->nexus_info[
id],exception);
2166 GetMagickPixelPacket(image,pixel);
2167 if (pixels == (
const PixelPacket *) NULL)
2168 return(MagickFalse);
2169 indexes=GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]);
2170 SetMagickPixelPacket(image,pixels,indexes,pixel);
2209MagickExport MagickBooleanType GetOneVirtualMethodPixel(
const Image *image,
2210 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2211 PixelPacket *pixel,ExceptionInfo *exception)
2214 *magick_restrict cache_info;
2217 id = GetOpenMPThreadId();
2220 *magick_restrict pixels;
2222 assert(image != (
const Image *) NULL);
2223 assert(image->signature == MagickCoreSignature);
2224 assert(image->cache != (Cache) NULL);
2225 cache_info=(CacheInfo *) image->cache;
2226 assert(cache_info->signature == MagickCoreSignature);
2227 *pixel=image->background_color;
2228 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2229 (GetOneVirtualPixelFromHandler) NULL)
2230 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2231 virtual_pixel_method,x,y,pixel,exception));
2232 assert(
id < (
int) cache_info->number_threads);
2233 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2234 cache_info->nexus_info[
id],exception);
2235 if (pixels == (
const PixelPacket *) NULL)
2236 return(MagickFalse);
2272MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2273 const ssize_t x,
const ssize_t y,PixelPacket *pixel,ExceptionInfo *exception)
2276 *magick_restrict cache_info;
2279 id = GetOpenMPThreadId();
2282 *magick_restrict pixels;
2284 assert(image != (
const Image *) NULL);
2285 assert(image->signature == MagickCoreSignature);
2286 assert(image->cache != (Cache) NULL);
2287 cache_info=(CacheInfo *) image->cache;
2288 assert(cache_info->signature == MagickCoreSignature);
2289 *pixel=image->background_color;
2290 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2291 (GetOneVirtualPixelFromHandler) NULL)
2292 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2293 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2294 assert(
id < (
int) cache_info->number_threads);
2295 pixels=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2296 1UL,1UL,cache_info->nexus_info[
id],exception);
2297 if (pixels == (
const PixelPacket *) NULL)
2298 return(MagickFalse);
2337static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2338 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2339 PixelPacket *pixel,ExceptionInfo *exception)
2342 *magick_restrict cache_info;
2345 id = GetOpenMPThreadId();
2348 *magick_restrict pixels;
2350 assert(image != (
const Image *) NULL);
2351 assert(image->signature == MagickCoreSignature);
2352 assert(image->cache != (Cache) NULL);
2353 cache_info=(CacheInfo *) image->cache;
2354 assert(cache_info->signature == MagickCoreSignature);
2355 assert(
id < (
int) cache_info->number_threads);
2356 *pixel=image->background_color;
2357 pixels=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2358 cache_info->nexus_info[
id],exception);
2359 if (pixels == (
const PixelPacket *) NULL)
2360 return(MagickFalse);
2390MagickExport
size_t GetPixelCacheChannels(
const Cache cache)
2393 *magick_restrict cache_info;
2395 assert(cache != (Cache) NULL);
2396 cache_info=(CacheInfo *) cache;
2397 assert(cache_info->signature == MagickCoreSignature);
2398 if (IsEventLogging() != MagickFalse)
2399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2400 cache_info->filename);
2401 return(cache_info->channels);
2426MagickExport ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2429 *magick_restrict cache_info;
2431 assert(cache != (Cache) NULL);
2432 cache_info=(CacheInfo *) cache;
2433 assert(cache_info->signature == MagickCoreSignature);
2434 if (IsEventLogging() != MagickFalse)
2435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2436 cache_info->filename);
2437 return(cache_info->colorspace);
2463MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2466 *magick_restrict cache_info;
2468 assert(image != (
const Image *) NULL);
2469 assert(image->signature == MagickCoreSignature);
2470 assert(image->cache != (Cache) NULL);
2471 cache_info=(CacheInfo *) image->cache;
2472 assert(cache_info->signature == MagickCoreSignature);
2473 return(cache_info->cache_filename);
2498MagickExport
void GetPixelCacheMethods(CacheMethods *cache_methods)
2500 assert(cache_methods != (CacheMethods *) NULL);
2501 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2502 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2503 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2504 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
2505 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2506 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2507 cache_methods->get_authentic_indexes_from_handler=
2508 GetAuthenticIndexesFromCache;
2509 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2510 cache_methods->get_one_authentic_pixel_from_handler=
2511 GetOneAuthenticPixelFromCache;
2512 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2513 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2514 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2541MagickExport MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2542 NexusInfo *nexus_info)
2545 *magick_restrict cache_info;
2550 assert(cache != NULL);
2551 cache_info=(CacheInfo *) cache;
2552 assert(cache_info->signature == MagickCoreSignature);
2553 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2555 return((MagickSizeType) cache_info->columns*cache_info->rows);
2586MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2587 ExceptionInfo *exception)
2590 *magick_restrict cache_info;
2592 assert(image != (
const Image *) NULL);
2593 assert(image->signature == MagickCoreSignature);
2594 assert(image->cache != (Cache) NULL);
2595 assert(length != (MagickSizeType *) NULL);
2596 assert(exception != (ExceptionInfo *) NULL);
2597 assert(exception->signature == MagickCoreSignature);
2598 cache_info=(CacheInfo *) image->cache;
2599 assert(cache_info->signature == MagickCoreSignature);
2601 *length=cache_info->length;
2602 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2603 return((
void *) NULL);
2604 return((
void *) cache_info->pixels);
2631MagickExport ClassType GetPixelCacheStorageClass(
const Cache cache)
2634 *magick_restrict cache_info;
2636 assert(cache != (Cache) NULL);
2637 cache_info=(CacheInfo *) cache;
2638 assert(cache_info->signature == MagickCoreSignature);
2639 if (IsEventLogging() != MagickFalse)
2640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2641 cache_info->filename);
2642 return(cache_info->storage_class);
2672MagickExport
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2675 assert(image != (Image *) NULL);
2676 assert(image->signature == MagickCoreSignature);
2677 if (IsEventLogging() != MagickFalse)
2678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2679 *width=2048UL/
sizeof(PixelPacket);
2680 if (GetImagePixelCacheType(image) == DiskCache)
2681 *width=8192UL/
sizeof(PixelPacket);
2709MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2712 *magick_restrict cache_info;
2714 assert(image != (Image *) NULL);
2715 assert(image->signature == MagickCoreSignature);
2716 assert(image->cache != (Cache) NULL);
2717 cache_info=(CacheInfo *) image->cache;
2718 assert(cache_info->signature == MagickCoreSignature);
2719 return(cache_info->virtual_pixel_method);
2745static const IndexPacket *GetVirtualIndexesFromCache(
const Image *image)
2748 *magick_restrict cache_info;
2751 id = GetOpenMPThreadId();
2753 assert(image != (
const Image *) NULL);
2754 assert(image->signature == MagickCoreSignature);
2755 assert(image->cache != (Cache) NULL);
2756 cache_info=(CacheInfo *) image->cache;
2757 assert(cache_info->signature == MagickCoreSignature);
2758 assert(
id < (
int) cache_info->number_threads);
2759 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2788MagickExport
const IndexPacket *GetVirtualIndexesFromNexus(
const Cache cache,
2789 NexusInfo *nexus_info)
2792 *magick_restrict cache_info;
2794 assert(cache != (Cache) NULL);
2795 cache_info=(CacheInfo *) cache;
2796 assert(cache_info->signature == MagickCoreSignature);
2797 if (cache_info->storage_class == UndefinedClass)
2798 return((IndexPacket *) NULL);
2799 return(nexus_info->indexes);
2827MagickExport
const IndexPacket *GetVirtualIndexQueue(
const Image *image)
2830 *magick_restrict cache_info;
2833 id = GetOpenMPThreadId();
2835 assert(image != (
const Image *) NULL);
2836 assert(image->signature == MagickCoreSignature);
2837 assert(image->cache != (Cache) NULL);
2838 cache_info=(CacheInfo *) image->cache;
2839 assert(cache_info->signature == MagickCoreSignature);
2840 if (cache_info->methods.get_virtual_indexes_from_handler !=
2841 (GetVirtualIndexesFromHandler) NULL)
2846 indexes=cache_info->methods.get_virtual_indexes_from_handler(image);
2847 if (indexes != (IndexPacket *) NULL)
2850 assert(
id < (
int) cache_info->number_threads);
2851 return(GetVirtualIndexesFromNexus(cache_info,cache_info->nexus_info[
id]));
2894 0, 48, 12, 60, 3, 51, 15, 63,
2895 32, 16, 44, 28, 35, 19, 47, 31,
2896 8, 56, 4, 52, 11, 59, 7, 55,
2897 40, 24, 36, 20, 43, 27, 39, 23,
2898 2, 50, 14, 62, 1, 49, 13, 61,
2899 34, 18, 46, 30, 33, 17, 45, 29,
2900 10, 58, 6, 54, 9, 57, 5, 53,
2901 42, 26, 38, 22, 41, 25, 37, 21
2904static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2909 index=x+DitherMatrix[x & 0x07]-32L;
2912 if (index >= (ssize_t) columns)
2913 return((ssize_t) columns-1L);
2917static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2922 index=y+DitherMatrix[y & 0x07]-32L;
2925 if (index >= (ssize_t) rows)
2926 return((ssize_t) rows-1L);
2930static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2934 if (x >= (ssize_t) columns)
2935 return((ssize_t) (columns-1));
2939static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2943 if (y >= (ssize_t) rows)
2944 return((ssize_t) (rows-1));
2948static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2951 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2952 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2953 return(MagickFalse);
2957static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2959 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2962static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2964 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2967static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2968 const size_t extent)
2973 modulo.quotient=offset;
2977 modulo.quotient=offset/((ssize_t) extent);
2978 modulo.remainder=offset % ((ssize_t) extent);
2980 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2983 modulo.remainder+=((ssize_t) extent);
2988MagickExport
const PixelPacket *GetVirtualPixelCacheNexus(
const Image *image,
2989 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2990 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2991 ExceptionInfo *exception)
2994 *magick_restrict cache_info;
2997 *magick_restrict virtual_indexes;
3004 *magick_restrict indexes;
3014 *magick_restrict virtual_nexus;
3017 *magick_restrict pixels,
3028 assert(image != (
const Image *) NULL);
3029 assert(image->signature == MagickCoreSignature);
3030 assert(image->cache != (Cache) NULL);
3031 cache_info=(CacheInfo *) image->cache;
3032 assert(cache_info->signature == MagickCoreSignature);
3033 if (cache_info->type == UndefinedCache)
3034 return((
const PixelPacket *) NULL);
3035#if defined(MAGICKCORE_OPENCL_SUPPORT)
3036 CopyOpenCLBuffer(cache_info);
3038 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
3039 (image->clip_mask != (Image *) NULL) || (image->mask != (Image *) NULL) ?
3040 MagickTrue : MagickFalse,nexus_info,exception);
3041 if (pixels == (PixelPacket *) NULL)
3042 return((
const PixelPacket *) NULL);
3043 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
3044 return((
const PixelPacket *) NULL);
3045 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
3046 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
3047 return((
const PixelPacket *) NULL);
3048 offset+=nexus_info->region.x;
3049 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
3050 nexus_info->region.width-1L;
3051 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3052 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
3053 if ((x >= 0) && ((x+(ssize_t) columns) <= (ssize_t) cache_info->columns) &&
3054 (y >= 0) && ((y+(ssize_t) rows) <= (ssize_t) cache_info->rows))
3062 if (nexus_info->authentic_pixel_cache != MagickFalse)
3064 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
3065 if (status == MagickFalse)
3066 return((
const PixelPacket *) NULL);
3067 if ((cache_info->storage_class == PseudoClass) ||
3068 (cache_info->colorspace == CMYKColorspace))
3070 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
3071 if (status == MagickFalse)
3072 return((
const PixelPacket *) NULL);
3079 virtual_nexus=nexus_info->virtual_nexus;
3081 indexes=nexus_info->indexes;
3082 switch (virtual_pixel_method)
3084 case BlackVirtualPixelMethod:
3086 SetPixelRed(&virtual_pixel,0);
3087 SetPixelGreen(&virtual_pixel,0);
3088 SetPixelBlue(&virtual_pixel,0);
3089 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3092 case GrayVirtualPixelMethod:
3094 SetPixelRed(&virtual_pixel,QuantumRange/2);
3095 SetPixelGreen(&virtual_pixel,QuantumRange/2);
3096 SetPixelBlue(&virtual_pixel,QuantumRange/2);
3097 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3100 case TransparentVirtualPixelMethod:
3102 SetPixelRed(&virtual_pixel,0);
3103 SetPixelGreen(&virtual_pixel,0);
3104 SetPixelBlue(&virtual_pixel,0);
3105 SetPixelOpacity(&virtual_pixel,TransparentOpacity);
3108 case MaskVirtualPixelMethod:
3109 case WhiteVirtualPixelMethod:
3111 SetPixelRed(&virtual_pixel,QuantumRange);
3112 SetPixelGreen(&virtual_pixel,QuantumRange);
3113 SetPixelBlue(&virtual_pixel,QuantumRange);
3114 SetPixelOpacity(&virtual_pixel,OpaqueOpacity);
3119 virtual_pixel=image->background_color;
3123 virtual_index=(IndexPacket) 0;
3124 for (v=0; v < (ssize_t) rows; v++)
3130 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3131 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3132 y_offset=EdgeY(y_offset,cache_info->rows);
3133 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3139 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-x_offset,
3140 (ssize_t) columns-u);
3141 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3142 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3152 length=(MagickSizeType) 1;
3153 switch (virtual_pixel_method)
3155 case BackgroundVirtualPixelMethod:
3156 case ConstantVirtualPixelMethod:
3157 case BlackVirtualPixelMethod:
3158 case GrayVirtualPixelMethod:
3159 case TransparentVirtualPixelMethod:
3160 case MaskVirtualPixelMethod:
3161 case WhiteVirtualPixelMethod:
3164 virtual_indexes=(&virtual_index);
3167 case EdgeVirtualPixelMethod:
3170 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3171 EdgeX(x_offset,cache_info->columns),
3172 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3174 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3178 case RandomVirtualPixelMethod:
3180 if (cache_info->random_info == (RandomInfo *) NULL)
3181 cache_info->random_info=AcquireRandomInfo();
3182 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3183 RandomX(cache_info->random_info,cache_info->columns),
3184 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3185 virtual_nexus,exception);
3186 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3190 case DitherVirtualPixelMethod:
3192 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3193 DitherX(x_offset,cache_info->columns),
3194 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3196 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3200 case TileVirtualPixelMethod:
3202 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3203 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3204 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3205 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3207 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3211 case MirrorVirtualPixelMethod:
3213 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3214 if ((x_modulo.quotient & 0x01) == 1L)
3215 x_modulo.remainder=(ssize_t) cache_info->columns-
3216 x_modulo.remainder-1L;
3217 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3218 if ((y_modulo.quotient & 0x01) == 1L)
3219 y_modulo.remainder=(ssize_t) cache_info->rows-
3220 y_modulo.remainder-1L;
3221 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3222 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3224 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3228 case CheckerTileVirtualPixelMethod:
3230 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3231 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3232 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3235 virtual_indexes=(&virtual_index);
3238 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3239 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3241 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3245 case HorizontalTileVirtualPixelMethod:
3247 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3250 virtual_indexes=(&virtual_index);
3253 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3254 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3255 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3256 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3258 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3262 case VerticalTileVirtualPixelMethod:
3264 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3267 virtual_indexes=(&virtual_index);
3270 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3271 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3272 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3273 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3275 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3279 case HorizontalTileEdgeVirtualPixelMethod:
3281 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3282 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3283 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3284 virtual_nexus,exception);
3285 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3289 case VerticalTileEdgeVirtualPixelMethod:
3291 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3292 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3293 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3294 virtual_nexus,exception);
3295 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,
3300 if (p == (
const PixelPacket *) NULL)
3303 if ((indexes != (IndexPacket *) NULL) &&
3304 (virtual_indexes != (
const IndexPacket *) NULL))
3305 *indexes++=(*virtual_indexes);
3311 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3312 (
size_t) length,1UL,virtual_nexus,exception);
3313 if (p == (
const PixelPacket *) NULL)
3315 virtual_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus);
3316 (void) memcpy(q,p,(
size_t) length*
sizeof(*p));
3317 q+=(ptrdiff_t) length;
3318 if ((indexes != (IndexPacket *) NULL) &&
3319 (virtual_indexes != (
const IndexPacket *) NULL))
3321 (void) memcpy(indexes,virtual_indexes,(
size_t) length*
3322 sizeof(*virtual_indexes));
3326 if (u < (ssize_t) columns)
3332 if (v < (ssize_t) rows)
3333 return((
const PixelPacket *) NULL);
3371static const PixelPacket *GetVirtualPixelCache(
const Image *image,
3372 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3373 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3376 *magick_restrict cache_info;
3379 id = GetOpenMPThreadId();
3381 assert(image != (
const Image *) NULL);
3382 assert(image->signature == MagickCoreSignature);
3383 assert(image->cache != (Cache) NULL);
3384 cache_info=(CacheInfo *) image->cache;
3385 assert(cache_info->signature == MagickCoreSignature);
3386 assert(
id < (
int) cache_info->number_threads);
3387 return(GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3388 cache_info->nexus_info[
id],exception));
3414MagickExport
const PixelPacket *GetVirtualPixelQueue(
const Image *image)
3417 *magick_restrict cache_info;
3420 id = GetOpenMPThreadId();
3422 assert(image != (
const Image *) NULL);
3423 assert(image->signature == MagickCoreSignature);
3424 assert(image->cache != (Cache) NULL);
3425 cache_info=(CacheInfo *) image->cache;
3426 assert(cache_info->signature == MagickCoreSignature);
3427 if (cache_info->methods.get_virtual_pixels_handler !=
3428 (GetVirtualPixelsHandler) NULL)
3429 return(cache_info->methods.get_virtual_pixels_handler(image));
3430 assert(
id < (
int) cache_info->number_threads);
3431 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3482MagickExport
const PixelPacket *GetVirtualPixels(
const Image *image,
3483 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3484 ExceptionInfo *exception)
3487 *magick_restrict cache_info;
3490 id = GetOpenMPThreadId();
3492 assert(image != (
const Image *) NULL);
3493 assert(image->signature == MagickCoreSignature);
3494 assert(image->cache != (Cache) NULL);
3495 cache_info=(CacheInfo *) image->cache;
3496 assert(cache_info->signature == MagickCoreSignature);
3497 if (cache_info->methods.get_virtual_pixel_handler !=
3498 (GetVirtualPixelHandler) NULL)
3499 return(cache_info->methods.get_virtual_pixel_handler(image,
3500 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3501 assert(
id < (
int) cache_info->number_threads);
3502 return(GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3503 columns,rows,cache_info->nexus_info[
id],exception));
3529static const PixelPacket *GetVirtualPixelsCache(
const Image *image)
3532 *magick_restrict cache_info;
3535 id = GetOpenMPThreadId();
3537 assert(image != (
const Image *) NULL);
3538 assert(image->signature == MagickCoreSignature);
3539 assert(image->cache != (Cache) NULL);
3540 cache_info=(CacheInfo *) image->cache;
3541 assert(cache_info->signature == MagickCoreSignature);
3542 assert(
id < (
int) cache_info->number_threads);
3543 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3572MagickExport
const PixelPacket *GetVirtualPixelsNexus(
const Cache cache,
3573 NexusInfo *nexus_info)
3576 *magick_restrict cache_info;
3578 assert(cache != (Cache) NULL);
3579 cache_info=(CacheInfo *) cache;
3580 assert(cache_info->signature == MagickCoreSignature);
3581 if (cache_info->storage_class == UndefinedClass)
3582 return((PixelPacket *) NULL);
3583 return((
const PixelPacket *) nexus_info->pixels);
3616static inline void ApplyPixelCompositeMask(
const MagickPixelPacket *p,
3617 const MagickRealType alpha,
const MagickPixelPacket *q,
3618 const MagickRealType beta,MagickPixelPacket *composite)
3623 if (fabs((
double) alpha-(
double) TransparentOpacity) < MagickEpsilon)
3628 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3629 gamma=MagickSafeReciprocal(gamma);
3630 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
3631 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
3632 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
3633 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
3634 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
3637static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3638 ExceptionInfo *exception)
3641 *magick_restrict cache_info;
3647 *magick_restrict nexus_indexes,
3648 *magick_restrict indexes;
3658 **magick_restrict mask_nexus;
3670 if (IsEventLogging() != MagickFalse)
3671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3672 if ((image->mask == (Image *) NULL) || (image->storage_class == PseudoClass))
3674 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3676 cache_info=(CacheInfo *) image->cache;
3677 if (cache_info == (Cache) NULL)
3678 return(MagickFalse);
3679 mask_nexus=AcquirePixelCacheNexus(1);
3680 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y, nexus_info->region.width,nexus_info->region.height,
3681 nexus_info->virtual_nexus,exception);
3682 indexes=nexus_info->virtual_nexus->indexes;
3683 q=nexus_info->pixels;
3684 nexus_indexes=nexus_info->indexes;
3685 r=GetVirtualPixelCacheNexus(image->mask,MaskVirtualPixelMethod,
3686 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
3687 nexus_info->region.height,mask_nexus[0],&image->exception);
3688 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL) ||
3689 (r == (
const PixelPacket *) NULL))
3690 return(MagickFalse);
3692 GetMagickPixelPacket(image,&alpha);
3693 GetMagickPixelPacket(image,&beta);
3694 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3699 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3701 SetMagickPixelPacket(image,p,indexes+n,&alpha);
3702 SetMagickPixelPacket(image,q,nexus_indexes+n,&beta);
3703 ApplyPixelCompositeMask(&beta,GetPixelIntensity(image,r),&alpha,
3704 alpha.opacity,&beta);
3705 SetPixelRed(q,ClampToQuantum(beta.red));
3706 SetPixelGreen(q,ClampToQuantum(beta.green));
3707 SetPixelBlue(q,ClampToQuantum(beta.blue));
3708 SetPixelOpacity(q,ClampToQuantum(beta.opacity));
3709 if (cache_info->active_index_channel != MagickFalse)
3710 SetPixelIndex(nexus_indexes+n,GetPixelIndex(indexes+n));
3717 mask_nexus=DestroyPixelCacheNexus(mask_nexus,1);
3752static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3761 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3763 if (*cache_info->cache_filename ==
'\0')
3764 file=AcquireUniqueFileResource(cache_info->cache_filename);
3770 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3775 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3776 O_BINARY | O_EXCL,S_MODE);
3778 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3784 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3787 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3792 return(MagickFalse);
3793 (void) AcquireMagickResource(FileResource,1);
3794 if (cache_info->file != -1)
3795 (void) ClosePixelCacheOnDisk(cache_info);
3796 cache_info->file=file;
3797 cache_info->disk_mode=mode;
3801static inline MagickOffsetType WritePixelCacheRegion(
3802 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3803 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3811#if !defined(MAGICKCORE_HAVE_PWRITE)
3812 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3813 return((MagickOffsetType) -1);
3815 for (i=0; i < (MagickOffsetType) length; i+=count)
3817#if !defined(MAGICKCORE_HAVE_PWRITE)
3818 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3819 (MagickSizeType) i,MagickMaxBufferExtent));
3821 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3822 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3834static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3837 *magick_restrict cache_info;
3842 cache_info=(CacheInfo *) image->cache;
3843 if (cache_info->debug != MagickFalse)
3846 format[MaxTextExtent],
3847 message[MaxTextExtent];
3849 (void) FormatMagickSize(length,MagickFalse,format);
3850 (void) FormatLocaleString(message,MaxTextExtent,
3851 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3852 cache_info->cache_filename,cache_info->file,format);
3853 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3855 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3857 return(MagickFalse);
3858 if ((MagickSizeType) offset < length)
3864 extent=(MagickOffsetType) length-1;
3865 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3868 return(MagickFalse);
3869#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3870 if (cache_info->synchronize != MagickFalse)
3871 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3872 return(MagickFalse);
3875 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3877 return(MagickFalse);
3881static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3882 ExceptionInfo *exception)
3885 *magick_restrict cache_info,
3889 format[MaxTextExtent],
3890 message[MaxTextExtent];
3907 assert(image != (
const Image *) NULL);
3908 assert(image->signature == MagickCoreSignature);
3909 assert(image->cache != (Cache) NULL);
3910 if (IsEventLogging() != MagickFalse)
3911 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3912 if (cache_anonymous_memory < 0)
3920 cache_anonymous_memory=0;
3921 value=GetPolicyValue(
"pixel-cache-memory");
3922 if (value == (
char *) NULL)
3923 value=GetPolicyValue(
"cache:memory-map");
3924 if (LocaleCompare(value,
"anonymous") == 0)
3926#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3927 cache_anonymous_memory=1;
3929 (void) ThrowMagickException(exception,GetMagickModule(),
3930 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3931 "'%s' (policy requires anonymous memory mapping)",image->filename);
3934 value=DestroyString(value);
3936 if ((image->columns == 0) || (image->rows == 0))
3937 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3938 cache_info=(CacheInfo *) image->cache;
3939 assert(cache_info->signature == MagickCoreSignature);
3940 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3941 ((MagickSizeType) image->rows > cache_info->height_limit))
3942 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3944 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3946 length=GetImageListLength(image);
3947 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3948 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3951 source_info=(*cache_info);
3952 source_info.file=(-1);
3953 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,
"%s[%.20g]",
3954 image->filename,(
double) image->scene);
3955 cache_info->storage_class=image->storage_class;
3956 cache_info->colorspace=image->colorspace;
3957 cache_info->rows=image->rows;
3958 cache_info->columns=image->columns;
3959 cache_info->channels=image->channels;
3960 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
3961 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
3962 cache_info->mode=mode;
3963 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3964 packet_size=
sizeof(PixelPacket);
3965 if (cache_info->active_index_channel != MagickFalse)
3966 packet_size+=
sizeof(IndexPacket);
3967 length=number_pixels*packet_size;
3968 columns=(size_t) (length/cache_info->rows/packet_size);
3969 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3970 ((ssize_t) cache_info->rows < 0))
3971 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3973 cache_info->length=length;
3974 if (image->ping != MagickFalse)
3976 cache_info->type=PingCache;
3979 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3980 cache_info->columns*cache_info->rows);
3981 if (cache_info->mode == PersistMode)
3983 length=number_pixels*(
sizeof(PixelPacket)+
sizeof(IndexPacket));
3984 if ((status != MagickFalse) &&
3985 (length == (MagickSizeType) ((
size_t) length)) &&
3986 ((cache_info->type == UndefinedCache) ||
3987 (cache_info->type == MemoryCache)))
3989 status=AcquireMagickResource(MemoryResource,cache_info->length);
3990 if (status != MagickFalse)
3993 if (cache_anonymous_memory <= 0)
3995 cache_info->mapped=MagickFalse;
3996 cache_info->pixels=(PixelPacket *) MagickAssumeAligned(
3997 AcquireAlignedMemory(1,(
size_t) cache_info->length));
4001 cache_info->mapped=MagickTrue;
4002 cache_info->pixels=(PixelPacket *) MapBlob(-1,IOMode,0,(
size_t)
4003 cache_info->length);
4005 if (cache_info->pixels == (PixelPacket *) NULL)
4007 cache_info->mapped=source_info.mapped;
4008 cache_info->pixels=source_info.pixels;
4015 cache_info->colorspace=image->colorspace;
4016 cache_info->type=MemoryCache;
4017 cache_info->indexes=(IndexPacket *) NULL;
4018 if (cache_info->active_index_channel != MagickFalse)
4019 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4021 if ((source_info.storage_class != UndefinedClass) &&
4024 status&=ClonePixelCacheRepository(cache_info,&source_info,
4026 RelinquishPixelCachePixels(&source_info);
4028 if (cache_info->debug != MagickFalse)
4030 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4031 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4033 (void) FormatLocaleString(message,MaxTextExtent,
4034 "open %s (%s %s, %.20gx%.20g %s)",cache_info->filename,
4035 cache_info->mapped != MagickFalse ?
"Anonymous" :
"Heap",
4036 type,(
double) cache_info->columns,(
double) cache_info->rows,
4038 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4041 cache_info->storage_class=image->storage_class;
4044 if ((source_info.storage_class != UndefinedClass) &&
4046 RelinquishPixelCachePixels(&source_info);
4047 cache_info->type=UndefinedCache;
4048 return(MagickFalse);
4054 status=AcquireMagickResource(DiskResource,cache_info->length);
4055 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
4057 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
4065 server_info=AcquireDistributeCacheInfo(exception);
4066 if (server_info != (DistributeCacheInfo *) NULL)
4068 status=OpenDistributePixelCache(server_info,image);
4069 if (status == MagickFalse)
4071 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4072 GetDistributeCacheHostname(server_info));
4073 server_info=DestroyDistributeCacheInfo(server_info);
4081 cache_info->type=DistributedCache;
4082 cache_info->storage_class=image->storage_class;
4083 cache_info->colorspace=image->colorspace;
4084 cache_info->server_info=server_info;
4085 (void) FormatLocaleString(cache_info->cache_filename,
4086 MaxTextExtent,
"%s:%d",GetDistributeCacheHostname(
4087 (DistributeCacheInfo *) cache_info->server_info),
4088 GetDistributeCachePort((DistributeCacheInfo *)
4089 cache_info->server_info));
4090 if ((source_info.storage_class != UndefinedClass) &&
4093 status=ClonePixelCacheRepository(cache_info,&source_info,
4095 RelinquishPixelCachePixels(&source_info);
4097 if (cache_info->debug != MagickFalse)
4099 (void) FormatMagickSize(cache_info->length,MagickFalse,
4101 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4103 (void) FormatLocaleString(message,MaxTextExtent,
4104 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4105 cache_info->cache_filename,GetDistributeCacheFile(
4106 (DistributeCacheInfo *) cache_info->server_info),type,
4107 (
double) cache_info->columns,(
double) cache_info->rows,
4109 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4114 if ((source_info.storage_class != UndefinedClass) &&
4116 RelinquishPixelCachePixels(&source_info);
4117 cache_info->type=UndefinedCache;
4118 return(MagickFalse);
4123 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4124 RelinquishPixelCachePixels(&source_info);
4125 cache_info->type=UndefinedCache;
4126 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4127 "CacheResourcesExhausted",
"`%s'",image->filename);
4128 return(MagickFalse);
4133 if (status == MagickFalse)
4135 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4136 RelinquishPixelCachePixels(&source_info);
4137 cache_info->type=UndefinedCache;
4138 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4139 "CacheResourcesExhausted",
"`%s'",image->filename);
4140 return(MagickFalse);
4142 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4143 (cache_info->mode != PersistMode))
4145 (void) ClosePixelCacheOnDisk(cache_info);
4146 *cache_info->cache_filename=
'\0';
4148 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4150 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4151 RelinquishPixelCachePixels(&source_info);
4152 cache_info->type=UndefinedCache;
4153 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4155 return(MagickFalse);
4157 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4158 cache_info->length);
4159 if (status == MagickFalse)
4161 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4162 RelinquishPixelCachePixels(&source_info);
4163 cache_info->type=UndefinedCache;
4164 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4166 return(MagickFalse);
4168 cache_info->storage_class=image->storage_class;
4169 cache_info->colorspace=image->colorspace;
4170 cache_info->type=DiskCache;
4171 length=number_pixels*(
sizeof(PixelPacket)+
sizeof(IndexPacket));
4172 if (length == (MagickSizeType) ((
size_t) length))
4174 status=AcquireMagickResource(MapResource,cache_info->length);
4175 if (status != MagickFalse)
4177 cache_info->pixels=(PixelPacket *) MapBlob(cache_info->file,mode,
4178 cache_info->offset,(
size_t) cache_info->length);
4179 if (cache_info->pixels == (PixelPacket *) NULL)
4181 cache_info->mapped=source_info.mapped;
4182 cache_info->pixels=source_info.pixels;
4183 RelinquishMagickResource(MapResource,cache_info->length);
4190 (void) ClosePixelCacheOnDisk(cache_info);
4191 cache_info->type=MapCache;
4192 cache_info->mapped=MagickTrue;
4193 cache_info->indexes=(IndexPacket *) NULL;
4194 if (cache_info->active_index_channel != MagickFalse)
4195 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
4197 if ((source_info.storage_class != UndefinedClass) &&
4200 status=ClonePixelCacheRepository(cache_info,&source_info,
4202 RelinquishPixelCachePixels(&source_info);
4204 if (cache_info->debug != MagickFalse)
4206 (void) FormatMagickSize(cache_info->length,MagickTrue,format);
4207 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4209 (void) FormatLocaleString(message,MaxTextExtent,
4210 "open %s (%s[%d], %s, %.20gx%.20g %s)",
4211 cache_info->filename,cache_info->cache_filename,
4212 cache_info->file,type,(
double) cache_info->columns,
4213 (
double) cache_info->rows,format);
4214 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4219 if ((source_info.storage_class != UndefinedClass) &&
4221 RelinquishPixelCachePixels(&source_info);
4222 cache_info->type=UndefinedCache;
4223 return(MagickFalse);
4230 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4232 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4233 RelinquishPixelCachePixels(&source_info);
4235 if (cache_info->debug != MagickFalse)
4237 (void) FormatMagickSize(cache_info->length,MagickFalse,format);
4238 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4240 (void) FormatLocaleString(message,MaxTextExtent,
4241 "open %s (%s[%d], %s, %.20gx%.20g %s)",cache_info->filename,
4242 cache_info->cache_filename,cache_info->file,type,(
double)
4243 cache_info->columns,(
double) cache_info->rows,format);
4244 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4248 cache_info->type=UndefinedCache;
4249 return(MagickFalse);
4291MagickExport MagickBooleanType PersistPixelCache(Image *image,
4292 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4293 ExceptionInfo *exception)
4296 *magick_restrict cache_info,
4297 *magick_restrict clone_info;
4305 assert(image != (Image *) NULL);
4306 assert(image->signature == MagickCoreSignature);
4307 if (IsEventLogging() != MagickFalse)
4308 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4309 assert(image->cache != (
void *) NULL);
4310 assert(filename != (
const char *) NULL);
4311 assert(offset != (MagickOffsetType *) NULL);
4312 page_size=GetMagickPageSize();
4313 cache_info=(CacheInfo *) image->cache;
4314 assert(cache_info->signature == MagickCoreSignature);
4315#if defined(MAGICKCORE_OPENCL_SUPPORT)
4316 CopyOpenCLBuffer(cache_info);
4318 if (attach != MagickFalse)
4323 if (cache_info->debug != MagickFalse)
4324 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4325 "attach persistent cache");
4326 (void) CopyMagickString(cache_info->cache_filename,filename,
4328 cache_info->type=MapCache;
4329 cache_info->offset=(*offset);
4330 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4331 return(MagickFalse);
4332 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4333 ((MagickOffsetType) cache_info->length % page_size));
4339 status=AcquireMagickResource(DiskResource,cache_info->length);
4340 if (status == MagickFalse)
4342 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4343 "CacheResourcesExhausted",
"`%s'",image->filename);
4344 return(MagickFalse);
4346 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4347 clone_info->type=DiskCache;
4348 (void) CopyMagickString(clone_info->cache_filename,filename,MaxTextExtent);
4349 clone_info->file=(-1);
4350 clone_info->storage_class=cache_info->storage_class;
4351 clone_info->colorspace=cache_info->colorspace;
4352 clone_info->columns=cache_info->columns;
4353 clone_info->rows=cache_info->rows;
4354 clone_info->active_index_channel=cache_info->active_index_channel;
4355 clone_info->mode=PersistMode;
4356 clone_info->length=cache_info->length;
4357 clone_info->channels=cache_info->channels;
4358 clone_info->offset=(*offset);
4359 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4360 if (status != MagickFalse)
4361 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4362 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4363 ((MagickOffsetType) cache_info->length % page_size));
4364 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4406MagickExport PixelPacket *QueueAuthenticPixel(Image *image,
const ssize_t x,
4407 const ssize_t y,
const size_t columns,
const size_t rows,
4408 const MagickBooleanType clone,NexusInfo *nexus_info,
4409 ExceptionInfo *exception)
4411 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,clone,nexus_info,
4415MagickExport PixelPacket *QueueAuthenticPixelCacheNexus(Image *image,
4416 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4417 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4420 *magick_restrict cache_info;
4429 *magick_restrict pixels;
4434 assert(image != (
const Image *) NULL);
4435 assert(image->signature == MagickCoreSignature);
4436 assert(image->cache != (Cache) NULL);
4437 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4438 if (cache_info == (Cache) NULL)
4439 return((PixelPacket *) NULL);
4440 assert(cache_info->signature == MagickCoreSignature);
4441 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4442 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4443 (y >= (ssize_t) cache_info->rows))
4445 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4446 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4447 return((PixelPacket *) NULL);
4449 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4450 return((PixelPacket *) NULL);
4451 offset=y*(MagickOffsetType) cache_info->columns+x;
4453 return((PixelPacket *) NULL);
4454 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4455 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4456 (MagickOffsetType) columns-1;
4457 if ((MagickSizeType) offset >= number_pixels)
4458 return((PixelPacket *) NULL);
4462 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4463 (image->clip_mask != (Image *) NULL) || (image->mask != (Image *) NULL) ?
4464 MagickTrue : MagickFalse,nexus_info,exception);
4501static PixelPacket *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4502 const ssize_t y,
const size_t columns,
const size_t rows,
4503 ExceptionInfo *exception)
4506 *magick_restrict cache_info;
4509 id = GetOpenMPThreadId();
4511 assert(image != (
const Image *) NULL);
4512 assert(image->signature == MagickCoreSignature);
4513 assert(image->cache != (Cache) NULL);
4514 cache_info=(CacheInfo *) image->cache;
4515 assert(cache_info->signature == MagickCoreSignature);
4516 assert(
id < (
int) cache_info->number_threads);
4517 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4518 cache_info->nexus_info[
id],exception));
4577MagickExport PixelPacket *QueueAuthenticPixels(Image *image,
const ssize_t x,
4578 const ssize_t y,
const size_t columns,
const size_t rows,
4579 ExceptionInfo *exception)
4582 *magick_restrict cache_info;
4585 id = GetOpenMPThreadId();
4587 assert(image != (Image *) NULL);
4588 assert(image->signature == MagickCoreSignature);
4589 assert(image->cache != (Cache) NULL);
4590 cache_info=(CacheInfo *) image->cache;
4591 assert(cache_info->signature == MagickCoreSignature);
4592 if (cache_info->methods.queue_authentic_pixels_handler !=
4593 (QueueAuthenticPixelsHandler) NULL)
4594 return(cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
4596 assert(
id < (
int) cache_info->number_threads);
4597 return(QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4598 cache_info->nexus_info[
id],exception));
4630static inline MagickOffsetType ReadPixelCacheRegion(
4631 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4632 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4640#if !defined(MAGICKCORE_HAVE_PREAD)
4641 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4642 return((MagickOffsetType) -1);
4644 for (i=0; i < (MagickOffsetType) length; i+=count)
4646#if !defined(MAGICKCORE_HAVE_PREAD)
4647 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4648 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4650 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4651 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4663static MagickBooleanType ReadPixelCacheIndexes(
4664 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4665 ExceptionInfo *exception)
4684 if (cache_info->active_index_channel == MagickFalse)
4685 return(MagickFalse);
4686 if (nexus_info->authentic_pixel_cache != MagickFalse)
4688 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4689 return(MagickFalse);
4690 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4691 nexus_info->region.x;
4692 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
4693 rows=nexus_info->region.height;
4695 q=nexus_info->indexes;
4697 switch (cache_info->type)
4708 if ((cache_info->columns == nexus_info->region.width) &&
4709 (extent == (MagickSizeType) ((
size_t) extent)))
4714 p=cache_info->indexes+offset;
4715 for (y=0; y < (ssize_t) rows; y++)
4717 (void) memcpy(q,p,(
size_t) length);
4718 p+=(ptrdiff_t) cache_info->columns;
4719 q+=(ptrdiff_t) nexus_info->region.width;
4728 LockSemaphoreInfo(cache_info->file_semaphore);
4729 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4731 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4732 cache_info->cache_filename);
4733 UnlockSemaphoreInfo(cache_info->file_semaphore);
4734 return(MagickFalse);
4736 if ((cache_info->columns == nexus_info->region.width) &&
4737 (extent <= MagickMaxBufferExtent))
4742 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4743 for (y=0; y < (ssize_t) rows; y++)
4745 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4746 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(PixelPacket)+
4747 offset*(MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4748 if (count < (MagickOffsetType) length)
4750 offset+=(MagickOffsetType) cache_info->columns;
4751 q+=(ptrdiff_t) nexus_info->region.width;
4753 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4754 (void) ClosePixelCacheOnDisk(cache_info);
4755 UnlockSemaphoreInfo(cache_info->file_semaphore);
4758 case DistributedCache:
4766 LockSemaphoreInfo(cache_info->file_semaphore);
4767 region=nexus_info->region;
4768 if ((cache_info->columns != nexus_info->region.width) ||
4769 (extent > MagickMaxBufferExtent))
4776 for (y=0; y < (ssize_t) rows; y++)
4778 count=ReadDistributePixelCacheIndexes((DistributeCacheInfo *)
4779 cache_info->server_info,®ion,length,(
unsigned char *) q);
4780 if (count != (MagickOffsetType) length)
4782 q+=(ptrdiff_t) nexus_info->region.width;
4785 UnlockSemaphoreInfo(cache_info->file_semaphore);
4791 if (y < (ssize_t) rows)
4793 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4794 cache_info->cache_filename);
4795 return(MagickFalse);
4797 if ((cache_info->debug != MagickFalse) &&
4798 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4799 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4800 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4801 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4802 nexus_info->region.x,(
double) nexus_info->region.y);
4834static MagickBooleanType ReadPixelCachePixels(
4835 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4836 ExceptionInfo *exception)
4855 if (nexus_info->authentic_pixel_cache != MagickFalse)
4857 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4858 return(MagickFalse);
4859 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4860 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4861 return(MagickFalse);
4862 offset+=nexus_info->region.x;
4863 length=(MagickSizeType) nexus_info->region.width*
sizeof(PixelPacket);
4864 if ((length/
sizeof(PixelPacket)) != nexus_info->region.width)
4865 return(MagickFalse);
4866 rows=nexus_info->region.height;
4868 if ((extent == 0) || ((extent/length) != rows))
4869 return(MagickFalse);
4870 q=nexus_info->pixels;
4872 switch (cache_info->type)
4883 if ((cache_info->columns == nexus_info->region.width) &&
4884 (extent == (MagickSizeType) ((
size_t) extent)))
4889 p=cache_info->pixels+offset;
4890 for (y=0; y < (ssize_t) rows; y++)
4892 (void) memcpy(q,p,(
size_t) length);
4893 p+=(ptrdiff_t) cache_info->columns;
4894 q+=(ptrdiff_t) nexus_info->region.width;
4903 LockSemaphoreInfo(cache_info->file_semaphore);
4904 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4906 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4907 cache_info->cache_filename);
4908 UnlockSemaphoreInfo(cache_info->file_semaphore);
4909 return(MagickFalse);
4911 if ((cache_info->columns == nexus_info->region.width) &&
4912 (extent <= MagickMaxBufferExtent))
4917 for (y=0; y < (ssize_t) rows; y++)
4919 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4920 (MagickOffsetType)
sizeof(*q),length,(
unsigned char *) q);
4921 if (count < (MagickOffsetType) length)
4923 offset+=(MagickOffsetType) cache_info->columns;
4924 q+=(ptrdiff_t) nexus_info->region.width;
4926 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4927 (void) ClosePixelCacheOnDisk(cache_info);
4928 UnlockSemaphoreInfo(cache_info->file_semaphore);
4931 case DistributedCache:
4939 LockSemaphoreInfo(cache_info->file_semaphore);
4940 region=nexus_info->region;
4941 if ((cache_info->columns != nexus_info->region.width) ||
4942 (extent > MagickMaxBufferExtent))
4949 for (y=0; y < (ssize_t) rows; y++)
4951 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4952 cache_info->server_info,®ion,length,(
unsigned char *) q);
4953 if (count != (MagickOffsetType) length)
4955 q+=(ptrdiff_t) nexus_info->region.width;
4958 UnlockSemaphoreInfo(cache_info->file_semaphore);
4964 if (y < (ssize_t) rows)
4966 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4967 cache_info->cache_filename);
4968 return(MagickFalse);
4970 if ((cache_info->debug != MagickFalse) &&
4971 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4972 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4973 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4974 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4975 nexus_info->region.x,(
double) nexus_info->region.y);
5002MagickExport Cache ReferencePixelCache(Cache cache)
5005 *magick_restrict cache_info;
5007 assert(cache != (Cache *) NULL);
5008 cache_info=(CacheInfo *) cache;
5009 assert(cache_info->signature == MagickCoreSignature);
5010 LockSemaphoreInfo(cache_info->semaphore);
5011 cache_info->reference_count++;
5012 UnlockSemaphoreInfo(cache_info->semaphore);
5034MagickPrivate
void ResetCacheAnonymousMemory(
void)
5036 cache_anonymous_memory=0;
5063MagickExport
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5066 *magick_restrict cache_info;
5068 GetOneAuthenticPixelFromHandler
5069 get_one_authentic_pixel_from_handler;
5071 GetOneVirtualPixelFromHandler
5072 get_one_virtual_pixel_from_handler;
5077 assert(cache != (Cache) NULL);
5078 assert(cache_methods != (CacheMethods *) NULL);
5079 cache_info=(CacheInfo *) cache;
5080 assert(cache_info->signature == MagickCoreSignature);
5081 if (IsEventLogging() != MagickFalse)
5082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5083 cache_info->filename);
5084 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5085 cache_info->methods.get_virtual_pixel_handler=
5086 cache_methods->get_virtual_pixel_handler;
5087 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5088 cache_info->methods.destroy_pixel_handler=
5089 cache_methods->destroy_pixel_handler;
5090 if (cache_methods->get_virtual_indexes_from_handler !=
5091 (GetVirtualIndexesFromHandler) NULL)
5092 cache_info->methods.get_virtual_indexes_from_handler=
5093 cache_methods->get_virtual_indexes_from_handler;
5094 if (cache_methods->get_authentic_pixels_handler !=
5095 (GetAuthenticPixelsHandler) NULL)
5096 cache_info->methods.get_authentic_pixels_handler=
5097 cache_methods->get_authentic_pixels_handler;
5098 if (cache_methods->queue_authentic_pixels_handler !=
5099 (QueueAuthenticPixelsHandler) NULL)
5100 cache_info->methods.queue_authentic_pixels_handler=
5101 cache_methods->queue_authentic_pixels_handler;
5102 if (cache_methods->sync_authentic_pixels_handler !=
5103 (SyncAuthenticPixelsHandler) NULL)
5104 cache_info->methods.sync_authentic_pixels_handler=
5105 cache_methods->sync_authentic_pixels_handler;
5106 if (cache_methods->get_authentic_pixels_from_handler !=
5107 (GetAuthenticPixelsFromHandler) NULL)
5108 cache_info->methods.get_authentic_pixels_from_handler=
5109 cache_methods->get_authentic_pixels_from_handler;
5110 if (cache_methods->get_authentic_indexes_from_handler !=
5111 (GetAuthenticIndexesFromHandler) NULL)
5112 cache_info->methods.get_authentic_indexes_from_handler=
5113 cache_methods->get_authentic_indexes_from_handler;
5114 get_one_virtual_pixel_from_handler=
5115 cache_info->methods.get_one_virtual_pixel_from_handler;
5116 if (get_one_virtual_pixel_from_handler !=
5117 (GetOneVirtualPixelFromHandler) NULL)
5118 cache_info->methods.get_one_virtual_pixel_from_handler=
5119 cache_methods->get_one_virtual_pixel_from_handler;
5120 get_one_authentic_pixel_from_handler=
5121 cache_methods->get_one_authentic_pixel_from_handler;
5122 if (get_one_authentic_pixel_from_handler !=
5123 (GetOneAuthenticPixelFromHandler) NULL)
5124 cache_info->methods.get_one_authentic_pixel_from_handler=
5125 cache_methods->get_one_authentic_pixel_from_handler;
5166static inline MagickBooleanType AcquireCacheNexusPixels(
5167 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5168 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5170 if (length != (MagickSizeType) ((
size_t) length))
5172 (void) ThrowMagickException(exception,GetMagickModule(),
5173 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5174 cache_info->filename);
5175 return(MagickFalse);
5177 nexus_info->length=0;
5178 nexus_info->mapped=MagickFalse;
5179 if (cache_anonymous_memory <= 0)
5181 nexus_info->cache=(PixelPacket *) MagickAssumeAligned(
5182 AcquireAlignedMemory(1,(
size_t) length));
5183 if (nexus_info->cache != (PixelPacket *) NULL)
5184 (void) memset(nexus_info->cache,0,(
size_t) length);
5188 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(
size_t) length);
5189 if (nexus_info->cache != (PixelPacket *) NULL)
5190 nexus_info->mapped=MagickTrue;
5192 if (nexus_info->cache == (PixelPacket *) NULL)
5194 (void) ThrowMagickException(exception,GetMagickModule(),
5195 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5196 cache_info->filename);
5197 return(MagickFalse);
5199 nexus_info->length=length;
5203static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5206 if (nexus_info->length < CACHE_LINE_SIZE)
5208 if (mode == ReadMode)
5210 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5214 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5217static inline MagickBooleanType ValidatePixelOffset(
const ssize_t x,
5220 if ((x >= 0) && (x >= ((ssize_t) (MAGICK_SSIZE_MAX-5*a))))
5221 return(MagickFalse);
5222 if (x <= ((ssize_t) (MAGICK_SSIZE_MIN+5*(MagickOffsetType) a)))
5223 return(MagickFalse);
5227static PixelPacket *SetPixelCacheNexusPixels(
5228 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5229 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5230 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5231 ExceptionInfo *exception)
5240 assert(cache_info != (
const CacheInfo *) NULL);
5241 assert(cache_info->signature == MagickCoreSignature);
5242 if (cache_info->type == UndefinedCache)
5243 return((PixelPacket *) NULL);
5244 assert(nexus_info->signature == MagickCoreSignature);
5245 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5246 if ((width == 0) || (height == 0))
5248 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5249 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5250 return((PixelPacket *) NULL);
5252 if (((MagickSizeType) width > cache_info->width_limit) ||
5253 ((MagickSizeType) height > cache_info->height_limit))
5255 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5256 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5257 return((PixelPacket *) NULL);
5259 if ((ValidatePixelOffset(x,width) == MagickFalse) ||
5260 (ValidatePixelOffset(y,height) == MagickFalse))
5262 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5263 "InvalidPixel",
"`%s'",cache_info->filename);
5264 return((PixelPacket *) NULL);
5266 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5267 (buffered == MagickFalse))
5269 if (((x >= 0) && (y >= 0) &&
5270 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5271 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5272 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5280 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5281 return((PixelPacket *) NULL);
5282 offset=y*(MagickOffsetType) cache_info->columns+x;
5283 nexus_info->pixels=cache_info->pixels+offset;
5284 nexus_info->indexes=(IndexPacket *) NULL;
5285 if (cache_info->active_index_channel != MagickFalse)
5286 nexus_info->indexes=cache_info->indexes+offset;
5287 nexus_info->region.width=width;
5288 nexus_info->region.height=height;
5289 nexus_info->region.x=x;
5290 nexus_info->region.y=y;
5291 nexus_info->authentic_pixel_cache=MagickTrue;
5292 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5293 return(nexus_info->pixels);
5299 number_pixels=(MagickSizeType) width*height;
5300 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5301 cache_info->rows))*
sizeof(PixelPacket);
5302 if (cache_info->active_index_channel != MagickFalse)
5303 length+=number_pixels*
sizeof(IndexPacket);
5305 if (nexus_info->cache == (PixelPacket *) NULL)
5306 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5308 if (nexus_info->length < length)
5310 RelinquishCacheNexusPixels(nexus_info);
5311 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5313 if (status == MagickFalse)
5315 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5316 return((PixelPacket *) NULL);
5318 nexus_info->pixels=nexus_info->cache;
5319 nexus_info->indexes=(IndexPacket *) NULL;
5320 if (cache_info->active_index_channel != MagickFalse)
5321 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
5322 nexus_info->region.width=width;
5323 nexus_info->region.height=height;
5324 nexus_info->region.x=x;
5325 nexus_info->region.y=y;
5326 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5327 MagickTrue : MagickFalse;
5328 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5329 return(nexus_info->pixels);
5360static MagickBooleanType SetCacheAlphaChannel(Image *image,
5361 const Quantum opacity)
5364 *magick_restrict image_view;
5372 assert(image != (Image *) NULL);
5373 assert(image->signature == MagickCoreSignature);
5374 if (IsEventLogging() != MagickFalse)
5375 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5376 assert(image->cache != (Cache) NULL);
5377 image->matte=MagickTrue;
5379 image_view=AcquireVirtualCacheView(image,&image->exception);
5380#if defined(MAGICKCORE_OPENMP_SUPPORT)
5381 #pragma omp parallel for schedule(static) shared(status) \
5382 magick_number_threads(image,image,image->rows,2)
5384 for (y=0; y < (ssize_t) image->rows; y++)
5392 if (status == MagickFalse)
5394 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
5396 if (q == (PixelPacket *) NULL)
5401 for (x=0; x < (ssize_t) image->columns; x++)
5406 status=SyncCacheViewAuthenticPixels(image_view,&image->exception);
5408 image_view=DestroyCacheView(image_view);
5412MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(
const Image *image,
5413 const VirtualPixelMethod virtual_pixel_method)
5416 *magick_restrict cache_info;
5421 assert(image != (Image *) NULL);
5422 assert(image->signature == MagickCoreSignature);
5423 if (IsEventLogging() != MagickFalse)
5424 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5425 assert(image->cache != (Cache) NULL);
5426 cache_info=(CacheInfo *) image->cache;
5427 assert(cache_info->signature == MagickCoreSignature);
5428 method=cache_info->virtual_pixel_method;
5429 cache_info->virtual_pixel_method=virtual_pixel_method;
5430 if ((image->columns != 0) && (image->rows != 0))
5431 switch (virtual_pixel_method)
5433 case BackgroundVirtualPixelMethod:
5435 if ((image->background_color.opacity != OpaqueOpacity) &&
5436 (image->matte == MagickFalse))
5437 (void) SetCacheAlphaChannel((Image *) image,OpaqueOpacity);
5438 if ((IsPixelGray(&image->background_color) == MagickFalse) &&
5439 (IsGrayColorspace(image->colorspace) != MagickFalse))
5440 (void) SetImageColorspace((Image *) image,sRGBColorspace);
5443 case TransparentVirtualPixelMethod:
5445 if (image->matte == MagickFalse)
5446 (void) SetCacheAlphaChannel((Image *) image,OpaqueOpacity);
5455#if defined(MAGICKCORE_OPENCL_SUPPORT)
5479static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5484 assert(cache_info != (CacheInfo *)NULL);
5485 if ((cache_info->type != MemoryCache) ||
5486 (cache_info->opencl == (OpenCLCacheInfo *)NULL))
5491 LockSemaphoreInfo(cache_info->semaphore);
5492 if (cache_info->opencl != (OpenCLCacheInfo *)NULL)
5500 clEnv=GetDefaultOpenCLEnv();
5501 events=CopyOpenCLEvents(cache_info->opencl,&event_count);
5502 if (events != (cl_event *) NULL)
5516 context=GetOpenCLContext(clEnv);
5517 queue=AcquireOpenCLCommandQueue(clEnv);
5518 pixels=(PixelPacket *) clEnv->library->clEnqueueMapBuffer(queue,
5519 cache_info->opencl->buffer,CL_TRUE, CL_MAP_READ | CL_MAP_WRITE,0,
5520 cache_info->length,event_count,events,NULL,&status);
5521 assert(pixels == cache_info->pixels);
5522 events=(cl_event *) RelinquishMagickMemory(events);
5523 RelinquishOpenCLCommandQueue(clEnv,queue);
5525 cache_info->opencl=RelinquishOpenCLCacheInfo(clEnv,cache_info->opencl);
5527 UnlockSemaphoreInfo(cache_info->semaphore);
5530MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5533 *magick_restrict cache_info;
5535 assert(image != (Image *)NULL);
5536 cache_info = (CacheInfo *)image->cache;
5537 CopyOpenCLBuffer(cache_info);
5570MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5571 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5574 *magick_restrict cache_info;
5582 assert(image != (Image *) NULL);
5583 assert(image->signature == MagickCoreSignature);
5584 if (image->cache == (Cache) NULL)
5585 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5586 cache_info=(CacheInfo *) image->cache;
5587 assert(cache_info->signature == MagickCoreSignature);
5588 if (cache_info->type == UndefinedCache)
5589 return(MagickFalse);
5590 if ((image->storage_class == DirectClass) &&
5591 (image->clip_mask != (Image *) NULL) &&
5592 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5593 return(MagickFalse);
5594 if ((image->storage_class == DirectClass) &&
5595 (image->mask != (Image *) NULL) &&
5596 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5597 return(MagickFalse);
5598 if (nexus_info->authentic_pixel_cache != MagickFalse)
5600 if (image->taint == MagickFalse)
5601 image->taint=MagickTrue;
5604 assert(cache_info->signature == MagickCoreSignature);
5605 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5606 if ((cache_info->active_index_channel != MagickFalse) &&
5607 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
5608 return(MagickFalse);
5609 if ((status != MagickFalse) && (image->taint == MagickFalse))
5610 image->taint=MagickTrue;
5641static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5642 ExceptionInfo *exception)
5645 *magick_restrict cache_info;
5648 id = GetOpenMPThreadId();
5653 assert(image != (Image *) NULL);
5654 assert(image->signature == MagickCoreSignature);
5655 assert(image->cache != (Cache) NULL);
5656 cache_info=(CacheInfo *) image->cache;
5657 assert(cache_info->signature == MagickCoreSignature);
5658 assert(
id < (
int) cache_info->number_threads);
5659 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5691MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5692 ExceptionInfo *exception)
5695 *magick_restrict cache_info;
5698 id = GetOpenMPThreadId();
5703 assert(image != (Image *) NULL);
5704 assert(image->signature == MagickCoreSignature);
5705 assert(image->cache != (Cache) NULL);
5706 cache_info=(CacheInfo *) image->cache;
5707 assert(cache_info->signature == MagickCoreSignature);
5708 if (cache_info->methods.sync_authentic_pixels_handler !=
5709 (SyncAuthenticPixelsHandler) NULL)
5710 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
5711 assert(
id < (
int) cache_info->number_threads);
5712 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5744MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5745 ExceptionInfo *exception)
5748 *magick_restrict cache_info;
5750 assert(image != (Image *) NULL);
5751 assert(exception != (ExceptionInfo *) NULL);
5752 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5753 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5784static MagickBooleanType WritePixelCacheIndexes(CacheInfo *cache_info,
5785 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5804 if (cache_info->active_index_channel == MagickFalse)
5805 return(MagickFalse);
5806 if (nexus_info->authentic_pixel_cache != MagickFalse)
5808 if (nexus_info->indexes == (IndexPacket *) NULL)
5809 return(MagickFalse);
5810 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5811 return(MagickFalse);
5812 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5813 nexus_info->region.x;
5814 length=(MagickSizeType) nexus_info->region.width*
sizeof(IndexPacket);
5815 rows=nexus_info->region.height;
5816 extent=(MagickSizeType) length*rows;
5817 p=nexus_info->indexes;
5819 switch (cache_info->type)
5830 if ((cache_info->columns == nexus_info->region.width) &&
5831 (extent == (MagickSizeType) ((
size_t) extent)))
5836 q=cache_info->indexes+offset;
5837 for (y=0; y < (ssize_t) rows; y++)
5839 (void) memcpy(q,p,(
size_t) length);
5840 p+=(ptrdiff_t) nexus_info->region.width;
5841 q+=(ptrdiff_t) cache_info->columns;
5850 LockSemaphoreInfo(cache_info->file_semaphore);
5851 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5853 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5854 cache_info->cache_filename);
5855 UnlockSemaphoreInfo(cache_info->file_semaphore);
5856 return(MagickFalse);
5858 if ((cache_info->columns == nexus_info->region.width) &&
5859 (extent <= MagickMaxBufferExtent))
5864 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5865 for (y=0; y < (ssize_t) rows; y++)
5867 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5868 (MagickOffsetType) extent*(MagickOffsetType)
sizeof(PixelPacket)+
5869 offset*(MagickOffsetType)
sizeof(*p),length,(
const unsigned char *)
5871 if (count < (MagickOffsetType) length)
5873 p+=(ptrdiff_t) nexus_info->region.width;
5874 offset+=(MagickOffsetType) cache_info->columns;
5876 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5877 (void) ClosePixelCacheOnDisk(cache_info);
5878 UnlockSemaphoreInfo(cache_info->file_semaphore);
5881 case DistributedCache:
5889 LockSemaphoreInfo(cache_info->file_semaphore);
5890 region=nexus_info->region;
5891 if ((cache_info->columns != nexus_info->region.width) ||
5892 (extent > MagickMaxBufferExtent))
5899 for (y=0; y < (ssize_t) rows; y++)
5901 count=WriteDistributePixelCacheIndexes((DistributeCacheInfo *)
5902 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5903 if (count != (MagickOffsetType) length)
5905 p+=(ptrdiff_t) nexus_info->region.width;
5908 UnlockSemaphoreInfo(cache_info->file_semaphore);
5914 if (y < (ssize_t) rows)
5916 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5917 cache_info->cache_filename);
5918 return(MagickFalse);
5920 if ((cache_info->debug != MagickFalse) &&
5921 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5922 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5923 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5924 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5925 nexus_info->region.x,(
double) nexus_info->region.y);
5957static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5958 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5977 if (nexus_info->authentic_pixel_cache != MagickFalse)
5979 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5980 return(MagickFalse);
5981 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5982 nexus_info->region.x;
5983 length=(MagickSizeType) nexus_info->region.width*
sizeof(PixelPacket);
5984 rows=nexus_info->region.height;
5986 p=nexus_info->pixels;
5988 switch (cache_info->type)
5999 if ((cache_info->columns == nexus_info->region.width) &&
6000 (extent == (MagickSizeType) ((
size_t) extent)))
6005 q=cache_info->pixels+offset;
6006 for (y=0; y < (ssize_t) rows; y++)
6008 (void) memcpy(q,p,(
size_t) length);
6009 p+=(ptrdiff_t) nexus_info->region.width;
6010 q+=(ptrdiff_t) cache_info->columns;
6019 LockSemaphoreInfo(cache_info->file_semaphore);
6020 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6022 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6023 cache_info->cache_filename);
6024 UnlockSemaphoreInfo(cache_info->file_semaphore);
6025 return(MagickFalse);
6027 if ((cache_info->columns == nexus_info->region.width) &&
6028 (extent <= MagickMaxBufferExtent))
6033 for (y=0; y < (ssize_t) rows; y++)
6035 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6036 (MagickOffsetType)
sizeof(*p),length,(
const unsigned char *) p);
6037 if (count < (MagickOffsetType) length)
6039 p+=(ptrdiff_t) nexus_info->region.width;
6040 offset+=(MagickOffsetType) cache_info->columns;
6042 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6043 (void) ClosePixelCacheOnDisk(cache_info);
6044 UnlockSemaphoreInfo(cache_info->file_semaphore);
6047 case DistributedCache:
6055 LockSemaphoreInfo(cache_info->file_semaphore);
6056 region=nexus_info->region;
6057 if ((cache_info->columns != nexus_info->region.width) ||
6058 (extent > MagickMaxBufferExtent))
6065 for (y=0; y < (ssize_t) rows; y++)
6067 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6068 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6069 if (count != (MagickOffsetType) length)
6071 p+=(ptrdiff_t) nexus_info->region.width;
6074 UnlockSemaphoreInfo(cache_info->file_semaphore);
6080 if (y < (ssize_t) rows)
6082 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6083 cache_info->cache_filename);
6084 return(MagickFalse);
6086 if ((cache_info->debug != MagickFalse) &&
6087 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6088 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6089 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6090 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6091 nexus_info->region.x,(
double) nexus_info->region.y);