43#include "MagickCore/studio.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/cache-private.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colorspace-private.h"
50#include "MagickCore/composite-private.h"
51#include "MagickCore/distribute-cache-private.h"
52#include "MagickCore/exception.h"
53#include "MagickCore/exception-private.h"
54#include "MagickCore/geometry.h"
55#include "MagickCore/list.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#include "MagickCore/memory-private.h"
60#include "MagickCore/nt-base-private.h"
61#include "MagickCore/option.h"
62#include "MagickCore/pixel.h"
63#include "MagickCore/pixel-accessor.h"
64#include "MagickCore/pixel-private.h"
65#include "MagickCore/policy.h"
66#include "MagickCore/quantum.h"
67#include "MagickCore/random_.h"
68#include "MagickCore/registry.h"
69#include "MagickCore/resource_.h"
70#include "MagickCore/semaphore.h"
71#include "MagickCore/splay-tree.h"
72#include "MagickCore/string_.h"
73#include "MagickCore/string-private.h"
74#include "MagickCore/timer-private.h"
75#include "MagickCore/thread-private.h"
76#include "MagickCore/utility.h"
77#include "MagickCore/utility-private.h"
78#if defined(MAGICKCORE_HAVE_ERRNO_H)
81#if defined(MAGICKCORE_HAVE_SYS_LOADAVG_H)
82# include <sys/loadavg.h>
84#if defined(MAGICKCORE_ZLIB_DELEGATE)
91#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
92#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
93 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
108#if defined(__cplusplus) || defined(c_plusplus)
117 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
119 *GetVirtualPixelsCache(
const Image *);
122 *GetVirtualMetacontentFromCache(
const Image *);
124static MagickBooleanType
125 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,Quantum *,
127 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
130 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
133 ReadPixelCacheMetacontent(
CacheInfo *magick_restrict,
142 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
144 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
146 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
147 const ssize_t,
const ssize_t,
const size_t,
const size_t,
151#if defined(MAGICKCORE_OPENCL_SUPPORT)
153 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
156#if defined(__cplusplus) || defined(c_plusplus)
167 cache_anonymous_memory = (-1);
191MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
194 *magick_restrict cache_info;
199 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
201 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
202 (void) memset(cache_info,0,
sizeof(*cache_info));
203 cache_info->type=UndefinedCache;
204 cache_info->mode=IOMode;
205 cache_info->disk_mode=IOMode;
206 cache_info->colorspace=sRGBColorspace;
207 cache_info->file=(-1);
208 cache_info->id=GetMagickThreadId();
209 cache_info->number_threads=number_threads;
210 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
211 cache_info->number_threads=GetOpenMPMaximumThreads();
212 if (cache_info->number_threads == 0)
213 cache_info->number_threads=1;
214 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
215 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
216 if (value != (
const char *) NULL)
218 cache_info->synchronize=IsStringTrue(value);
219 value=DestroyString(value);
221 value=GetPolicyValue(
"cache:synchronize");
222 if (value != (
const char *) NULL)
224 cache_info->synchronize=IsStringTrue(value);
225 value=DestroyString(value);
227 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
228 (MagickSizeType) MAGICK_SSIZE_MAX);
229 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
230 (MagickSizeType) MAGICK_SSIZE_MAX);
231 cache_info->semaphore=AcquireSemaphoreInfo();
232 cache_info->reference_count=1;
233 cache_info->file_semaphore=AcquireSemaphoreInfo();
234 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
236 cache_info->signature=MagickCoreSignature;
237 return((Cache ) cache_info);
262MagickPrivate
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
265 **magick_restrict nexus_info;
270 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
271 number_threads,
sizeof(*nexus_info)));
273 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
274 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
275 2*
sizeof(**nexus_info));
277 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
278 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
279 for (i=0; i < (ssize_t) (2*number_threads); i++)
281 nexus_info[i]=(*nexus_info+i);
282 if (i < (ssize_t) number_threads)
283 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
284 nexus_info[i]->signature=MagickCoreSignature;
317MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
321 *magick_restrict cache_info;
323 assert(image != (
const Image *) NULL);
324 assert(image->signature == MagickCoreSignature);
326 assert(exception->signature == MagickCoreSignature);
327 assert(image->cache != (Cache) NULL);
330 assert(cache_info->signature == MagickCoreSignature);
332 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
333 return((
void *) NULL);
334 *length=(size_t) cache_info->length;
335 return(cache_info->pixels);
356MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
359 cache_semaphore=AcquireSemaphoreInfo();
381MagickPrivate
void CacheComponentTerminus(
void)
384 ActivateSemaphoreInfo(&cache_semaphore);
386 RelinquishSemaphoreInfo(&cache_semaphore);
418static MagickBooleanType ClipPixelCacheNexus(
Image *image,
422 *magick_restrict cache_info;
434 if (IsEventLogging() != MagickFalse)
435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
436 if ((image->channels & WriteMaskChannel) == 0)
438 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
443 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
444 nexus_info->region.width,nexus_info->region.height,
445 nexus_info->virtual_nexus,exception);
446 q=nexus_info->pixels;
447 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
449 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
454 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
462 mask=(double) GetPixelWriteMask(image,p);
463 if (fabs(mask) >= MagickEpsilon)
472 src_alpha=GetPixelAlpha(image,p);
473 mask_alpha=QuantumScale*mask*(double) src_alpha;
474 dst_alpha=(double) GetPixelAlpha(image,q);
475 for (i=0; i < (ssize_t) image->number_channels; i++)
480 PixelChannel channel = GetPixelChannelChannel(image,i);
481 if (channel == AlphaPixelChannel)
483 traits=GetPixelChannelTraits(image,channel);
484 if ((traits & UpdatePixelTrait) == 0)
486 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha,
487 (
double) q[i],dst_alpha));
489 SetPixelAlpha(image,src_alpha,q);
491 p+=(ptrdiff_t) GetPixelChannels(image);
492 q+=(ptrdiff_t) GetPixelChannels(image);
520MagickPrivate Cache ClonePixelCache(
const Cache cache)
523 *magick_restrict clone_info;
526 *magick_restrict cache_info;
528 assert(cache != NULL);
530 assert(cache_info->signature == MagickCoreSignature);
531 if (IsEventLogging() != MagickFalse)
532 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
533 cache_info->filename);
534 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
535 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
536 return((Cache ) clone_info);
564MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
567 *magick_restrict cache_info,
568 *magick_restrict source_info;
570 assert(clone != (Cache) NULL);
572 assert(source_info->signature == MagickCoreSignature);
573 if (IsEventLogging() != MagickFalse)
574 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
575 source_info->filename);
576 assert(cache != (Cache) NULL);
578 assert(cache_info->signature == MagickCoreSignature);
579 source_info->methods=cache_info->methods;
611static MagickBooleanType ClonePixelCacheOnDisk(
632 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
633 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
635 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
636 (lseek(clone_info->file,0,SEEK_SET) < 0))
638 quantum=(size_t) MagickMaxBufferExtent;
639 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
641#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
642 if (cache_info->length < 0x7ffff000)
646 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
647 (
size_t) cache_info->length);
648 }
while ((count < 0) && (errno == EINTR));
649 if (count == (ssize_t) cache_info->length)
653 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
654 (lseek(clone_info->file,0,SEEK_SET) < 0))
658 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
660 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
661 if (buffer == (
unsigned char *) NULL)
662 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
664 while (extent < cache_info->length)
669 length=(size_t) MagickMin((MagickSizeType) quantum,cache_info->length-
673 count=read(cache_info->file,buffer,length);
674 }
while ((count < 0) && (errno == EINTR));
677 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
685 while (offset < count)
689 number_bytes=write(clone_info->file,buffer+offset,(
size_t) (count-
691 }
while ((number_bytes < 0) && (errno == EINTR));
692 if (number_bytes <= 0)
694 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
697 offset+=number_bytes;
699 extent+=(MagickSizeType) offset;
702 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
703 return(extent == cache_info->length ? MagickTrue : MagickFalse);
706#if defined(MAGICKCORE_OPENMP_SUPPORT)
707static inline int GetCacheNumberThreads(
const CacheInfo *source,
708 const CacheInfo *destination,
const size_t chunk,
const int factor)
711 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
712 number_threads = 1UL,
713 workload_factor = 64UL << factor;
718 number_threads=(chunk <= workload_factor) ? 1UL :
719 (chunk >= (workload_factor << 6)) ? max_threads :
720 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
724 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
725 ((destination->type != MemoryCache) && (destination->type != MapCache)))
726 number_threads=MagickMin(number_threads,4);
727 return((
int) number_threads);
731static MagickBooleanType ClonePixelCacheRepository(
735#define cache_number_threads(source,destination,chunk,factor) \
736 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
743 **magick_restrict cache_nexus,
744 **magick_restrict clone_nexus;
752 assert(cache_info != (
CacheInfo *) NULL);
753 assert(clone_info != (
CacheInfo *) NULL);
755 if (cache_info->type == PingCache)
757 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
758 if ((cache_info->storage_class == clone_info->storage_class) &&
759 (cache_info->colorspace == clone_info->colorspace) &&
760 (cache_info->alpha_trait == clone_info->alpha_trait) &&
761 (cache_info->channels == clone_info->channels) &&
762 (cache_info->columns == clone_info->columns) &&
763 (cache_info->rows == clone_info->rows) &&
764 (cache_info->number_channels == clone_info->number_channels) &&
765 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
766 (cache_info->metacontent_extent == clone_info->metacontent_extent))
771 if (((cache_info->type == MemoryCache) ||
772 (cache_info->type == MapCache)) &&
773 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
775 (void) memcpy(clone_info->pixels,cache_info->pixels,
776 cache_info->number_channels*cache_info->columns*cache_info->rows*
777 sizeof(*cache_info->pixels));
778 if ((cache_info->metacontent_extent != 0) &&
779 (clone_info->metacontent_extent != 0))
780 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
781 cache_info->columns*cache_info->rows*
782 clone_info->metacontent_extent*
sizeof(
unsigned char));
785 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
786 return(ClonePixelCacheOnDisk(cache_info,clone_info));
791 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
792 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
793 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
794 optimize=(cache_info->number_channels == clone_info->number_channels) &&
795 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
796 MagickTrue : MagickFalse;
797 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
798 clone_info->number_channels*clone_info->columns);
800#if defined(MAGICKCORE_OPENMP_SUPPORT)
801 #pragma omp parallel for schedule(static) shared(status) \
802 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
804 for (y=0; y < (ssize_t) cache_info->rows; y++)
807 id = GetOpenMPThreadId();
815 if (status == MagickFalse)
817 if (y >= (ssize_t) clone_info->rows)
819 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
820 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
821 if (pixels == (Quantum *) NULL)
823 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
824 if (status == MagickFalse)
826 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
827 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
828 if (pixels == (Quantum *) NULL)
830 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
831 if (optimize != MagickFalse)
832 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
845 p=cache_nexus[id]->pixels;
846 q=clone_nexus[id]->pixels;
847 for (x=0; x < (ssize_t) cache_info->columns; x++)
852 if (x == (ssize_t) clone_info->columns)
854 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
862 channel=clone_info->channel_map[i].channel;
863 traits=cache_info->channel_map[channel].traits;
864 if (traits != UndefinedPixelTrait)
865 *q=*(p+cache_info->channel_map[channel].offset);
868 p+=(ptrdiff_t) cache_info->number_channels;
871 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
873 if ((cache_info->metacontent_extent != 0) &&
874 (clone_info->metacontent_extent != 0))
879 length=(size_t) MagickMin(cache_info->metacontent_extent,
880 clone_info->metacontent_extent);
881#if defined(MAGICKCORE_OPENMP_SUPPORT)
882 #pragma omp parallel for schedule(static) shared(status) \
883 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
885 for (y=0; y < (ssize_t) cache_info->rows; y++)
888 id = GetOpenMPThreadId();
893 if (status == MagickFalse)
895 if (y >= (ssize_t) clone_info->rows)
897 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
898 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
899 if (pixels == (Quantum *) NULL)
901 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
902 if (status == MagickFalse)
904 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
905 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
906 if (pixels == (Quantum *) NULL)
908 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
909 (cache_nexus[
id]->metacontent != (
void *) NULL))
910 (void) memcpy(clone_nexus[
id]->metacontent,
911 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
912 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
915 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
916 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
917 if (cache_info->debug != MagickFalse)
920 message[MagickPathExtent];
922 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
923 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
924 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
925 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
952static void DestroyImagePixelCache(
Image *image)
954 assert(image != (
Image *) NULL);
955 assert(image->signature == MagickCoreSignature);
956 if (IsEventLogging() != MagickFalse)
957 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
958 if (image->cache != (
void *) NULL)
959 image->cache=DestroyPixelCache(image->cache);
984MagickExport
void DestroyImagePixels(
Image *image)
987 *magick_restrict cache_info;
989 assert(image != (
const Image *) NULL);
990 assert(image->signature == MagickCoreSignature);
991 if (IsEventLogging() != MagickFalse)
992 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
993 assert(image->cache != (Cache) NULL);
995 assert(cache_info->signature == MagickCoreSignature);
996 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
998 cache_info->methods.destroy_pixel_handler(image);
1001 image->cache=DestroyPixelCache(image->cache);
1027static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
1033 if (cache_info->file != -1)
1035 status=close_utf8(cache_info->file);
1036 cache_info->file=(-1);
1037 RelinquishMagickResource(FileResource,1);
1039 return(status == -1 ? MagickFalse : MagickTrue);
1042static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
1044 switch (cache_info->type)
1048 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1049#if defined(MAGICKCORE_OPENCL_SUPPORT)
1050 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1052 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1054 cache_info->pixels=(Quantum *) NULL;
1058 if (cache_info->mapped == MagickFalse)
1059 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1060 cache_info->pixels);
1063 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1064 cache_info->pixels=(Quantum *) NULL;
1066 RelinquishMagickResource(MemoryResource,cache_info->length);
1071 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1072 cache_info->pixels=(Quantum *) NULL;
1073 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1074 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1075 *cache_info->cache_filename=
'\0';
1076 RelinquishMagickResource(MapResource,cache_info->length);
1081 if (cache_info->file != -1)
1082 (void) ClosePixelCacheOnDisk(cache_info);
1083 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1084 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1085 *cache_info->cache_filename=
'\0';
1086 RelinquishMagickResource(DiskResource,cache_info->length);
1089 case DistributedCache:
1091 *cache_info->cache_filename=
'\0';
1093 cache_info->server_info);
1099 cache_info->type=UndefinedCache;
1100 cache_info->mapped=MagickFalse;
1101 cache_info->metacontent=(
void *) NULL;
1104MagickPrivate Cache DestroyPixelCache(Cache cache)
1107 *magick_restrict cache_info;
1109 assert(cache != (Cache) NULL);
1111 assert(cache_info->signature == MagickCoreSignature);
1112 if (IsEventLogging() != MagickFalse)
1113 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1114 cache_info->filename);
1115 LockSemaphoreInfo(cache_info->semaphore);
1116 cache_info->reference_count--;
1117 if (cache_info->reference_count != 0)
1119 UnlockSemaphoreInfo(cache_info->semaphore);
1120 return((Cache) NULL);
1122 UnlockSemaphoreInfo(cache_info->semaphore);
1123 if (cache_info->debug != MagickFalse)
1126 message[MagickPathExtent];
1128 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1129 cache_info->filename);
1130 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1132 RelinquishPixelCachePixels(cache_info);
1135 cache_info->server_info);
1136 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1137 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1138 cache_info->number_threads);
1139 if (cache_info->random_info != (
RandomInfo *) NULL)
1140 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1142 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1144 RelinquishSemaphoreInfo(&cache_info->semaphore);
1145 cache_info->signature=(~MagickCoreSignature);
1146 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1177static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1179 if (nexus_info->mapped == MagickFalse)
1180 (void) RelinquishAlignedMemory(nexus_info->cache);
1182 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1183 nexus_info->cache=(Quantum *) NULL;
1184 nexus_info->pixels=(Quantum *) NULL;
1185 nexus_info->metacontent=(
void *) NULL;
1186 nexus_info->length=0;
1187 nexus_info->mapped=MagickFalse;
1191 const size_t number_threads)
1196 assert(nexus_info != (
NexusInfo **) NULL);
1197 for (i=0; i < (ssize_t) (2*number_threads); i++)
1199 if (nexus_info[i]->cache != (Quantum *) NULL)
1200 RelinquishCacheNexusPixels(nexus_info[i]);
1201 nexus_info[i]->signature=(~MagickCoreSignature);
1203 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1204 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1233MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1236 *magick_restrict cache_info;
1239 id = GetOpenMPThreadId();
1241 assert(image != (
const Image *) NULL);
1242 assert(image->signature == MagickCoreSignature);
1243 assert(image->cache != (Cache) NULL);
1245 assert(cache_info->signature == MagickCoreSignature);
1246 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1247 (GetAuthenticMetacontentFromHandler) NULL)
1252 metacontent=cache_info->methods.
1253 get_authentic_metacontent_from_handler(image);
1254 return(metacontent);
1256 assert(
id < (
int) cache_info->number_threads);
1257 return(cache_info->nexus_info[
id]->metacontent);
1284static void *GetAuthenticMetacontentFromCache(
const Image *image)
1287 *magick_restrict cache_info;
1290 id = GetOpenMPThreadId();
1292 assert(image != (
const Image *) NULL);
1293 assert(image->signature == MagickCoreSignature);
1294 assert(image->cache != (Cache) NULL);
1296 assert(cache_info->signature == MagickCoreSignature);
1297 assert(
id < (
int) cache_info->number_threads);
1298 return(cache_info->nexus_info[
id]->metacontent);
1301#if defined(MAGICKCORE_OPENCL_SUPPORT)
1330MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1334 *magick_restrict cache_info;
1336 assert(image != (
const Image *) NULL);
1337 assert(device != (
const MagickCLDevice) NULL);
1339 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1341 (void) SyncImagePixelCache((
Image *) image,exception);
1344 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1345 return((cl_mem) NULL);
1346 LockSemaphoreInfo(cache_info->semaphore);
1347 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1348 (cache_info->opencl->device->context != device->context))
1349 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1350 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1352 assert(cache_info->pixels != (Quantum *) NULL);
1353 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1354 cache_info->length);
1356 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1357 RetainOpenCLMemObject(cache_info->opencl->buffer);
1358 UnlockSemaphoreInfo(cache_info->semaphore);
1359 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1360 return((cl_mem) NULL);
1361 assert(cache_info->opencl->pixels == cache_info->pixels);
1362 return(cache_info->opencl->buffer);
1401MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1402 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1406 *magick_restrict cache_info;
1409 *magick_restrict pixels;
1414 assert(image != (
Image *) NULL);
1415 assert(image->signature == MagickCoreSignature);
1416 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1417 nexus_info,exception);
1418 if (pixels == (Quantum *) NULL)
1419 return((Quantum *) NULL);
1421 assert(cache_info->signature == MagickCoreSignature);
1422 if (nexus_info->authentic_pixel_cache != MagickFalse)
1424 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1425 return((Quantum *) NULL);
1426 if (cache_info->metacontent_extent != 0)
1427 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1428 return((Quantum *) NULL);
1455static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1458 *magick_restrict cache_info;
1461 id = GetOpenMPThreadId();
1463 assert(image != (
const Image *) NULL);
1464 assert(image->signature == MagickCoreSignature);
1465 assert(image->cache != (Cache) NULL);
1467 assert(cache_info->signature == MagickCoreSignature);
1468 assert(
id < (
int) cache_info->number_threads);
1469 return(cache_info->nexus_info[
id]->pixels);
1496MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1499 *magick_restrict cache_info;
1502 id = GetOpenMPThreadId();
1504 assert(image != (
const Image *) NULL);
1505 assert(image->signature == MagickCoreSignature);
1506 assert(image->cache != (Cache) NULL);
1508 assert(cache_info->signature == MagickCoreSignature);
1509 if (cache_info->methods.get_authentic_pixels_from_handler !=
1510 (GetAuthenticPixelsFromHandler) NULL)
1511 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1512 assert(
id < (
int) cache_info->number_threads);
1513 return(cache_info->nexus_info[
id]->pixels);
1561MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1562 const ssize_t y,
const size_t columns,
const size_t rows,
1566 *magick_restrict cache_info;
1569 id = GetOpenMPThreadId();
1574 assert(image != (
Image *) NULL);
1575 assert(image->signature == MagickCoreSignature);
1576 assert(image->cache != (Cache) NULL);
1578 assert(cache_info->signature == MagickCoreSignature);
1579 if (cache_info->methods.get_authentic_pixels_handler !=
1580 (GetAuthenticPixelsHandler) NULL)
1582 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1586 assert(
id < (
int) cache_info->number_threads);
1587 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1588 cache_info->nexus_info[
id],exception);
1623static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1624 const ssize_t y,
const size_t columns,
const size_t rows,
1628 *magick_restrict cache_info;
1631 id = GetOpenMPThreadId();
1634 *magick_restrict pixels;
1636 assert(image != (
const Image *) NULL);
1637 assert(image->signature == MagickCoreSignature);
1638 assert(image->cache != (Cache) NULL);
1640 if (cache_info == (Cache) NULL)
1641 return((Quantum *) NULL);
1642 assert(cache_info->signature == MagickCoreSignature);
1643 assert(
id < (
int) cache_info->number_threads);
1644 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1645 cache_info->nexus_info[
id],exception);
1672MagickExport MagickSizeType GetImageExtent(
const Image *image)
1675 *magick_restrict cache_info;
1678 id = GetOpenMPThreadId();
1680 assert(image != (
Image *) NULL);
1681 assert(image->signature == MagickCoreSignature);
1682 if (IsEventLogging() != MagickFalse)
1683 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1684 assert(image->cache != (Cache) NULL);
1686 assert(cache_info->signature == MagickCoreSignature);
1687 assert(
id < (
int) cache_info->number_threads);
1688 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1721static MagickBooleanType GetDynamicThrottlePolicy(
void)
1723 static MagickBooleanType
1724 check_policy = MagickTrue;
1726 static MagickBooleanType
1727 dynamic_throttle = MagickFalse;
1729 if (check_policy != MagickFalse)
1731 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1732 if (value != (
char *) NULL)
1734 dynamic_throttle=IsStringTrue(value);
1735 value=DestroyString(value);
1737 check_policy=MagickFalse;
1739 return(dynamic_throttle);
1742static inline MagickBooleanType ValidatePixelCacheMorphology(
1743 const Image *magick_restrict image)
1746 *magick_restrict cache_info;
1756 p=image->channel_map;
1757 q=cache_info->channel_map;
1758 if ((image->storage_class != cache_info->storage_class) ||
1759 (image->colorspace != cache_info->colorspace) ||
1760 (image->alpha_trait != cache_info->alpha_trait) ||
1761 (image->channels != cache_info->channels) ||
1762 (image->columns != cache_info->columns) ||
1763 (image->rows != cache_info->rows) ||
1764 (image->number_channels != cache_info->number_channels) ||
1765 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1766 (image->metacontent_extent != cache_info->metacontent_extent) ||
1767 (cache_info->nexus_info == (
NexusInfo **) NULL))
1768 return(MagickFalse);
1772static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1776 *magick_restrict cache_info;
1780 status = MagickTrue;
1782 static MagickSizeType
1783 cpu_throttle = MagickResourceInfinity,
1786 if (IsImageTTLExpired(image) != MagickFalse)
1791 (void) ThrowMagickException(exception,GetMagickModule(),
1792 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1793 return((Cache) NULL);
1795 if (cpu_throttle == MagickResourceInfinity)
1796 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1797 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1810#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1811 if (getloadavg(&load_average,1) != 1)
1814 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1815 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1817 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1818 MagickDelay(cpu_throttle);
1820 LockSemaphoreInfo(image->semaphore);
1821 assert(image->cache != (Cache) NULL);
1823#if defined(MAGICKCORE_OPENCL_SUPPORT)
1824 CopyOpenCLBuffer(cache_info);
1826 destroy=MagickFalse;
1827 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1829 LockSemaphoreInfo(cache_info->semaphore);
1830 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1841 clone_image=(*image);
1842 clone_image.semaphore=AcquireSemaphoreInfo();
1843 clone_image.reference_count=1;
1844 clone_image.cache=ClonePixelCache(cache_info);
1845 clone_info=(
CacheInfo *) clone_image.cache;
1846 status=OpenPixelCache(&clone_image,IOMode,exception);
1847 if (status == MagickFalse)
1848 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1851 if (clone != MagickFalse)
1852 status=ClonePixelCacheRepository(clone_info,cache_info,
1854 if (status == MagickFalse)
1855 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1859 image->cache=clone_info;
1862 RelinquishSemaphoreInfo(&clone_image.semaphore);
1864 UnlockSemaphoreInfo(cache_info->semaphore);
1866 if (destroy != MagickFalse)
1867 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1868 if (status != MagickFalse)
1873 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1875 image->type=UndefinedType;
1876 status=OpenPixelCache(image,IOMode,exception);
1878 if (cache_info->file != -1)
1879 (void) ClosePixelCacheOnDisk(cache_info);
1882 UnlockSemaphoreInfo(image->semaphore);
1883 if (status == MagickFalse)
1884 return((Cache) NULL);
1885 return(image->cache);
1911MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1914 *magick_restrict cache_info;
1916 assert(image != (
Image *) NULL);
1917 assert(image->signature == MagickCoreSignature);
1918 assert(image->cache != (Cache) NULL);
1920 assert(cache_info->signature == MagickCoreSignature);
1921 return(cache_info->type);
1955static inline MagickBooleanType CopyPixel(
const Image *image,
1956 const Quantum *source,Quantum *destination)
1961 if (source == (
const Quantum *) NULL)
1963 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1964 destination[GreenPixelChannel]=ClampToQuantum(
1965 image->background_color.green);
1966 destination[BluePixelChannel]=ClampToQuantum(
1967 image->background_color.blue);
1968 destination[BlackPixelChannel]=ClampToQuantum(
1969 image->background_color.black);
1970 destination[AlphaPixelChannel]=ClampToQuantum(
1971 image->background_color.alpha);
1972 return(MagickFalse);
1974 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1976 PixelChannel channel = GetPixelChannelChannel(image,i);
1977 destination[channel]=source[i];
1982MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1983 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1986 *magick_restrict cache_info;
1991 assert(image != (
Image *) NULL);
1992 assert(image->signature == MagickCoreSignature);
1993 assert(image->cache != (Cache) NULL);
1995 assert(cache_info->signature == MagickCoreSignature);
1996 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1997 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1998 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1999 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
2000 return(CopyPixel(image,q,pixel));
2034static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
2035 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2038 *magick_restrict cache_info;
2041 id = GetOpenMPThreadId();
2046 assert(image != (
const Image *) NULL);
2047 assert(image->signature == MagickCoreSignature);
2048 assert(image->cache != (Cache) NULL);
2050 assert(cache_info->signature == MagickCoreSignature);
2051 assert(
id < (
int) cache_info->number_threads);
2052 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2053 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2055 return(CopyPixel(image,q,pixel));
2089MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2090 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2093 *magick_restrict cache_info;
2096 id = GetOpenMPThreadId();
2101 assert(image != (
const Image *) NULL);
2102 assert(image->signature == MagickCoreSignature);
2103 assert(image->cache != (Cache) NULL);
2105 assert(cache_info->signature == MagickCoreSignature);
2106 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2107 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2108 (GetOneVirtualPixelFromHandler) NULL)
2109 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2110 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2111 assert(
id < (
int) cache_info->number_threads);
2112 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2113 1UL,1UL,cache_info->nexus_info[
id],exception);
2114 return(CopyPixel(image,p,pixel));
2151static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2152 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2156 *magick_restrict cache_info;
2159 id = GetOpenMPThreadId();
2164 assert(image != (
const Image *) NULL);
2165 assert(image->signature == MagickCoreSignature);
2166 assert(image->cache != (Cache) NULL);
2168 assert(cache_info->signature == MagickCoreSignature);
2169 assert(
id < (
int) cache_info->number_threads);
2170 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2171 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2172 cache_info->nexus_info[
id],exception);
2173 return(CopyPixel(image,p,pixel));
2210MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2211 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2215 *magick_restrict cache_info;
2218 id = GetOpenMPThreadId();
2223 assert(image != (
const Image *) NULL);
2224 assert(image->signature == MagickCoreSignature);
2225 assert(image->cache != (Cache) NULL);
2227 assert(cache_info->signature == MagickCoreSignature);
2228 assert(
id < (
int) cache_info->number_threads);
2229 GetPixelInfo(image,pixel);
2230 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2231 cache_info->nexus_info[
id],exception);
2232 if (p == (
const Quantum *) NULL)
2233 return(MagickFalse);
2234 GetPixelInfoPixel(image,p,pixel);
2260MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2263 *magick_restrict cache_info;
2265 assert(cache != (Cache) NULL);
2267 assert(cache_info->signature == MagickCoreSignature);
2268 if (IsEventLogging() != MagickFalse)
2269 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2270 cache_info->filename);
2271 return(cache_info->colorspace);
2297MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2300 *magick_restrict cache_info;
2302 assert(image != (
const Image *) NULL);
2303 assert(image->signature == MagickCoreSignature);
2304 assert(image->cache != (Cache) NULL);
2306 assert(cache_info->signature == MagickCoreSignature);
2307 return(cache_info->cache_filename);
2332MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2335 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2336 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2337 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2338 cache_methods->get_virtual_metacontent_from_handler=
2339 GetVirtualMetacontentFromCache;
2340 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2341 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2342 cache_methods->get_authentic_metacontent_from_handler=
2343 GetAuthenticMetacontentFromCache;
2344 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2345 cache_methods->get_one_authentic_pixel_from_handler=
2346 GetOneAuthenticPixelFromCache;
2347 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2348 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2349 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2377MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2381 *magick_restrict cache_info;
2386 assert(cache != NULL);
2388 assert(cache_info->signature == MagickCoreSignature);
2389 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2391 return((MagickSizeType) cache_info->columns*cache_info->rows);
2422MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2426 *magick_restrict cache_info;
2428 assert(image != (
const Image *) NULL);
2429 assert(image->signature == MagickCoreSignature);
2430 assert(image->cache != (Cache) NULL);
2431 assert(length != (MagickSizeType *) NULL);
2432 magick_unreferenced(exception);
2434 assert(cache_info->signature == MagickCoreSignature);
2435 *length=cache_info->length;
2436 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2437 return((
void *) NULL);
2438 return((
void *) cache_info->pixels);
2465MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2468 *magick_restrict cache_info;
2470 assert(cache != (Cache) NULL);
2472 assert(cache_info->signature == MagickCoreSignature);
2473 if (IsEventLogging() != MagickFalse)
2474 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2475 cache_info->filename);
2476 return(cache_info->storage_class);
2506MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2510 *magick_restrict cache_info;
2512 assert(image != (
Image *) NULL);
2513 assert(image->signature == MagickCoreSignature);
2514 if (IsEventLogging() != MagickFalse)
2515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2517 assert(cache_info->signature == MagickCoreSignature);
2518 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2519 if (GetImagePixelCacheType(image) == DiskCache)
2520 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2548MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2551 *magick_restrict cache_info;
2553 assert(image != (
Image *) NULL);
2554 assert(image->signature == MagickCoreSignature);
2555 assert(image->cache != (Cache) NULL);
2557 assert(cache_info->signature == MagickCoreSignature);
2558 return(cache_info->virtual_pixel_method);
2584static const void *GetVirtualMetacontentFromCache(
const Image *image)
2587 *magick_restrict cache_info;
2590 id = GetOpenMPThreadId();
2593 *magick_restrict metacontent;
2595 assert(image != (
const Image *) NULL);
2596 assert(image->signature == MagickCoreSignature);
2597 assert(image->cache != (Cache) NULL);
2599 assert(cache_info->signature == MagickCoreSignature);
2600 assert(
id < (
int) cache_info->number_threads);
2601 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2602 cache_info->nexus_info[
id]);
2603 return(metacontent);
2632MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2636 *magick_restrict cache_info;
2638 assert(cache != (Cache) NULL);
2640 assert(cache_info->signature == MagickCoreSignature);
2641 if (cache_info->storage_class == UndefinedClass)
2642 return((
void *) NULL);
2643 return(nexus_info->metacontent);
2670MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2673 *magick_restrict cache_info;
2676 id = GetOpenMPThreadId();
2679 *magick_restrict metacontent;
2681 assert(image != (
const Image *) NULL);
2682 assert(image->signature == MagickCoreSignature);
2683 assert(image->cache != (Cache) NULL);
2685 assert(cache_info->signature == MagickCoreSignature);
2686 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2688 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2690 if (metacontent != (
const void *) NULL)
2691 return(metacontent);
2693 assert(
id < (
int) cache_info->number_threads);
2694 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2695 cache_info->nexus_info[
id]);
2696 return(metacontent);
2739 0, 48, 12, 60, 3, 51, 15, 63,
2740 32, 16, 44, 28, 35, 19, 47, 31,
2741 8, 56, 4, 52, 11, 59, 7, 55,
2742 40, 24, 36, 20, 43, 27, 39, 23,
2743 2, 50, 14, 62, 1, 49, 13, 61,
2744 34, 18, 46, 30, 33, 17, 45, 29,
2745 10, 58, 6, 54, 9, 57, 5, 53,
2746 42, 26, 38, 22, 41, 25, 37, 21
2749static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2754 index=x+DitherMatrix[x & 0x07]-32L;
2757 if (index >= (ssize_t) columns)
2758 return((ssize_t) columns-1L);
2762static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2767 index=y+DitherMatrix[y & 0x07]-32L;
2770 if (index >= (ssize_t) rows)
2771 return((ssize_t) rows-1L);
2775static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2779 if (x >= (ssize_t) columns)
2780 return((ssize_t) (columns-1));
2784static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2788 if (y >= (ssize_t) rows)
2789 return((ssize_t) (rows-1));
2793static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2794 const MagickOffsetType y)
2796 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2797 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2798 return(MagickFalse);
2802static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2804 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2807static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2809 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2812static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2813 const size_t extent)
2818 modulo.quotient=offset;
2822 modulo.quotient=offset/((ssize_t) extent);
2823 modulo.remainder=offset % ((ssize_t) extent);
2825 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2828 modulo.remainder+=((ssize_t) extent);
2833MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2834 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2835 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2839 *magick_restrict cache_info;
2855 *magick_restrict virtual_nexus;
2858 *magick_restrict pixels,
2860 virtual_pixel[MaxPixelChannels];
2871 *magick_restrict virtual_metacontent;
2876 assert(image != (
const Image *) NULL);
2877 assert(image->signature == MagickCoreSignature);
2878 assert(image->cache != (Cache) NULL);
2880 assert(cache_info->signature == MagickCoreSignature);
2881 if (cache_info->type == UndefinedCache)
2882 return((
const Quantum *) NULL);
2883#if defined(MAGICKCORE_OPENCL_SUPPORT)
2884 CopyOpenCLBuffer(cache_info);
2886 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2887 ((image->channels & WriteMaskChannel) != 0) ||
2888 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2889 nexus_info,exception);
2890 if (pixels == (Quantum *) NULL)
2891 return((
const Quantum *) NULL);
2892 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2893 return((
const Quantum *) NULL);
2894 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2895 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2896 return((
const Quantum *) NULL);
2897 offset+=nexus_info->region.x;
2898 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2899 nexus_info->region.width-1L;
2900 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2901 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2902 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2903 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2911 if (nexus_info->authentic_pixel_cache != MagickFalse)
2913 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2914 if (status == MagickFalse)
2915 return((
const Quantum *) NULL);
2916 if (cache_info->metacontent_extent != 0)
2918 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2919 if (status == MagickFalse)
2920 return((
const Quantum *) NULL);
2927 virtual_nexus=nexus_info->virtual_nexus;
2929 s=(
unsigned char *) nexus_info->metacontent;
2930 (void) memset(virtual_pixel,0,cache_info->number_channels*
2931 sizeof(*virtual_pixel));
2932 virtual_metacontent=(
void *) NULL;
2933 switch (virtual_pixel_method)
2935 case BackgroundVirtualPixelMethod:
2936 case BlackVirtualPixelMethod:
2937 case GrayVirtualPixelMethod:
2938 case TransparentVirtualPixelMethod:
2939 case MaskVirtualPixelMethod:
2940 case WhiteVirtualPixelMethod:
2941 case EdgeVirtualPixelMethod:
2942 case CheckerTileVirtualPixelMethod:
2943 case HorizontalTileVirtualPixelMethod:
2944 case VerticalTileVirtualPixelMethod:
2946 if (cache_info->metacontent_extent != 0)
2951 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2952 cache_info->metacontent_extent);
2953 if (virtual_metacontent == (
void *) NULL)
2955 (void) ThrowMagickException(exception,GetMagickModule(),
2956 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2957 return((
const Quantum *) NULL);
2959 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2961 switch (virtual_pixel_method)
2963 case BlackVirtualPixelMethod:
2965 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2966 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2967 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2970 case GrayVirtualPixelMethod:
2972 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2973 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2975 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2978 case TransparentVirtualPixelMethod:
2980 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2981 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2982 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2985 case MaskVirtualPixelMethod:
2986 case WhiteVirtualPixelMethod:
2988 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2989 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2990 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2995 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2997 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2999 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
3001 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
3003 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3013 for (v=0; v < (ssize_t) rows; v++)
3019 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3020 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3021 y_offset=EdgeY(y_offset,cache_info->rows);
3022 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3028 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
3029 x_offset,(ssize_t) columns-u);
3030 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3031 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3041 length=(MagickSizeType) 1;
3042 switch (virtual_pixel_method)
3044 case EdgeVirtualPixelMethod:
3047 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3048 EdgeX(x_offset,cache_info->columns),
3049 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3051 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3054 case RandomVirtualPixelMethod:
3056 if (cache_info->random_info == (
RandomInfo *) NULL)
3057 cache_info->random_info=AcquireRandomInfo();
3058 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3059 RandomX(cache_info->random_info,cache_info->columns),
3060 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3061 virtual_nexus,exception);
3062 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3065 case DitherVirtualPixelMethod:
3067 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3068 DitherX(x_offset,cache_info->columns),
3069 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3071 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3074 case TileVirtualPixelMethod:
3076 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3077 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3078 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3079 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3081 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3084 case MirrorVirtualPixelMethod:
3086 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3087 if ((x_modulo.quotient & 0x01) == 1L)
3088 x_modulo.remainder=(ssize_t) cache_info->columns-
3089 x_modulo.remainder-1L;
3090 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3091 if ((y_modulo.quotient & 0x01) == 1L)
3092 y_modulo.remainder=(ssize_t) cache_info->rows-
3093 y_modulo.remainder-1L;
3094 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3095 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3097 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3100 case HorizontalTileEdgeVirtualPixelMethod:
3102 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3103 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3104 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3105 virtual_nexus,exception);
3106 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3109 case VerticalTileEdgeVirtualPixelMethod:
3111 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3112 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3113 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3114 virtual_nexus,exception);
3115 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3118 case BackgroundVirtualPixelMethod:
3119 case BlackVirtualPixelMethod:
3120 case GrayVirtualPixelMethod:
3121 case TransparentVirtualPixelMethod:
3122 case MaskVirtualPixelMethod:
3123 case WhiteVirtualPixelMethod:
3126 r=virtual_metacontent;
3129 case CheckerTileVirtualPixelMethod:
3131 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3132 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3133 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3136 r=virtual_metacontent;
3139 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3140 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3142 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3145 case HorizontalTileVirtualPixelMethod:
3147 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3150 r=virtual_metacontent;
3153 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3154 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3155 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3156 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3158 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3161 case VerticalTileVirtualPixelMethod:
3163 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3166 r=virtual_metacontent;
3169 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3170 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3171 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3172 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3174 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3178 if (p == (
const Quantum *) NULL)
3180 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3182 q+=(ptrdiff_t) cache_info->number_channels;
3183 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3185 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3186 s+=(ptrdiff_t) cache_info->metacontent_extent;
3193 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3194 (
size_t) length,1UL,virtual_nexus,exception);
3195 if (p == (
const Quantum *) NULL)
3197 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3198 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3200 q+=(ptrdiff_t) cache_info->number_channels*length;
3201 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3203 (void) memcpy(s,r,(
size_t) length);
3204 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3207 if (u < (ssize_t) columns)
3213 if (virtual_metacontent != (
void *) NULL)
3214 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3215 if (v < (ssize_t) rows)
3216 return((
const Quantum *) NULL);
3254static const Quantum *GetVirtualPixelCache(
const Image *image,
3255 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3256 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3259 *magick_restrict cache_info;
3262 id = GetOpenMPThreadId();
3267 assert(image != (
const Image *) NULL);
3268 assert(image->signature == MagickCoreSignature);
3269 assert(image->cache != (Cache) NULL);
3271 assert(cache_info->signature == MagickCoreSignature);
3272 assert(
id < (
int) cache_info->number_threads);
3273 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3274 cache_info->nexus_info[
id],exception);
3301MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3304 *magick_restrict cache_info;
3307 id = GetOpenMPThreadId();
3309 assert(image != (
const Image *) NULL);
3310 assert(image->signature == MagickCoreSignature);
3311 assert(image->cache != (Cache) NULL);
3313 assert(cache_info->signature == MagickCoreSignature);
3314 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3315 return(cache_info->methods.get_virtual_pixels_handler(image));
3316 assert(
id < (
int) cache_info->number_threads);
3317 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3368MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3369 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3373 *magick_restrict cache_info;
3376 id = GetOpenMPThreadId();
3381 assert(image != (
const Image *) NULL);
3382 assert(image->signature == MagickCoreSignature);
3383 assert(image->cache != (Cache) NULL);
3385 assert(cache_info->signature == MagickCoreSignature);
3386 if (cache_info->methods.get_virtual_pixel_handler !=
3387 (GetVirtualPixelHandler) NULL)
3388 return(cache_info->methods.get_virtual_pixel_handler(image,
3389 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3390 assert(
id < (
int) cache_info->number_threads);
3391 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3392 columns,rows,cache_info->nexus_info[
id],exception);
3419static const Quantum *GetVirtualPixelsCache(
const Image *image)
3422 *magick_restrict cache_info;
3425 id = GetOpenMPThreadId();
3427 assert(image != (
const Image *) NULL);
3428 assert(image->signature == MagickCoreSignature);
3429 assert(image->cache != (Cache) NULL);
3431 assert(cache_info->signature == MagickCoreSignature);
3432 assert(
id < (
int) cache_info->number_threads);
3433 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3462MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3466 *magick_restrict cache_info;
3468 assert(cache != (Cache) NULL);
3470 assert(cache_info->signature == MagickCoreSignature);
3471 if (cache_info->storage_class == UndefinedClass)
3472 return((Quantum *) NULL);
3473 return((
const Quantum *) nexus_info->pixels);
3506static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3507 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3512 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3514 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3515 gamma=MagickSafeReciprocal(gamma);
3516 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3519static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3523 *magick_restrict cache_info;
3535 if (IsEventLogging() != MagickFalse)
3536 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3537 if ((image->channels & CompositeMaskChannel) == 0)
3539 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3542 if (cache_info == (Cache) NULL)
3543 return(MagickFalse);
3544 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3545 nexus_info->region.width,nexus_info->region.height,
3546 nexus_info->virtual_nexus,exception);
3547 q=nexus_info->pixels;
3548 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3549 return(MagickFalse);
3550 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3555 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3563 alpha=(double) GetPixelCompositeMask(image,p);
3564 for (i=0; i < (ssize_t) image->number_channels; i++)
3566 PixelChannel channel = GetPixelChannelChannel(image,i);
3567 PixelTrait traits = GetPixelChannelTraits(image,channel);
3568 if ((traits & UpdatePixelTrait) == 0)
3570 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3572 p+=(ptrdiff_t) GetPixelChannels(image);
3573 q+=(ptrdiff_t) GetPixelChannels(image);
3610static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3611 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3616 if ((count == 0) || (quantum == 0))
3618 length=count*quantum;
3619 if (quantum != (length/count))
3626 return(MagickFalse);
3629static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3638 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3640 if (*cache_info->cache_filename ==
'\0')
3641 file=AcquireUniqueFileResource(cache_info->cache_filename);
3647 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3652 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3653 O_BINARY | O_EXCL,S_MODE);
3655 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3661 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3664 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3669 return(MagickFalse);
3670 (void) AcquireMagickResource(FileResource,1);
3671 if (cache_info->file != -1)
3672 (void) ClosePixelCacheOnDisk(cache_info);
3673 cache_info->file=file;
3674 cache_info->disk_mode=mode;
3678static inline MagickOffsetType WritePixelCacheRegion(
3679 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3680 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3688#if !defined(MAGICKCORE_HAVE_PWRITE)
3689 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3690 return((MagickOffsetType) -1);
3692 for (i=0; i < (MagickOffsetType) length; i+=count)
3694#if !defined(MAGICKCORE_HAVE_PWRITE)
3695 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3696 (MagickSizeType) i,MagickMaxBufferExtent));
3698 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3699 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3711static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3714 *magick_restrict cache_info;
3720 if (cache_info->debug != MagickFalse)
3723 format[MagickPathExtent],
3724 message[MagickPathExtent];
3726 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3727 (void) FormatLocaleString(message,MagickPathExtent,
3728 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3729 cache_info->cache_filename,cache_info->file,format);
3730 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3732 if (length != (MagickSizeType) ((MagickOffsetType) length))
3733 return(MagickFalse);
3734 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3736 return(MagickFalse);
3737 if ((MagickSizeType) offset < length)
3743 extent=(MagickOffsetType) length-1;
3744 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3747 return(MagickFalse);
3748#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3749 if (cache_info->synchronize != MagickFalse)
3750 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3751 return(MagickFalse);
3754 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3756 return(MagickFalse);
3760static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3764 *magick_restrict cache_info,
3768 format[MagickPathExtent],
3769 message[MagickPathExtent];
3786 assert(image != (
const Image *) NULL);
3787 assert(image->signature == MagickCoreSignature);
3788 assert(image->cache != (Cache) NULL);
3789 if (IsEventLogging() != MagickFalse)
3790 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3791 if (cache_anonymous_memory < 0)
3799 cache_anonymous_memory=0;
3800 value=GetPolicyValue(
"pixel-cache-memory");
3801 if (value == (
char *) NULL)
3802 value=GetPolicyValue(
"cache:memory-map");
3803 if (LocaleCompare(value,
"anonymous") == 0)
3805#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3806 cache_anonymous_memory=1;
3808 (void) ThrowMagickException(exception,GetMagickModule(),
3809 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3810 "`%s' (policy requires anonymous memory mapping)",image->filename);
3813 value=DestroyString(value);
3815 if ((image->columns == 0) || (image->rows == 0))
3816 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3818 assert(cache_info->signature == MagickCoreSignature);
3819 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3820 ((MagickSizeType) image->rows > cache_info->height_limit))
3822 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3823 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3824 image->filename, (double) image->columns, (
double) image->rows,
3825 (double) cache_info->width_limit,(
double) cache_info->height_limit);
3826 return(MagickFalse);
3828 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3830 length=GetImageListLength(image);
3831 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3832 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3835 source_info=(*cache_info);
3836 source_info.file=(-1);
3837 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3838 image->filename,(
double) image->scene);
3839 cache_info->storage_class=image->storage_class;
3840 cache_info->colorspace=image->colorspace;
3841 cache_info->alpha_trait=image->alpha_trait;
3842 cache_info->channels=image->channels;
3843 cache_info->rows=image->rows;
3844 cache_info->columns=image->columns;
3845 status=ResetPixelChannelMap(image,exception);
3846 if (status == MagickFalse)
3847 return(MagickFalse);
3848 cache_info->number_channels=GetPixelChannels(image);
3849 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3850 sizeof(*image->channel_map));
3851 cache_info->metacontent_extent=image->metacontent_extent;
3852 cache_info->mode=mode;
3853 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3854 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3855 if (image->metacontent_extent != 0)
3856 packet_size+=cache_info->metacontent_extent;
3857 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3859 cache_info->storage_class=UndefinedClass;
3860 cache_info->length=0;
3861 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3864 columns=(size_t) (length/cache_info->rows/packet_size);
3865 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3866 ((ssize_t) cache_info->rows < 0))
3868 cache_info->storage_class=UndefinedClass;
3869 cache_info->length=0;
3870 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3873 cache_info->length=length;
3874 if (image->ping != MagickFalse)
3876 cache_info->type=PingCache;
3879 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3880 cache_info->columns*cache_info->rows);
3881 if (cache_info->mode == PersistMode)
3883 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3884 cache_info->metacontent_extent);
3885 if ((status != MagickFalse) &&
3886 (length == (MagickSizeType) ((
size_t) length)) &&
3887 ((cache_info->type == UndefinedCache) ||
3888 (cache_info->type == MemoryCache)))
3890 status=AcquireMagickResource(MemoryResource,cache_info->length);
3891 if (status != MagickFalse)
3894 if (cache_anonymous_memory <= 0)
3896 cache_info->mapped=MagickFalse;
3897 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3898 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3902 cache_info->mapped=MagickTrue;
3903 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3904 cache_info->length);
3906 if (cache_info->pixels == (Quantum *) NULL)
3908 cache_info->mapped=source_info.mapped;
3909 cache_info->pixels=source_info.pixels;
3916 cache_info->type=MemoryCache;
3917 cache_info->metacontent=(
void *) NULL;
3918 if (cache_info->metacontent_extent != 0)
3919 cache_info->metacontent=(
void *) (cache_info->pixels+
3920 cache_info->number_channels*number_pixels);
3921 if ((source_info.storage_class != UndefinedClass) &&
3924 status=ClonePixelCacheRepository(cache_info,&source_info,
3926 RelinquishPixelCachePixels(&source_info);
3928 if (cache_info->debug != MagickFalse)
3930 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3931 MagickPathExtent,format);
3932 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3934 (void) FormatLocaleString(message,MagickPathExtent,
3935 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3936 cache_info->filename,cache_info->mapped != MagickFalse ?
3937 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3938 (double) cache_info->rows,(double)
3939 cache_info->number_channels,format);
3940 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3943 cache_info->storage_class=image->storage_class;
3946 if ((source_info.storage_class != UndefinedClass) &&
3948 RelinquishPixelCachePixels(&source_info);
3949 cache_info->type=UndefinedCache;
3950 return(MagickFalse);
3956 status=AcquireMagickResource(DiskResource,cache_info->length);
3957 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3959 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3967 server_info=AcquireDistributeCacheInfo(exception);
3970 status=OpenDistributePixelCache(server_info,image);
3971 if (status == MagickFalse)
3973 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3974 GetDistributeCacheHostname(server_info));
3975 server_info=DestroyDistributeCacheInfo(server_info);
3983 cache_info->type=DistributedCache;
3984 cache_info->server_info=server_info;
3985 (void) FormatLocaleString(cache_info->cache_filename,
3986 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3989 cache_info->server_info));
3990 if ((source_info.storage_class != UndefinedClass) &&
3993 status=ClonePixelCacheRepository(cache_info,&source_info,
3995 RelinquishPixelCachePixels(&source_info);
3997 if (cache_info->debug != MagickFalse)
3999 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4000 MagickPathExtent,format);
4001 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4003 (void) FormatLocaleString(message,MagickPathExtent,
4004 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4005 cache_info->filename,cache_info->cache_filename,
4007 cache_info->server_info),type,(double) cache_info->columns,
4008 (
double) cache_info->rows,(double)
4009 cache_info->number_channels,format);
4010 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4015 if ((source_info.storage_class != UndefinedClass) &&
4017 RelinquishPixelCachePixels(&source_info);
4018 cache_info->type=UndefinedCache;
4019 return(MagickFalse);
4024 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4025 RelinquishPixelCachePixels(&source_info);
4026 cache_info->type=UndefinedCache;
4027 (void) memset(image->channel_map,0,MaxPixelChannels*
4028 sizeof(*image->channel_map));
4029 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4030 "CacheResourcesExhausted",
"`%s'",image->filename);
4031 return(MagickFalse);
4036 if (status == MagickFalse)
4038 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4039 RelinquishPixelCachePixels(&source_info);
4040 cache_info->type=UndefinedCache;
4041 (void) memset(image->channel_map,0,MaxPixelChannels*
4042 sizeof(*image->channel_map));
4043 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4044 "CacheResourcesExhausted",
"`%s'",image->filename);
4045 return(MagickFalse);
4047 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4048 (cache_info->mode != PersistMode))
4050 (void) ClosePixelCacheOnDisk(cache_info);
4051 *cache_info->cache_filename=
'\0';
4053 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4055 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4056 RelinquishPixelCachePixels(&source_info);
4057 cache_info->type=UndefinedCache;
4058 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4060 return(MagickFalse);
4062 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4063 cache_info->length);
4064 if (status == MagickFalse)
4066 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4067 RelinquishPixelCachePixels(&source_info);
4068 cache_info->type=UndefinedCache;
4069 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4071 return(MagickFalse);
4073 cache_info->type=DiskCache;
4074 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4075 cache_info->metacontent_extent);
4076 if (length == (MagickSizeType) ((
size_t) length))
4078 status=AcquireMagickResource(MapResource,cache_info->length);
4079 if (status != MagickFalse)
4081 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4082 cache_info->offset,(
size_t) cache_info->length);
4083 if (cache_info->pixels == (Quantum *) NULL)
4085 cache_info->mapped=source_info.mapped;
4086 cache_info->pixels=source_info.pixels;
4087 RelinquishMagickResource(MapResource,cache_info->length);
4094 (void) ClosePixelCacheOnDisk(cache_info);
4095 cache_info->type=MapCache;
4096 cache_info->mapped=MagickTrue;
4097 cache_info->metacontent=(
void *) NULL;
4098 if (cache_info->metacontent_extent != 0)
4099 cache_info->metacontent=(
void *) (cache_info->pixels+
4100 cache_info->number_channels*number_pixels);
4101 if ((source_info.storage_class != UndefinedClass) &&
4104 status=ClonePixelCacheRepository(cache_info,&source_info,
4106 RelinquishPixelCachePixels(&source_info);
4108 if (cache_info->debug != MagickFalse)
4110 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4111 MagickPathExtent,format);
4112 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4114 (void) FormatLocaleString(message,MagickPathExtent,
4115 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4116 cache_info->filename,cache_info->cache_filename,
4117 cache_info->file,type,(
double) cache_info->columns,
4118 (double) cache_info->rows,(
double)
4119 cache_info->number_channels,format);
4120 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4125 if ((source_info.storage_class != UndefinedClass) &&
4127 RelinquishPixelCachePixels(&source_info);
4128 cache_info->type=UndefinedCache;
4129 return(MagickFalse);
4136 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4138 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4139 RelinquishPixelCachePixels(&source_info);
4141 if (cache_info->debug != MagickFalse)
4143 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4144 MagickPathExtent,format);
4145 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4147 (void) FormatLocaleString(message,MagickPathExtent,
4148 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4149 cache_info->cache_filename,cache_info->file,type,(
double)
4150 cache_info->columns,(double) cache_info->rows,(
double)
4151 cache_info->number_channels,format);
4152 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4156 cache_info->type=UndefinedCache;
4157 return(MagickFalse);
4199MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4200 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4204 *magick_restrict cache_info,
4205 *magick_restrict clone_info;
4213 assert(image != (
Image *) NULL);
4214 assert(image->signature == MagickCoreSignature);
4215 if (IsEventLogging() != MagickFalse)
4216 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4217 assert(image->cache != (
void *) NULL);
4218 assert(filename != (
const char *) NULL);
4219 assert(offset != (MagickOffsetType *) NULL);
4220 page_size=GetMagickPageSize();
4222 assert(cache_info->signature == MagickCoreSignature);
4223#if defined(MAGICKCORE_OPENCL_SUPPORT)
4224 CopyOpenCLBuffer(cache_info);
4226 if (attach != MagickFalse)
4231 if (cache_info->debug != MagickFalse)
4232 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4233 "attach persistent cache");
4234 (void) CopyMagickString(cache_info->cache_filename,filename,
4236 cache_info->type=MapCache;
4237 cache_info->offset=(*offset);
4238 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4239 return(MagickFalse);
4240 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4241 ((MagickOffsetType) cache_info->length % page_size));
4247 status=AcquireMagickResource(DiskResource,cache_info->length);
4248 if (status == MagickFalse)
4250 cache_info->type=UndefinedCache;
4251 (void) memset(image->channel_map,0,MaxPixelChannels*
4252 sizeof(*image->channel_map));
4253 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4254 "CacheResourcesExhausted",
"`%s'",image->filename);
4255 return(MagickFalse);
4257 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4258 clone_info->type=DiskCache;
4259 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4260 clone_info->file=(-1);
4261 clone_info->storage_class=cache_info->storage_class;
4262 clone_info->colorspace=cache_info->colorspace;
4263 clone_info->alpha_trait=cache_info->alpha_trait;
4264 clone_info->channels=cache_info->channels;
4265 clone_info->columns=cache_info->columns;
4266 clone_info->rows=cache_info->rows;
4267 clone_info->number_channels=cache_info->number_channels;
4268 clone_info->metacontent_extent=cache_info->metacontent_extent;
4269 clone_info->mode=PersistMode;
4270 clone_info->length=cache_info->length;
4271 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4272 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4273 clone_info->offset=(*offset);
4274 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4275 if (status != MagickFalse)
4276 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4277 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4278 ((MagickOffsetType) cache_info->length % page_size));
4279 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4321MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4322 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4326 *magick_restrict cache_info;
4335 *magick_restrict pixels;
4340 assert(image != (
const Image *) NULL);
4341 assert(image->signature == MagickCoreSignature);
4342 assert(image->cache != (Cache) NULL);
4343 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4344 if (cache_info == (Cache) NULL)
4345 return((Quantum *) NULL);
4346 assert(cache_info->signature == MagickCoreSignature);
4347 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4348 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4349 (y >= (ssize_t) cache_info->rows))
4351 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4352 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4353 return((Quantum *) NULL);
4355 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4356 return((Quantum *) NULL);
4357 offset=y*(MagickOffsetType) cache_info->columns;
4358 if (IsOffsetOverflow(offset,(MagickOffsetType) x) == MagickFalse)
4359 return((Quantum *) NULL);
4362 return((Quantum *) NULL);
4363 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4364 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns;
4365 if (IsOffsetOverflow(offset,(MagickOffsetType) columns-1) == MagickFalse)
4366 return((Quantum *) NULL);
4367 offset+=(MagickOffsetType) columns-1;
4368 if ((MagickSizeType) offset >= number_pixels)
4369 return((Quantum *) NULL);
4373 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4374 ((image->channels & WriteMaskChannel) != 0) ||
4375 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4376 nexus_info,exception);
4413static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4414 const ssize_t y,
const size_t columns,
const size_t rows,
4418 *magick_restrict cache_info;
4421 id = GetOpenMPThreadId();
4424 *magick_restrict pixels;
4426 assert(image != (
const Image *) NULL);
4427 assert(image->signature == MagickCoreSignature);
4428 assert(image->cache != (Cache) NULL);
4430 assert(cache_info->signature == MagickCoreSignature);
4431 assert(
id < (
int) cache_info->number_threads);
4432 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4433 cache_info->nexus_info[
id],exception);
4493MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4494 const ssize_t y,
const size_t columns,
const size_t rows,
4498 *magick_restrict cache_info;
4501 id = GetOpenMPThreadId();
4504 *magick_restrict pixels;
4506 assert(image != (
Image *) NULL);
4507 assert(image->signature == MagickCoreSignature);
4508 assert(image->cache != (Cache) NULL);
4510 assert(cache_info->signature == MagickCoreSignature);
4511 if (cache_info->methods.queue_authentic_pixels_handler !=
4512 (QueueAuthenticPixelsHandler) NULL)
4514 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4515 columns,rows,exception);
4518 assert(
id < (
int) cache_info->number_threads);
4519 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4520 cache_info->nexus_info[
id],exception);
4553static inline MagickOffsetType ReadPixelCacheRegion(
4554 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4555 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4563#if !defined(MAGICKCORE_HAVE_PREAD)
4564 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4565 return((MagickOffsetType) -1);
4567 for (i=0; i < (MagickOffsetType) length; i+=count)
4569#if !defined(MAGICKCORE_HAVE_PREAD)
4570 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4571 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4573 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4574 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4586static MagickBooleanType ReadPixelCacheMetacontent(
4607 if (cache_info->metacontent_extent == 0)
4608 return(MagickFalse);
4609 if (nexus_info->authentic_pixel_cache != MagickFalse)
4611 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4612 return(MagickFalse);
4613 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4614 nexus_info->region.x;
4615 length=(MagickSizeType) nexus_info->region.width*
4616 cache_info->metacontent_extent;
4617 extent=length*nexus_info->region.height;
4618 rows=nexus_info->region.height;
4620 q=(
unsigned char *) nexus_info->metacontent;
4621 switch (cache_info->type)
4632 if ((cache_info->columns == nexus_info->region.width) &&
4633 (extent == (MagickSizeType) ((
size_t) extent)))
4638 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4639 cache_info->metacontent_extent;
4640 for (y=0; y < (ssize_t) rows; y++)
4642 (void) memcpy(q,p,(
size_t) length);
4643 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4644 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4653 LockSemaphoreInfo(cache_info->file_semaphore);
4654 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4656 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4657 cache_info->cache_filename);
4658 UnlockSemaphoreInfo(cache_info->file_semaphore);
4659 return(MagickFalse);
4661 if ((cache_info->columns == nexus_info->region.width) &&
4662 (extent <= MagickMaxBufferExtent))
4667 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4668 for (y=0; y < (ssize_t) rows; y++)
4670 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4671 (MagickOffsetType) extent*(MagickOffsetType)
4672 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4673 (MagickOffsetType) cache_info->metacontent_extent,length,
4674 (
unsigned char *) q);
4675 if (count != (MagickOffsetType) length)
4677 offset+=(MagickOffsetType) cache_info->columns;
4678 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4680 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4681 (void) ClosePixelCacheOnDisk(cache_info);
4682 UnlockSemaphoreInfo(cache_info->file_semaphore);
4685 case DistributedCache:
4693 LockSemaphoreInfo(cache_info->file_semaphore);
4694 region=nexus_info->region;
4695 if ((cache_info->columns != nexus_info->region.width) ||
4696 (extent > MagickMaxBufferExtent))
4703 for (y=0; y < (ssize_t) rows; y++)
4706 cache_info->server_info,®ion,length,(
unsigned char *) q);
4707 if (count != (MagickOffsetType) length)
4709 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4712 UnlockSemaphoreInfo(cache_info->file_semaphore);
4718 if (y < (ssize_t) rows)
4720 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4721 cache_info->cache_filename);
4722 return(MagickFalse);
4724 if ((cache_info->debug != MagickFalse) &&
4725 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4726 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4727 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4728 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4729 nexus_info->region.x,(
double) nexus_info->region.y);
4761static MagickBooleanType ReadPixelCachePixels(
4783 if (nexus_info->authentic_pixel_cache != MagickFalse)
4785 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4786 return(MagickFalse);
4787 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4788 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4789 return(MagickFalse);
4790 offset+=nexus_info->region.x;
4791 number_channels=cache_info->number_channels;
4792 length=(MagickSizeType) number_channels*nexus_info->region.width*
4794 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4795 return(MagickFalse);
4796 rows=nexus_info->region.height;
4798 if ((extent == 0) || ((extent/length) != rows))
4799 return(MagickFalse);
4801 q=nexus_info->pixels;
4802 switch (cache_info->type)
4813 if ((cache_info->columns == nexus_info->region.width) &&
4814 (extent == (MagickSizeType) ((
size_t) extent)))
4819 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4821 for (y=0; y < (ssize_t) rows; y++)
4823 (void) memcpy(q,p,(
size_t) length);
4824 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4825 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4834 LockSemaphoreInfo(cache_info->file_semaphore);
4835 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4837 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4838 cache_info->cache_filename);
4839 UnlockSemaphoreInfo(cache_info->file_semaphore);
4840 return(MagickFalse);
4842 if ((cache_info->columns == nexus_info->region.width) &&
4843 (extent <= MagickMaxBufferExtent))
4848 for (y=0; y < (ssize_t) rows; y++)
4850 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4851 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4852 sizeof(*q),length,(
unsigned char *) q);
4853 if (count != (MagickOffsetType) length)
4855 offset+=(MagickOffsetType) cache_info->columns;
4856 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4858 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4859 (void) ClosePixelCacheOnDisk(cache_info);
4860 UnlockSemaphoreInfo(cache_info->file_semaphore);
4863 case DistributedCache:
4871 LockSemaphoreInfo(cache_info->file_semaphore);
4872 region=nexus_info->region;
4873 if ((cache_info->columns != nexus_info->region.width) ||
4874 (extent > MagickMaxBufferExtent))
4881 for (y=0; y < (ssize_t) rows; y++)
4884 cache_info->server_info,®ion,length,(
unsigned char *) q);
4885 if (count != (MagickOffsetType) length)
4887 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4890 UnlockSemaphoreInfo(cache_info->file_semaphore);
4896 if (y < (ssize_t) rows)
4898 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4899 cache_info->cache_filename);
4900 return(MagickFalse);
4902 if ((cache_info->debug != MagickFalse) &&
4903 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4904 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4905 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4906 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4907 nexus_info->region.x,(
double) nexus_info->region.y);
4934MagickPrivate Cache ReferencePixelCache(Cache cache)
4937 *magick_restrict cache_info;
4939 assert(cache != (Cache *) NULL);
4941 assert(cache_info->signature == MagickCoreSignature);
4942 LockSemaphoreInfo(cache_info->semaphore);
4943 cache_info->reference_count++;
4944 UnlockSemaphoreInfo(cache_info->semaphore);
4970MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4973 *magick_restrict cache_info;
4975 assert(image != (
const Image *) NULL);
4976 assert(image->signature == MagickCoreSignature);
4977 assert(image->cache != (Cache) NULL);
4979 assert(cache_info->signature == MagickCoreSignature);
4980 cache_info->number_channels=GetPixelChannels(image);
5001MagickPrivate
void ResetCacheAnonymousMemory(
void)
5003 cache_anonymous_memory=0;
5035MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
5036 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
5044 assert(image != (
Image *) NULL);
5045 assert(image->signature == MagickCoreSignature);
5046 if (IsEventLogging() != MagickFalse)
5047 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5048 assert(image->cache != (
void *) NULL);
5049 extent=(MagickSizeType) columns*rows;
5050 if (extent > ((MagickSizeType) image->columns*image->rows))
5051 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5053 image->columns=columns;
5056 cache_info->columns=columns;
5057 cache_info->rows=rows;
5058 return(SyncImagePixelCache(image,exception));
5085MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5088 *magick_restrict cache_info;
5090 GetOneAuthenticPixelFromHandler
5091 get_one_authentic_pixel_from_handler;
5093 GetOneVirtualPixelFromHandler
5094 get_one_virtual_pixel_from_handler;
5099 assert(cache != (Cache) NULL);
5102 assert(cache_info->signature == MagickCoreSignature);
5103 if (IsEventLogging() != MagickFalse)
5104 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5105 cache_info->filename);
5106 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5107 cache_info->methods.get_virtual_pixel_handler=
5108 cache_methods->get_virtual_pixel_handler;
5109 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5110 cache_info->methods.destroy_pixel_handler=
5111 cache_methods->destroy_pixel_handler;
5112 if (cache_methods->get_virtual_metacontent_from_handler !=
5113 (GetVirtualMetacontentFromHandler) NULL)
5114 cache_info->methods.get_virtual_metacontent_from_handler=
5115 cache_methods->get_virtual_metacontent_from_handler;
5116 if (cache_methods->get_authentic_pixels_handler !=
5117 (GetAuthenticPixelsHandler) NULL)
5118 cache_info->methods.get_authentic_pixels_handler=
5119 cache_methods->get_authentic_pixels_handler;
5120 if (cache_methods->queue_authentic_pixels_handler !=
5121 (QueueAuthenticPixelsHandler) NULL)
5122 cache_info->methods.queue_authentic_pixels_handler=
5123 cache_methods->queue_authentic_pixels_handler;
5124 if (cache_methods->sync_authentic_pixels_handler !=
5125 (SyncAuthenticPixelsHandler) NULL)
5126 cache_info->methods.sync_authentic_pixels_handler=
5127 cache_methods->sync_authentic_pixels_handler;
5128 if (cache_methods->get_authentic_pixels_from_handler !=
5129 (GetAuthenticPixelsFromHandler) NULL)
5130 cache_info->methods.get_authentic_pixels_from_handler=
5131 cache_methods->get_authentic_pixels_from_handler;
5132 if (cache_methods->get_authentic_metacontent_from_handler !=
5133 (GetAuthenticMetacontentFromHandler) NULL)
5134 cache_info->methods.get_authentic_metacontent_from_handler=
5135 cache_methods->get_authentic_metacontent_from_handler;
5136 get_one_virtual_pixel_from_handler=
5137 cache_info->methods.get_one_virtual_pixel_from_handler;
5138 if (get_one_virtual_pixel_from_handler !=
5139 (GetOneVirtualPixelFromHandler) NULL)
5140 cache_info->methods.get_one_virtual_pixel_from_handler=
5141 cache_methods->get_one_virtual_pixel_from_handler;
5142 get_one_authentic_pixel_from_handler=
5143 cache_methods->get_one_authentic_pixel_from_handler;
5144 if (get_one_authentic_pixel_from_handler !=
5145 (GetOneAuthenticPixelFromHandler) NULL)
5146 cache_info->methods.get_one_authentic_pixel_from_handler=
5147 cache_methods->get_one_authentic_pixel_from_handler;
5188static inline MagickBooleanType AcquireCacheNexusPixels(
5189 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5192 if (length != (MagickSizeType) ((
size_t) length))
5194 (void) ThrowMagickException(exception,GetMagickModule(),
5195 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5196 cache_info->filename);
5197 return(MagickFalse);
5199 nexus_info->length=0;
5200 nexus_info->mapped=MagickFalse;
5201 if (cache_anonymous_memory <= 0)
5203 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5205 if (nexus_info->cache != (Quantum *) NULL)
5206 (
void) memset(nexus_info->cache,0,(
size_t) length);
5210 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5211 if (nexus_info->cache != (Quantum *) NULL)
5212 nexus_info->mapped=MagickTrue;
5214 if (nexus_info->cache == (Quantum *) NULL)
5216 (void) ThrowMagickException(exception,GetMagickModule(),
5217 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5218 cache_info->filename);
5219 return(MagickFalse);
5221 nexus_info->length=length;
5225static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5228 if (nexus_info->length < CACHE_LINE_SIZE)
5230 if (mode == ReadMode)
5232 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5236 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5239static Quantum *SetPixelCacheNexusPixels(
5240 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5241 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5242 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5252 assert(cache_info != (
const CacheInfo *) NULL);
5253 assert(cache_info->signature == MagickCoreSignature);
5254 if (cache_info->type == UndefinedCache)
5255 return((Quantum *) NULL);
5256 assert(nexus_info->signature == MagickCoreSignature);
5257 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5258 if ((width == 0) || (height == 0))
5260 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5261 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5262 return((Quantum *) NULL);
5264 if (((MagickSizeType) width > cache_info->width_limit) ||
5265 ((MagickSizeType) height > cache_info->height_limit))
5267 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5268 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5269 return((Quantum *) NULL);
5271 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5272 (IsValidPixelOffset(y,height) == MagickFalse))
5274 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5275 "InvalidPixel",
"`%s'",cache_info->filename);
5276 return((Quantum *) NULL);
5278 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5279 (buffered == MagickFalse))
5281 if (((x >= 0) && (y >= 0) &&
5282 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5283 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5284 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5292 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5293 return((Quantum *) NULL);
5294 offset=y*(MagickOffsetType) cache_info->columns+x;
5295 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5296 cache_info->number_channels*offset;
5297 nexus_info->metacontent=(
void *) NULL;
5298 if (cache_info->metacontent_extent != 0)
5299 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5300 offset*(MagickOffsetType) cache_info->metacontent_extent;
5301 nexus_info->region.width=width;
5302 nexus_info->region.height=height;
5303 nexus_info->region.x=x;
5304 nexus_info->region.y=y;
5305 nexus_info->authentic_pixel_cache=MagickTrue;
5306 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5307 return(nexus_info->pixels);
5313 number_pixels=(MagickSizeType) width*height;
5314 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5315 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5316 if (cache_info->metacontent_extent != 0)
5317 length+=number_pixels*cache_info->metacontent_extent;
5319 if (nexus_info->cache == (Quantum *) NULL)
5320 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5322 if (nexus_info->length < length)
5324 RelinquishCacheNexusPixels(nexus_info);
5325 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5327 if (status == MagickFalse)
5328 return((Quantum *) NULL);
5329 nexus_info->pixels=nexus_info->cache;
5330 nexus_info->metacontent=(
void *) NULL;
5331 if (cache_info->metacontent_extent != 0)
5332 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5333 cache_info->number_channels*number_pixels);
5334 nexus_info->region.width=width;
5335 nexus_info->region.height=height;
5336 nexus_info->region.x=x;
5337 nexus_info->region.y=y;
5338 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5339 MagickTrue : MagickFalse;
5340 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5341 return(nexus_info->pixels);
5374static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5378 *magick_restrict image_view;
5386 assert(image != (
Image *) NULL);
5387 assert(image->signature == MagickCoreSignature);
5388 if (IsEventLogging() != MagickFalse)
5389 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5390 assert(image->cache != (Cache) NULL);
5391 image->alpha_trait=BlendPixelTrait;
5393 image_view=AcquireVirtualCacheView(image,exception);
5394#if defined(MAGICKCORE_OPENMP_SUPPORT)
5395 #pragma omp parallel for schedule(static) shared(status) \
5396 magick_number_threads(image,image,image->rows,2)
5398 for (y=0; y < (ssize_t) image->rows; y++)
5406 if (status == MagickFalse)
5408 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5409 if (q == (Quantum *) NULL)
5414 for (x=0; x < (ssize_t) image->columns; x++)
5416 SetPixelAlpha(image,alpha,q);
5417 q+=(ptrdiff_t) GetPixelChannels(image);
5419 status=SyncCacheViewAuthenticPixels(image_view,exception);
5421 image_view=DestroyCacheView(image_view);
5425MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5426 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5429 *magick_restrict cache_info;
5434 assert(image != (
Image *) NULL);
5435 assert(image->signature == MagickCoreSignature);
5436 if (IsEventLogging() != MagickFalse)
5437 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5438 assert(image->cache != (Cache) NULL);
5440 assert(cache_info->signature == MagickCoreSignature);
5441 method=cache_info->virtual_pixel_method;
5442 cache_info->virtual_pixel_method=virtual_pixel_method;
5443 if ((image->columns != 0) && (image->rows != 0))
5444 switch (virtual_pixel_method)
5446 case BackgroundVirtualPixelMethod:
5448 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5449 ((image->alpha_trait & BlendPixelTrait) == 0))
5450 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5451 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5452 (IsGrayColorspace(image->colorspace) != MagickFalse))
5453 (void) SetImageColorspace(image,sRGBColorspace,exception);
5456 case TransparentVirtualPixelMethod:
5458 if ((image->alpha_trait & BlendPixelTrait) == 0)
5459 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5468#if defined(MAGICKCORE_OPENCL_SUPPORT)
5493static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5495 assert(cache_info != (
CacheInfo *) NULL);
5496 assert(cache_info->signature == MagickCoreSignature);
5497 if ((cache_info->type != MemoryCache) ||
5498 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5503 LockSemaphoreInfo(cache_info->semaphore);
5504 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5505 UnlockSemaphoreInfo(cache_info->semaphore);
5508MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5511 *magick_restrict cache_info;
5513 assert(image != (
const Image *) NULL);
5515 CopyOpenCLBuffer(cache_info);
5548MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5552 *magick_restrict cache_info;
5560 assert(image != (
Image *) NULL);
5561 assert(image->signature == MagickCoreSignature);
5562 if (image->cache == (Cache) NULL)
5563 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5565 assert(cache_info->signature == MagickCoreSignature);
5566 if (cache_info->type == UndefinedCache)
5567 return(MagickFalse);
5568 if ((image->mask_trait & UpdatePixelTrait) != 0)
5570 if (((image->channels & WriteMaskChannel) != 0) &&
5571 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5572 return(MagickFalse);
5573 if (((image->channels & CompositeMaskChannel) != 0) &&
5574 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5575 return(MagickFalse);
5577 if (nexus_info->authentic_pixel_cache != MagickFalse)
5579 if (image->taint == MagickFalse)
5580 image->taint=MagickTrue;
5583 assert(cache_info->signature == MagickCoreSignature);
5584 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5585 if ((cache_info->metacontent_extent != 0) &&
5586 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5587 return(MagickFalse);
5588 if ((status != MagickFalse) && (image->taint == MagickFalse))
5589 image->taint=MagickTrue;
5620static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5624 *magick_restrict cache_info;
5627 id = GetOpenMPThreadId();
5632 assert(image != (
Image *) NULL);
5633 assert(image->signature == MagickCoreSignature);
5634 assert(image->cache != (Cache) NULL);
5636 assert(cache_info->signature == MagickCoreSignature);
5637 assert(
id < (
int) cache_info->number_threads);
5638 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5670MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5674 *magick_restrict cache_info;
5677 id = GetOpenMPThreadId();
5682 assert(image != (
Image *) NULL);
5683 assert(image->signature == MagickCoreSignature);
5684 assert(image->cache != (Cache) NULL);
5686 assert(cache_info->signature == MagickCoreSignature);
5687 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5689 status=cache_info->methods.sync_authentic_pixels_handler(image,
5693 assert(
id < (
int) cache_info->number_threads);
5694 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5726MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5730 *magick_restrict cache_info;
5732 assert(image != (
Image *) NULL);
5734 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5735 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5766static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5786 if (cache_info->metacontent_extent == 0)
5787 return(MagickFalse);
5788 if (nexus_info->authentic_pixel_cache != MagickFalse)
5790 if (nexus_info->metacontent == (
unsigned char *) NULL)
5791 return(MagickFalse);
5792 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5793 return(MagickFalse);
5794 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5795 nexus_info->region.x;
5796 length=(MagickSizeType) nexus_info->region.width*
5797 cache_info->metacontent_extent;
5798 extent=(MagickSizeType) length*nexus_info->region.height;
5799 rows=nexus_info->region.height;
5801 p=(
unsigned char *) nexus_info->metacontent;
5802 switch (cache_info->type)
5813 if ((cache_info->columns == nexus_info->region.width) &&
5814 (extent == (MagickSizeType) ((
size_t) extent)))
5819 q=(
unsigned char *) cache_info->metacontent+offset*
5820 (MagickOffsetType) cache_info->metacontent_extent;
5821 for (y=0; y < (ssize_t) rows; y++)
5823 (void) memcpy(q,p,(
size_t) length);
5824 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5825 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5834 LockSemaphoreInfo(cache_info->file_semaphore);
5835 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5837 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5838 cache_info->cache_filename);
5839 UnlockSemaphoreInfo(cache_info->file_semaphore);
5840 return(MagickFalse);
5842 if ((cache_info->columns == nexus_info->region.width) &&
5843 (extent <= MagickMaxBufferExtent))
5848 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5849 for (y=0; y < (ssize_t) rows; y++)
5851 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5852 (MagickOffsetType) extent*(MagickOffsetType)
5853 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5854 (MagickOffsetType) cache_info->metacontent_extent,length,
5855 (
const unsigned char *) p);
5856 if (count != (MagickOffsetType) length)
5858 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5859 offset+=(MagickOffsetType) cache_info->columns;
5861 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5862 (void) ClosePixelCacheOnDisk(cache_info);
5863 UnlockSemaphoreInfo(cache_info->file_semaphore);
5866 case DistributedCache:
5874 LockSemaphoreInfo(cache_info->file_semaphore);
5875 region=nexus_info->region;
5876 if ((cache_info->columns != nexus_info->region.width) ||
5877 (extent > MagickMaxBufferExtent))
5884 for (y=0; y < (ssize_t) rows; y++)
5887 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5888 if (count != (MagickOffsetType) length)
5890 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5893 UnlockSemaphoreInfo(cache_info->file_semaphore);
5899 if (y < (ssize_t) rows)
5901 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5902 cache_info->cache_filename);
5903 return(MagickFalse);
5905 if ((cache_info->debug != MagickFalse) &&
5906 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5907 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5908 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5909 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5910 nexus_info->region.x,(
double) nexus_info->region.y);
5942static MagickBooleanType WritePixelCachePixels(
5963 if (nexus_info->authentic_pixel_cache != MagickFalse)
5965 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5966 return(MagickFalse);
5967 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5968 nexus_info->region.x;
5969 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5971 extent=length*nexus_info->region.height;
5972 rows=nexus_info->region.height;
5974 p=nexus_info->pixels;
5975 switch (cache_info->type)
5986 if ((cache_info->columns == nexus_info->region.width) &&
5987 (extent == (MagickSizeType) ((
size_t) extent)))
5992 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5994 for (y=0; y < (ssize_t) rows; y++)
5996 (void) memcpy(q,p,(
size_t) length);
5997 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5998 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
6007 LockSemaphoreInfo(cache_info->file_semaphore);
6008 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
6010 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
6011 cache_info->cache_filename);
6012 UnlockSemaphoreInfo(cache_info->file_semaphore);
6013 return(MagickFalse);
6015 if ((cache_info->columns == nexus_info->region.width) &&
6016 (extent <= MagickMaxBufferExtent))
6021 for (y=0; y < (ssize_t) rows; y++)
6023 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
6024 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
6025 sizeof(*p),length,(
const unsigned char *) p);
6026 if (count != (MagickOffsetType) length)
6028 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6029 offset+=(MagickOffsetType) cache_info->columns;
6031 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6032 (void) ClosePixelCacheOnDisk(cache_info);
6033 UnlockSemaphoreInfo(cache_info->file_semaphore);
6036 case DistributedCache:
6044 LockSemaphoreInfo(cache_info->file_semaphore);
6045 region=nexus_info->region;
6046 if ((cache_info->columns != nexus_info->region.width) ||
6047 (extent > MagickMaxBufferExtent))
6054 for (y=0; y < (ssize_t) rows; y++)
6057 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6058 if (count != (MagickOffsetType) length)
6060 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6063 UnlockSemaphoreInfo(cache_info->file_semaphore);
6069 if (y < (ssize_t) rows)
6071 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6072 cache_info->cache_filename);
6073 return(MagickFalse);
6075 if ((cache_info->debug != MagickFalse) &&
6076 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6077 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6078 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6079 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6080 nexus_info->region.x,(
double) nexus_info->region.y);