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)
113 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
117 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
118 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
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,
128 const ssize_t,
const ssize_t,Quantum *,ExceptionInfo *),
129 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
130 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
131 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
133 ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
134 NexusInfo *magick_restrict,ExceptionInfo *),
135 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
136 WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
138 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
142 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
143 const size_t,ExceptionInfo *),
144 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
145 const size_t,ExceptionInfo *),
146 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
147 const ssize_t,
const ssize_t,
const size_t,
const size_t,
148 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
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));
200 if (cache_info == (CacheInfo *) NULL)
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)));
272 if (nexus_info == (NexusInfo **) NULL)
273 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
274 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
275 2*
sizeof(**nexus_info));
276 if (*nexus_info == (NexusInfo *) NULL)
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,
318 ExceptionInfo *exception)
321 *magick_restrict cache_info;
323 assert(image != (
const Image *) NULL);
324 assert(image->signature == MagickCoreSignature);
325 assert(exception != (ExceptionInfo *) NULL);
326 assert(exception->signature == MagickCoreSignature);
327 assert(image->cache != (Cache) NULL);
329 cache_info=(CacheInfo *) image->cache;
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,
419 NexusInfo *nexus_info,ExceptionInfo *exception)
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))
440 cache_info=(CacheInfo *) image->cache;
441 if (cache_info == (CacheInfo *) NULL)
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);
529 cache_info=(
const CacheInfo *) cache;
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);
571 source_info=(CacheInfo *) clone;
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);
577 cache_info=(CacheInfo *) cache;
578 assert(cache_info->signature == MagickCoreSignature);
579 source_info->methods=cache_info->methods;
611static MagickBooleanType ClonePixelCacheOnDisk(
612 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
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-
671 count=MagickRead(cache_info->file,buffer,length);
674 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
682 while (offset < count)
684 number_bytes=MagickWrite(clone_info->file,buffer+offset,(
size_t) (count-
686 if (number_bytes <= 0)
688 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
691 offset+=number_bytes;
693 extent+=(MagickSizeType) offset;
696 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
697 return(extent == cache_info->length ? MagickTrue : MagickFalse);
700#if defined(MAGICKCORE_OPENMP_SUPPORT)
701static inline int GetCacheNumberThreads(
const CacheInfo *source,
702 const CacheInfo *destination,
const size_t chunk,
const int factor)
705 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
706 number_threads = 1UL,
707 workload_factor = 64UL << factor;
712 number_threads=(chunk <= workload_factor) ? 1UL :
713 (chunk >= (workload_factor << 6)) ? max_threads :
714 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
718 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
719 ((destination->type != MemoryCache) && (destination->type != MapCache)))
720 number_threads=MagickMin(number_threads,4);
721 return((
int) number_threads);
725static MagickBooleanType ClonePixelCacheRepository(
726 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
727 ExceptionInfo *exception)
729#define cache_number_threads(source,destination,chunk,factor) \
730 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
737 **magick_restrict cache_nexus,
738 **magick_restrict clone_nexus;
746 assert(cache_info != (CacheInfo *) NULL);
747 assert(clone_info != (CacheInfo *) NULL);
748 assert(exception != (ExceptionInfo *) NULL);
749 if (cache_info->type == PingCache)
751 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
752 if ((cache_info->storage_class == clone_info->storage_class) &&
753 (cache_info->colorspace == clone_info->colorspace) &&
754 (cache_info->alpha_trait == clone_info->alpha_trait) &&
755 (cache_info->channels == clone_info->channels) &&
756 (cache_info->columns == clone_info->columns) &&
757 (cache_info->rows == clone_info->rows) &&
758 (cache_info->number_channels == clone_info->number_channels) &&
759 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
760 (cache_info->metacontent_extent == clone_info->metacontent_extent))
765 if (((cache_info->type == MemoryCache) ||
766 (cache_info->type == MapCache)) &&
767 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
769 (void) memcpy(clone_info->pixels,cache_info->pixels,
770 cache_info->number_channels*cache_info->columns*cache_info->rows*
771 sizeof(*cache_info->pixels));
772 if ((cache_info->metacontent_extent != 0) &&
773 (clone_info->metacontent_extent != 0))
774 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
775 cache_info->columns*cache_info->rows*
776 clone_info->metacontent_extent*
sizeof(
unsigned char));
779 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
780 return(ClonePixelCacheOnDisk(cache_info,clone_info));
785 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
786 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
787 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
788 optimize=(cache_info->number_channels == clone_info->number_channels) &&
789 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
790 MagickTrue : MagickFalse;
791 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
792 clone_info->number_channels*clone_info->columns);
794#if defined(MAGICKCORE_OPENMP_SUPPORT)
795 #pragma omp parallel for schedule(static) shared(status) \
796 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
798 for (y=0; y < (ssize_t) cache_info->rows; y++)
801 id = GetOpenMPThreadId();
809 if (status == MagickFalse)
811 if (y >= (ssize_t) clone_info->rows)
813 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
814 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
815 if (pixels == (Quantum *) NULL)
817 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
818 if (status == MagickFalse)
820 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
821 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
822 if (pixels == (Quantum *) NULL)
824 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
825 if (optimize != MagickFalse)
826 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
839 p=cache_nexus[id]->pixels;
840 q=clone_nexus[id]->pixels;
841 for (x=0; x < (ssize_t) cache_info->columns; x++)
846 if (x == (ssize_t) clone_info->columns)
848 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
856 channel=clone_info->channel_map[i].channel;
857 traits=cache_info->channel_map[channel].traits;
858 if (traits != UndefinedPixelTrait)
859 *q=*(p+cache_info->channel_map[channel].offset);
862 p+=(ptrdiff_t) cache_info->number_channels;
865 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
867 if ((cache_info->metacontent_extent != 0) &&
868 (clone_info->metacontent_extent != 0))
873 length=(size_t) MagickMin(cache_info->metacontent_extent,
874 clone_info->metacontent_extent);
875#if defined(MAGICKCORE_OPENMP_SUPPORT)
876 #pragma omp parallel for schedule(static) shared(status) \
877 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
879 for (y=0; y < (ssize_t) cache_info->rows; y++)
882 id = GetOpenMPThreadId();
887 if (status == MagickFalse)
889 if (y >= (ssize_t) clone_info->rows)
891 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
892 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
893 if (pixels == (Quantum *) NULL)
895 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
896 if (status == MagickFalse)
898 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
899 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
900 if (pixels == (Quantum *) NULL)
902 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
903 (cache_nexus[
id]->metacontent != (
void *) NULL))
904 (void) memcpy(clone_nexus[
id]->metacontent,
905 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
906 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
909 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
910 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
911 if (cache_info->debug != MagickFalse)
914 message[MagickPathExtent];
916 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
917 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
918 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
919 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
946static void DestroyImagePixelCache(Image *image)
948 assert(image != (Image *) NULL);
949 assert(image->signature == MagickCoreSignature);
950 if (IsEventLogging() != MagickFalse)
951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
952 if (image->cache != (
void *) NULL)
953 image->cache=DestroyPixelCache(image->cache);
978MagickExport
void DestroyImagePixels(Image *image)
981 *magick_restrict cache_info;
983 assert(image != (
const Image *) NULL);
984 assert(image->signature == MagickCoreSignature);
985 if (IsEventLogging() != MagickFalse)
986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
987 assert(image->cache != (Cache) NULL);
988 cache_info=(CacheInfo *) image->cache;
989 assert(cache_info->signature == MagickCoreSignature);
990 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
992 cache_info->methods.destroy_pixel_handler(image);
995 image->cache=DestroyPixelCache(image->cache);
1021static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
1027 if (cache_info->file != -1)
1029 status=close_utf8(cache_info->file);
1030 cache_info->file=(-1);
1031 RelinquishMagickResource(FileResource,1);
1033 return(status == -1 ? MagickFalse : MagickTrue);
1036static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1038 switch (cache_info->type)
1042 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1043#if defined(MAGICKCORE_OPENCL_SUPPORT)
1044 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1046 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1048 cache_info->pixels=(Quantum *) NULL;
1052 if (cache_info->mapped == MagickFalse)
1053 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1054 cache_info->pixels);
1057 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1058 cache_info->pixels=(Quantum *) NULL;
1060 RelinquishMagickResource(MemoryResource,cache_info->length);
1065 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1066 cache_info->pixels=(Quantum *) NULL;
1067 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1068 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1069 *cache_info->cache_filename=
'\0';
1070 RelinquishMagickResource(MapResource,cache_info->length);
1075 if (cache_info->file != -1)
1076 (void) ClosePixelCacheOnDisk(cache_info);
1077 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1078 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1079 *cache_info->cache_filename=
'\0';
1080 RelinquishMagickResource(DiskResource,cache_info->length);
1083 case DistributedCache:
1085 *cache_info->cache_filename=
'\0';
1086 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1087 cache_info->server_info);
1093 cache_info->type=UndefinedCache;
1094 cache_info->mapped=MagickFalse;
1095 cache_info->metacontent=(
void *) NULL;
1098MagickPrivate Cache DestroyPixelCache(Cache cache)
1101 *magick_restrict cache_info;
1103 assert(cache != (Cache) NULL);
1104 cache_info=(CacheInfo *) cache;
1105 assert(cache_info->signature == MagickCoreSignature);
1106 if (IsEventLogging() != MagickFalse)
1107 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1108 cache_info->filename);
1109 LockSemaphoreInfo(cache_info->semaphore);
1110 cache_info->reference_count--;
1111 if (cache_info->reference_count != 0)
1113 UnlockSemaphoreInfo(cache_info->semaphore);
1114 return((Cache) NULL);
1116 UnlockSemaphoreInfo(cache_info->semaphore);
1117 if (cache_info->debug != MagickFalse)
1120 message[MagickPathExtent];
1122 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1123 cache_info->filename);
1124 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1126 RelinquishPixelCachePixels(cache_info);
1127 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1128 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1129 cache_info->server_info);
1130 if (cache_info->nexus_info != (NexusInfo **) NULL)
1131 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1132 cache_info->number_threads);
1133 if (cache_info->random_info != (RandomInfo *) NULL)
1134 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1136 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1138 RelinquishSemaphoreInfo(&cache_info->semaphore);
1139 cache_info->signature=(~MagickCoreSignature);
1140 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1171static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1173 if (nexus_info->mapped == MagickFalse)
1174 (void) RelinquishAlignedMemory(nexus_info->cache);
1176 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1177 nexus_info->cache=(Quantum *) NULL;
1178 nexus_info->pixels=(Quantum *) NULL;
1179 nexus_info->metacontent=(
void *) NULL;
1180 nexus_info->length=0;
1181 nexus_info->mapped=MagickFalse;
1184MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1185 const size_t number_threads)
1190 assert(nexus_info != (NexusInfo **) NULL);
1191 for (i=0; i < (ssize_t) (2*number_threads); i++)
1193 if (nexus_info[i]->cache != (Quantum *) NULL)
1194 RelinquishCacheNexusPixels(nexus_info[i]);
1195 nexus_info[i]->signature=(~MagickCoreSignature);
1197 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1198 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1227MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1230 *magick_restrict cache_info;
1233 id = GetOpenMPThreadId();
1235 assert(image != (
const Image *) NULL);
1236 assert(image->signature == MagickCoreSignature);
1237 assert(image->cache != (Cache) NULL);
1238 cache_info=(CacheInfo *) image->cache;
1239 assert(cache_info->signature == MagickCoreSignature);
1240 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1241 (GetAuthenticMetacontentFromHandler) NULL)
1246 metacontent=cache_info->methods.
1247 get_authentic_metacontent_from_handler(image);
1248 return(metacontent);
1250 assert(
id < (
int) cache_info->number_threads);
1251 return(cache_info->nexus_info[
id]->metacontent);
1278static void *GetAuthenticMetacontentFromCache(
const Image *image)
1281 *magick_restrict cache_info;
1284 id = GetOpenMPThreadId();
1286 assert(image != (
const Image *) NULL);
1287 assert(image->signature == MagickCoreSignature);
1288 assert(image->cache != (Cache) NULL);
1289 cache_info=(CacheInfo *) image->cache;
1290 assert(cache_info->signature == MagickCoreSignature);
1291 assert(
id < (
int) cache_info->number_threads);
1292 return(cache_info->nexus_info[
id]->metacontent);
1295#if defined(MAGICKCORE_OPENCL_SUPPORT)
1324MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1325 MagickCLDevice device,ExceptionInfo *exception)
1328 *magick_restrict cache_info;
1330 assert(image != (
const Image *) NULL);
1331 assert(device != (
const MagickCLDevice) NULL);
1332 cache_info=(CacheInfo *) image->cache;
1333 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1335 (void) SyncImagePixelCache((Image *) image,exception);
1336 cache_info=(CacheInfo *) image->cache;
1338 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1339 return((cl_mem) NULL);
1340 LockSemaphoreInfo(cache_info->semaphore);
1341 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1342 (cache_info->opencl->device->context != device->context))
1343 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1344 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1346 assert(cache_info->pixels != (Quantum *) NULL);
1347 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1348 cache_info->length);
1350 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1351 RetainOpenCLMemObject(cache_info->opencl->buffer);
1352 UnlockSemaphoreInfo(cache_info->semaphore);
1353 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1354 return((cl_mem) NULL);
1355 assert(cache_info->opencl->pixels == cache_info->pixels);
1356 return(cache_info->opencl->buffer);
1395MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
const ssize_t x,
1396 const ssize_t y,
const size_t columns,
const size_t rows,NexusInfo *nexus_info,
1397 ExceptionInfo *exception)
1400 *magick_restrict cache_info;
1403 *magick_restrict pixels;
1408 assert(image != (Image *) NULL);
1409 assert(image->signature == MagickCoreSignature);
1410 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1411 nexus_info,exception);
1412 if (pixels == (Quantum *) NULL)
1413 return((Quantum *) NULL);
1414 cache_info=(CacheInfo *) image->cache;
1415 assert(cache_info->signature == MagickCoreSignature);
1416 if (nexus_info->authentic_pixel_cache != MagickFalse)
1418 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1419 return((Quantum *) NULL);
1420 if (cache_info->metacontent_extent != 0)
1421 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1422 return((Quantum *) NULL);
1449static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1452 *magick_restrict cache_info;
1455 id = GetOpenMPThreadId();
1457 assert(image != (
const Image *) NULL);
1458 assert(image->signature == MagickCoreSignature);
1459 assert(image->cache != (Cache) NULL);
1460 cache_info=(CacheInfo *) image->cache;
1461 assert(cache_info->signature == MagickCoreSignature);
1462 assert(
id < (
int) cache_info->number_threads);
1463 return(cache_info->nexus_info[
id]->pixels);
1490MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1493 *magick_restrict cache_info;
1496 id = GetOpenMPThreadId();
1498 assert(image != (
const Image *) NULL);
1499 assert(image->signature == MagickCoreSignature);
1500 assert(image->cache != (Cache) NULL);
1501 cache_info=(CacheInfo *) image->cache;
1502 assert(cache_info->signature == MagickCoreSignature);
1503 if (cache_info->methods.get_authentic_pixels_from_handler !=
1504 (GetAuthenticPixelsFromHandler) NULL)
1505 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1506 assert(
id < (
int) cache_info->number_threads);
1507 return(cache_info->nexus_info[
id]->pixels);
1555MagickExport Quantum *GetAuthenticPixels(Image *image,
const ssize_t x,
1556 const ssize_t y,
const size_t columns,
const size_t rows,
1557 ExceptionInfo *exception)
1560 *magick_restrict cache_info;
1563 id = GetOpenMPThreadId();
1568 assert(image != (Image *) NULL);
1569 assert(image->signature == MagickCoreSignature);
1570 assert(image->cache != (Cache) NULL);
1571 cache_info=(CacheInfo *) image->cache;
1572 assert(cache_info->signature == MagickCoreSignature);
1573 if (cache_info->methods.get_authentic_pixels_handler !=
1574 (GetAuthenticPixelsHandler) NULL)
1576 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1580 assert(
id < (
int) cache_info->number_threads);
1581 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1582 cache_info->nexus_info[
id],exception);
1617static Quantum *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1618 const ssize_t y,
const size_t columns,
const size_t rows,
1619 ExceptionInfo *exception)
1622 *magick_restrict cache_info;
1625 id = GetOpenMPThreadId();
1628 *magick_restrict pixels;
1630 assert(image != (
const Image *) NULL);
1631 assert(image->signature == MagickCoreSignature);
1632 assert(image->cache != (Cache) NULL);
1633 cache_info=(CacheInfo *) image->cache;
1634 if (cache_info == (Cache) NULL)
1635 return((Quantum *) NULL);
1636 assert(cache_info->signature == MagickCoreSignature);
1637 assert(
id < (
int) cache_info->number_threads);
1638 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1639 cache_info->nexus_info[
id],exception);
1666MagickExport MagickSizeType GetImageExtent(
const Image *image)
1669 *magick_restrict cache_info;
1672 id = GetOpenMPThreadId();
1674 assert(image != (Image *) NULL);
1675 assert(image->signature == MagickCoreSignature);
1676 if (IsEventLogging() != MagickFalse)
1677 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1678 assert(image->cache != (Cache) NULL);
1679 cache_info=(CacheInfo *) image->cache;
1680 assert(cache_info->signature == MagickCoreSignature);
1681 assert(
id < (
int) cache_info->number_threads);
1682 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1715static MagickBooleanType GetDynamicThrottlePolicy(
void)
1717 static MagickBooleanType
1718 check_policy = MagickTrue;
1720 static MagickBooleanType
1721 dynamic_throttle = MagickFalse;
1723 if (check_policy != MagickFalse)
1725 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1726 if (value != (
char *) NULL)
1728 dynamic_throttle=IsStringTrue(value);
1729 value=DestroyString(value);
1731 check_policy=MagickFalse;
1733 return(dynamic_throttle);
1736static inline MagickBooleanType ValidatePixelCacheMorphology(
1737 const Image *magick_restrict image)
1740 *magick_restrict cache_info;
1742 const PixelChannelMap
1749 cache_info=(CacheInfo *) image->cache;
1750 p=image->channel_map;
1751 q=cache_info->channel_map;
1752 if ((image->storage_class != cache_info->storage_class) ||
1753 (image->colorspace != cache_info->colorspace) ||
1754 (image->alpha_trait != cache_info->alpha_trait) ||
1755 (image->channels != cache_info->channels) ||
1756 (image->columns != cache_info->columns) ||
1757 (image->rows != cache_info->rows) ||
1758 (image->number_channels != cache_info->number_channels) ||
1759 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1760 (image->metacontent_extent != cache_info->metacontent_extent) ||
1761 (cache_info->nexus_info == (NexusInfo **) NULL))
1762 return(MagickFalse);
1766static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1767 ExceptionInfo *exception)
1770 *magick_restrict cache_info;
1774 status = MagickTrue;
1776 static MagickSizeType
1777 cpu_throttle = MagickResourceInfinity,
1780 if (IsImageTTLExpired(image) != MagickFalse)
1785 (void) ThrowMagickException(exception,GetMagickModule(),
1786 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1787 return((Cache) NULL);
1789 if (cpu_throttle == MagickResourceInfinity)
1790 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1791 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1804#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1805 if (getloadavg(&load_average,1) != 1)
1808 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1809 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1811 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1812 MagickDelay(cpu_throttle);
1814 LockSemaphoreInfo(image->semaphore);
1815 assert(image->cache != (Cache) NULL);
1816 cache_info=(CacheInfo *) image->cache;
1817#if defined(MAGICKCORE_OPENCL_SUPPORT)
1818 CopyOpenCLBuffer(cache_info);
1820 destroy=MagickFalse;
1821 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1823 LockSemaphoreInfo(cache_info->semaphore);
1824 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1835 clone_image=(*image);
1836 clone_image.semaphore=AcquireSemaphoreInfo();
1837 clone_image.reference_count=1;
1838 clone_image.cache=ClonePixelCache(cache_info);
1839 clone_info=(CacheInfo *) clone_image.cache;
1840 status=OpenPixelCache(&clone_image,IOMode,exception);
1841 if (status == MagickFalse)
1842 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1845 if (clone != MagickFalse)
1846 status=ClonePixelCacheRepository(clone_info,cache_info,
1848 if (status == MagickFalse)
1849 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1853 image->cache=clone_info;
1856 RelinquishSemaphoreInfo(&clone_image.semaphore);
1858 UnlockSemaphoreInfo(cache_info->semaphore);
1860 if (destroy != MagickFalse)
1861 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1862 if (status != MagickFalse)
1867 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1869 image->type=UndefinedType;
1870 status=OpenPixelCache(image,IOMode,exception);
1871 cache_info=(CacheInfo *) image->cache;
1872 if (cache_info->file != -1)
1873 (void) ClosePixelCacheOnDisk(cache_info);
1876 UnlockSemaphoreInfo(image->semaphore);
1877 if (status == MagickFalse)
1878 return((Cache) NULL);
1879 return(image->cache);
1905MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1908 *magick_restrict cache_info;
1910 assert(image != (Image *) NULL);
1911 assert(image->signature == MagickCoreSignature);
1912 assert(image->cache != (Cache) NULL);
1913 cache_info=(CacheInfo *) image->cache;
1914 assert(cache_info->signature == MagickCoreSignature);
1915 return(cache_info->type);
1949static inline MagickBooleanType CopyPixel(
const Image *image,
1950 const Quantum *source,Quantum *destination)
1955 if (source == (
const Quantum *) NULL)
1957 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1958 destination[GreenPixelChannel]=ClampToQuantum(
1959 image->background_color.green);
1960 destination[BluePixelChannel]=ClampToQuantum(
1961 image->background_color.blue);
1962 destination[BlackPixelChannel]=ClampToQuantum(
1963 image->background_color.black);
1964 destination[AlphaPixelChannel]=ClampToQuantum(
1965 image->background_color.alpha);
1966 return(MagickFalse);
1968 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1970 PixelChannel channel = GetPixelChannelChannel(image,i);
1971 destination[channel]=source[i];
1976MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1977 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1980 *magick_restrict cache_info;
1985 assert(image != (Image *) NULL);
1986 assert(image->signature == MagickCoreSignature);
1987 assert(image->cache != (Cache) NULL);
1988 cache_info=(CacheInfo *) image->cache;
1989 assert(cache_info->signature == MagickCoreSignature);
1990 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1991 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1992 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1993 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1994 return(CopyPixel(image,q,pixel));
2028static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2029 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2032 *magick_restrict cache_info;
2035 id = GetOpenMPThreadId();
2040 assert(image != (
const Image *) NULL);
2041 assert(image->signature == MagickCoreSignature);
2042 assert(image->cache != (Cache) NULL);
2043 cache_info=(CacheInfo *) image->cache;
2044 assert(cache_info->signature == MagickCoreSignature);
2045 assert(
id < (
int) cache_info->number_threads);
2046 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2047 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2049 return(CopyPixel(image,q,pixel));
2083MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2084 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2087 *magick_restrict cache_info;
2090 id = GetOpenMPThreadId();
2095 assert(image != (
const Image *) NULL);
2096 assert(image->signature == MagickCoreSignature);
2097 assert(image->cache != (Cache) NULL);
2098 cache_info=(CacheInfo *) image->cache;
2099 assert(cache_info->signature == MagickCoreSignature);
2100 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2101 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2102 (GetOneVirtualPixelFromHandler) NULL)
2103 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2104 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2105 assert(
id < (
int) cache_info->number_threads);
2106 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2107 1UL,1UL,cache_info->nexus_info[
id],exception);
2108 return(CopyPixel(image,p,pixel));
2145static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2146 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2147 Quantum *pixel,ExceptionInfo *exception)
2150 *magick_restrict cache_info;
2153 id = GetOpenMPThreadId();
2158 assert(image != (
const Image *) NULL);
2159 assert(image->signature == MagickCoreSignature);
2160 assert(image->cache != (Cache) NULL);
2161 cache_info=(CacheInfo *) image->cache;
2162 assert(cache_info->signature == MagickCoreSignature);
2163 assert(
id < (
int) cache_info->number_threads);
2164 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2165 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2166 cache_info->nexus_info[
id],exception);
2167 return(CopyPixel(image,p,pixel));
2204MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2205 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2206 PixelInfo *pixel,ExceptionInfo *exception)
2209 *magick_restrict cache_info;
2212 id = GetOpenMPThreadId();
2217 assert(image != (
const Image *) NULL);
2218 assert(image->signature == MagickCoreSignature);
2219 assert(image->cache != (Cache) NULL);
2220 cache_info=(CacheInfo *) image->cache;
2221 assert(cache_info->signature == MagickCoreSignature);
2222 assert(
id < (
int) cache_info->number_threads);
2223 GetPixelInfo(image,pixel);
2224 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2225 cache_info->nexus_info[
id],exception);
2226 if (p == (
const Quantum *) NULL)
2227 return(MagickFalse);
2228 GetPixelInfoPixel(image,p,pixel);
2254MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2257 *magick_restrict cache_info;
2259 assert(cache != (Cache) NULL);
2260 cache_info=(CacheInfo *) cache;
2261 assert(cache_info->signature == MagickCoreSignature);
2262 if (IsEventLogging() != MagickFalse)
2263 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2264 cache_info->filename);
2265 return(cache_info->colorspace);
2291MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2294 *magick_restrict cache_info;
2296 assert(image != (
const Image *) NULL);
2297 assert(image->signature == MagickCoreSignature);
2298 assert(image->cache != (Cache) NULL);
2299 cache_info=(CacheInfo *) image->cache;
2300 assert(cache_info->signature == MagickCoreSignature);
2301 return(cache_info->cache_filename);
2326MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2328 assert(cache_methods != (CacheMethods *) NULL);
2329 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2330 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2331 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2332 cache_methods->get_virtual_metacontent_from_handler=
2333 GetVirtualMetacontentFromCache;
2334 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2335 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2336 cache_methods->get_authentic_metacontent_from_handler=
2337 GetAuthenticMetacontentFromCache;
2338 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2339 cache_methods->get_one_authentic_pixel_from_handler=
2340 GetOneAuthenticPixelFromCache;
2341 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2342 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2343 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2371MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2372 NexusInfo *magick_restrict nexus_info)
2375 *magick_restrict cache_info;
2380 assert(cache != NULL);
2381 cache_info=(CacheInfo *) cache;
2382 assert(cache_info->signature == MagickCoreSignature);
2383 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2385 return((MagickSizeType) cache_info->columns*cache_info->rows);
2416MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2417 ExceptionInfo *magick_unused(exception))
2420 *magick_restrict cache_info;
2422 assert(image != (
const Image *) NULL);
2423 assert(image->signature == MagickCoreSignature);
2424 assert(image->cache != (Cache) NULL);
2425 assert(length != (MagickSizeType *) NULL);
2426 magick_unreferenced(exception);
2427 cache_info=(CacheInfo *) image->cache;
2428 assert(cache_info->signature == MagickCoreSignature);
2429 *length=cache_info->length;
2430 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2431 return((
void *) NULL);
2432 return((
void *) cache_info->pixels);
2459MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2462 *magick_restrict cache_info;
2464 assert(cache != (Cache) NULL);
2465 cache_info=(CacheInfo *) cache;
2466 assert(cache_info->signature == MagickCoreSignature);
2467 if (IsEventLogging() != MagickFalse)
2468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2469 cache_info->filename);
2470 return(cache_info->storage_class);
2500MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2504 *magick_restrict cache_info;
2506 assert(image != (Image *) NULL);
2507 assert(image->signature == MagickCoreSignature);
2508 if (IsEventLogging() != MagickFalse)
2509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2510 cache_info=(CacheInfo *) image->cache;
2511 assert(cache_info->signature == MagickCoreSignature);
2512 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2513 if (GetImagePixelCacheType(image) == DiskCache)
2514 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2542MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2545 *magick_restrict cache_info;
2547 assert(image != (Image *) NULL);
2548 assert(image->signature == MagickCoreSignature);
2549 assert(image->cache != (Cache) NULL);
2550 cache_info=(CacheInfo *) image->cache;
2551 assert(cache_info->signature == MagickCoreSignature);
2552 return(cache_info->virtual_pixel_method);
2578static const void *GetVirtualMetacontentFromCache(
const Image *image)
2581 *magick_restrict cache_info;
2584 id = GetOpenMPThreadId();
2587 *magick_restrict metacontent;
2589 assert(image != (
const Image *) NULL);
2590 assert(image->signature == MagickCoreSignature);
2591 assert(image->cache != (Cache) NULL);
2592 cache_info=(CacheInfo *) image->cache;
2593 assert(cache_info->signature == MagickCoreSignature);
2594 assert(
id < (
int) cache_info->number_threads);
2595 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2596 cache_info->nexus_info[
id]);
2597 return(metacontent);
2626MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2627 NexusInfo *magick_restrict nexus_info)
2630 *magick_restrict cache_info;
2632 assert(cache != (Cache) NULL);
2633 cache_info=(CacheInfo *) cache;
2634 assert(cache_info->signature == MagickCoreSignature);
2635 if (cache_info->storage_class == UndefinedClass)
2636 return((
void *) NULL);
2637 return(nexus_info->metacontent);
2664MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2667 *magick_restrict cache_info;
2670 id = GetOpenMPThreadId();
2673 *magick_restrict metacontent;
2675 assert(image != (
const Image *) NULL);
2676 assert(image->signature == MagickCoreSignature);
2677 assert(image->cache != (Cache) NULL);
2678 cache_info=(CacheInfo *) image->cache;
2679 assert(cache_info->signature == MagickCoreSignature);
2680 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2682 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2684 if (metacontent != (
const void *) NULL)
2685 return(metacontent);
2687 assert(
id < (
int) cache_info->number_threads);
2688 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2689 cache_info->nexus_info[
id]);
2690 return(metacontent);
2733 0, 48, 12, 60, 3, 51, 15, 63,
2734 32, 16, 44, 28, 35, 19, 47, 31,
2735 8, 56, 4, 52, 11, 59, 7, 55,
2736 40, 24, 36, 20, 43, 27, 39, 23,
2737 2, 50, 14, 62, 1, 49, 13, 61,
2738 34, 18, 46, 30, 33, 17, 45, 29,
2739 10, 58, 6, 54, 9, 57, 5, 53,
2740 42, 26, 38, 22, 41, 25, 37, 21
2743static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2748 index=x+DitherMatrix[x & 0x07]-32L;
2751 if (index >= (ssize_t) columns)
2752 return((ssize_t) columns-1L);
2756static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2761 index=y+DitherMatrix[y & 0x07]-32L;
2764 if (index >= (ssize_t) rows)
2765 return((ssize_t) rows-1L);
2769static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2773 if (x >= (ssize_t) columns)
2774 return((ssize_t) (columns-1));
2778static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2782 if (y >= (ssize_t) rows)
2783 return((ssize_t) (rows-1));
2787static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2788 const MagickOffsetType y)
2790 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2791 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2792 return(MagickFalse);
2796static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2798 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2801static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2803 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2806static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2807 const size_t extent)
2812 modulo.quotient=offset;
2816 modulo.quotient=offset/((ssize_t) extent);
2817 modulo.remainder=offset % ((ssize_t) extent);
2819 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2822 modulo.remainder+=((ssize_t) extent);
2827MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2828 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2829 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2830 ExceptionInfo *exception)
2833 *magick_restrict cache_info;
2849 *magick_restrict virtual_nexus;
2852 *magick_restrict pixels,
2854 virtual_pixel[MaxPixelChannels];
2865 *magick_restrict virtual_metacontent;
2870 assert(image != (
const Image *) NULL);
2871 assert(image->signature == MagickCoreSignature);
2872 assert(image->cache != (Cache) NULL);
2873 cache_info=(CacheInfo *) image->cache;
2874 assert(cache_info->signature == MagickCoreSignature);
2875 if (cache_info->type == UndefinedCache)
2876 return((
const Quantum *) NULL);
2877#if defined(MAGICKCORE_OPENCL_SUPPORT)
2878 CopyOpenCLBuffer(cache_info);
2880 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2881 ((image->channels & WriteMaskChannel) != 0) ||
2882 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2883 nexus_info,exception);
2884 if (pixels == (Quantum *) NULL)
2885 return((
const Quantum *) NULL);
2886 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2887 return((
const Quantum *) NULL);
2888 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2889 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2890 return((
const Quantum *) NULL);
2891 offset+=nexus_info->region.x;
2892 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2893 nexus_info->region.width-1L;
2894 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2895 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2896 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2897 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2905 if (nexus_info->authentic_pixel_cache != MagickFalse)
2907 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2908 if (status == MagickFalse)
2909 return((
const Quantum *) NULL);
2910 if (cache_info->metacontent_extent != 0)
2912 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2913 if (status == MagickFalse)
2914 return((
const Quantum *) NULL);
2921 virtual_nexus=nexus_info->virtual_nexus;
2923 s=(
unsigned char *) nexus_info->metacontent;
2924 (void) memset(virtual_pixel,0,cache_info->number_channels*
2925 sizeof(*virtual_pixel));
2926 virtual_metacontent=(
void *) NULL;
2927 switch (virtual_pixel_method)
2929 case BackgroundVirtualPixelMethod:
2930 case BlackVirtualPixelMethod:
2931 case GrayVirtualPixelMethod:
2932 case TransparentVirtualPixelMethod:
2933 case MaskVirtualPixelMethod:
2934 case WhiteVirtualPixelMethod:
2935 case EdgeVirtualPixelMethod:
2936 case CheckerTileVirtualPixelMethod:
2937 case HorizontalTileVirtualPixelMethod:
2938 case VerticalTileVirtualPixelMethod:
2940 if (cache_info->metacontent_extent != 0)
2945 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2946 cache_info->metacontent_extent);
2947 if (virtual_metacontent == (
void *) NULL)
2949 (void) ThrowMagickException(exception,GetMagickModule(),
2950 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2951 return((
const Quantum *) NULL);
2953 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2955 switch (virtual_pixel_method)
2957 case BlackVirtualPixelMethod:
2959 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2960 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2961 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2964 case GrayVirtualPixelMethod:
2966 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2967 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2969 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2972 case TransparentVirtualPixelMethod:
2974 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2975 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2976 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2979 case MaskVirtualPixelMethod:
2980 case WhiteVirtualPixelMethod:
2982 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2983 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2984 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2989 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2991 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2993 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2995 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2997 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
3007 for (v=0; v < (ssize_t) rows; v++)
3013 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
3014 (virtual_pixel_method == UndefinedVirtualPixelMethod))
3015 y_offset=EdgeY(y_offset,cache_info->rows);
3016 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
3022 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
3023 x_offset,(ssize_t) columns-u);
3024 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
3025 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3035 length=(MagickSizeType) 1;
3036 switch (virtual_pixel_method)
3038 case EdgeVirtualPixelMethod:
3041 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3042 EdgeX(x_offset,cache_info->columns),
3043 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3045 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3048 case RandomVirtualPixelMethod:
3050 if (cache_info->random_info == (RandomInfo *) NULL)
3051 cache_info->random_info=AcquireRandomInfo();
3052 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3053 RandomX(cache_info->random_info,cache_info->columns),
3054 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3055 virtual_nexus,exception);
3056 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3059 case DitherVirtualPixelMethod:
3061 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3062 DitherX(x_offset,cache_info->columns),
3063 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3065 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3068 case TileVirtualPixelMethod:
3070 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3071 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3072 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3073 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3075 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3078 case MirrorVirtualPixelMethod:
3080 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3081 if ((x_modulo.quotient & 0x01) == 1L)
3082 x_modulo.remainder=(ssize_t) cache_info->columns-
3083 x_modulo.remainder-1L;
3084 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3085 if ((y_modulo.quotient & 0x01) == 1L)
3086 y_modulo.remainder=(ssize_t) cache_info->rows-
3087 y_modulo.remainder-1L;
3088 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3089 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3091 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3094 case HorizontalTileEdgeVirtualPixelMethod:
3096 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3097 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3098 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3099 virtual_nexus,exception);
3100 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3103 case VerticalTileEdgeVirtualPixelMethod:
3105 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3106 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3107 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3108 virtual_nexus,exception);
3109 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3112 case BackgroundVirtualPixelMethod:
3113 case BlackVirtualPixelMethod:
3114 case GrayVirtualPixelMethod:
3115 case TransparentVirtualPixelMethod:
3116 case MaskVirtualPixelMethod:
3117 case WhiteVirtualPixelMethod:
3120 r=virtual_metacontent;
3123 case CheckerTileVirtualPixelMethod:
3125 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3126 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3127 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3130 r=virtual_metacontent;
3133 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3134 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3136 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3139 case HorizontalTileVirtualPixelMethod:
3141 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3144 r=virtual_metacontent;
3147 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3148 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3149 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3150 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3152 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3155 case VerticalTileVirtualPixelMethod:
3157 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3160 r=virtual_metacontent;
3163 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3164 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3165 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3166 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3168 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3172 if (p == (
const Quantum *) NULL)
3174 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3176 q+=(ptrdiff_t) cache_info->number_channels;
3177 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3179 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3180 s+=(ptrdiff_t) cache_info->metacontent_extent;
3187 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3188 (
size_t) length,1UL,virtual_nexus,exception);
3189 if (p == (
const Quantum *) NULL)
3191 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3192 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3194 q+=(ptrdiff_t) cache_info->number_channels*length;
3195 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3197 (void) memcpy(s,r,(
size_t) length);
3198 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3201 if (u < (ssize_t) columns)
3207 if (virtual_metacontent != (
void *) NULL)
3208 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3209 if (v < (ssize_t) rows)
3210 return((
const Quantum *) NULL);
3248static const Quantum *GetVirtualPixelCache(
const Image *image,
3249 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3250 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3253 *magick_restrict cache_info;
3256 id = GetOpenMPThreadId();
3261 assert(image != (
const Image *) NULL);
3262 assert(image->signature == MagickCoreSignature);
3263 assert(image->cache != (Cache) NULL);
3264 cache_info=(CacheInfo *) image->cache;
3265 assert(cache_info->signature == MagickCoreSignature);
3266 assert(
id < (
int) cache_info->number_threads);
3267 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3268 cache_info->nexus_info[
id],exception);
3295MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3298 *magick_restrict cache_info;
3301 id = GetOpenMPThreadId();
3303 assert(image != (
const Image *) NULL);
3304 assert(image->signature == MagickCoreSignature);
3305 assert(image->cache != (Cache) NULL);
3306 cache_info=(CacheInfo *) image->cache;
3307 assert(cache_info->signature == MagickCoreSignature);
3308 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3309 return(cache_info->methods.get_virtual_pixels_handler(image));
3310 assert(
id < (
int) cache_info->number_threads);
3311 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3362MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3363 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3364 ExceptionInfo *exception)
3367 *magick_restrict cache_info;
3370 id = GetOpenMPThreadId();
3375 assert(image != (
const Image *) NULL);
3376 assert(image->signature == MagickCoreSignature);
3377 assert(image->cache != (Cache) NULL);
3378 cache_info=(CacheInfo *) image->cache;
3379 assert(cache_info->signature == MagickCoreSignature);
3380 if (cache_info->methods.get_virtual_pixel_handler !=
3381 (GetVirtualPixelHandler) NULL)
3382 return(cache_info->methods.get_virtual_pixel_handler(image,
3383 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3384 assert(
id < (
int) cache_info->number_threads);
3385 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3386 columns,rows,cache_info->nexus_info[
id],exception);
3413static const Quantum *GetVirtualPixelsCache(
const Image *image)
3416 *magick_restrict cache_info;
3419 id = GetOpenMPThreadId();
3421 assert(image != (
const Image *) NULL);
3422 assert(image->signature == MagickCoreSignature);
3423 assert(image->cache != (Cache) NULL);
3424 cache_info=(CacheInfo *) image->cache;
3425 assert(cache_info->signature == MagickCoreSignature);
3426 assert(
id < (
int) cache_info->number_threads);
3427 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3456MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3457 NexusInfo *magick_restrict nexus_info)
3460 *magick_restrict cache_info;
3462 assert(cache != (Cache) NULL);
3463 cache_info=(CacheInfo *) cache;
3464 assert(cache_info->signature == MagickCoreSignature);
3465 if (cache_info->storage_class == UndefinedClass)
3466 return((Quantum *) NULL);
3467 return((
const Quantum *) nexus_info->pixels);
3500static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3501 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3506 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3508 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3509 gamma=MagickSafeReciprocal(gamma);
3510 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3513static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3514 ExceptionInfo *exception)
3517 *magick_restrict cache_info;
3529 if (IsEventLogging() != MagickFalse)
3530 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3531 if ((image->channels & CompositeMaskChannel) == 0)
3533 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3535 cache_info=(CacheInfo *) image->cache;
3536 if (cache_info == (Cache) NULL)
3537 return(MagickFalse);
3538 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3539 nexus_info->region.width,nexus_info->region.height,
3540 nexus_info->virtual_nexus,exception);
3541 q=nexus_info->pixels;
3542 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3543 return(MagickFalse);
3544 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3549 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3557 alpha=(double) GetPixelCompositeMask(image,p);
3558 for (i=0; i < (ssize_t) image->number_channels; i++)
3560 PixelChannel channel = GetPixelChannelChannel(image,i);
3561 PixelTrait traits = GetPixelChannelTraits(image,channel);
3562 if ((traits & UpdatePixelTrait) == 0)
3564 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3566 p+=(ptrdiff_t) GetPixelChannels(image);
3567 q+=(ptrdiff_t) GetPixelChannels(image);
3604static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3605 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3610 if ((count == 0) || (quantum == 0))
3612 length=count*quantum;
3613 if (quantum != (length/count))
3620 return(MagickFalse);
3623static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3632 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3634 if (*cache_info->cache_filename ==
'\0')
3635 file=AcquireUniqueFileResource(cache_info->cache_filename);
3641 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3646 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3647 O_BINARY | O_EXCL,S_MODE);
3649 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3655 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3658 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3663 return(MagickFalse);
3664 (void) AcquireMagickResource(FileResource,1);
3665 if (cache_info->file != -1)
3666 (void) ClosePixelCacheOnDisk(cache_info);
3667 cache_info->file=file;
3668 cache_info->disk_mode=mode;
3672static inline MagickOffsetType WritePixelCacheRegion(
3673 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3674 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3682 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3683 return((MagickOffsetType) -1);
3684 for (i=0; i < (MagickOffsetType) length; i+=count)
3686 count=MagickWrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3687 (MagickSizeType) i,MagickMaxBufferExtent));
3694static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3697 *magick_restrict cache_info;
3702 cache_info=(CacheInfo *) image->cache;
3703 if (cache_info->debug != MagickFalse)
3706 format[MagickPathExtent],
3707 message[MagickPathExtent];
3709 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3710 (void) FormatLocaleString(message,MagickPathExtent,
3711 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3712 cache_info->cache_filename,cache_info->file,format);
3713 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3715 if (length != (MagickSizeType) ((MagickOffsetType) length))
3716 return(MagickFalse);
3717 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3719 return(MagickFalse);
3720 if ((MagickSizeType) offset < length)
3726 extent=(MagickOffsetType) length-1;
3727 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3730 return(MagickFalse);
3731#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3732 if (cache_info->synchronize != MagickFalse)
3733 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3734 return(MagickFalse);
3737 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3739 return(MagickFalse);
3743static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3744 ExceptionInfo *exception)
3747 *magick_restrict cache_info,
3751 format[MagickPathExtent],
3752 message[MagickPathExtent];
3769 assert(image != (
const Image *) NULL);
3770 assert(image->signature == MagickCoreSignature);
3771 assert(image->cache != (Cache) NULL);
3772 if (IsEventLogging() != MagickFalse)
3773 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3774 if (cache_anonymous_memory < 0)
3782 cache_anonymous_memory=0;
3783 value=GetPolicyValue(
"pixel-cache-memory");
3784 if (value == (
char *) NULL)
3785 value=GetPolicyValue(
"cache:memory-map");
3786 if (LocaleCompare(value,
"anonymous") == 0)
3788#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3789 cache_anonymous_memory=1;
3791 (void) ThrowMagickException(exception,GetMagickModule(),
3792 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3793 "`%s' (policy requires anonymous memory mapping)",image->filename);
3796 value=DestroyString(value);
3798 if ((image->columns == 0) || (image->rows == 0))
3799 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3800 cache_info=(CacheInfo *) image->cache;
3801 assert(cache_info->signature == MagickCoreSignature);
3802 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3803 ((MagickSizeType) image->rows > cache_info->height_limit))
3805 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3806 "WidthOrHeightExceedsLimit",
"`%s' (%.17gx%.17g) > (%.17gx%.17g)",
3807 image->filename, (
double) image->columns, (
double) image->rows,
3808 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3809 return(MagickFalse);
3811 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3813 length=GetImageListLength(image);
3814 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3815 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3818 source_info=(*cache_info);
3819 source_info.file=(-1);
3820 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.17g]",
3821 image->filename,(
double) image->scene);
3822 cache_info->storage_class=image->storage_class;
3823 cache_info->colorspace=image->colorspace;
3824 cache_info->alpha_trait=image->alpha_trait;
3825 cache_info->channels=image->channels;
3826 cache_info->rows=image->rows;
3827 cache_info->columns=image->columns;
3828 status=ResetPixelChannelMap(image,exception);
3829 if (status == MagickFalse)
3830 return(MagickFalse);
3831 cache_info->number_channels=GetPixelChannels(image);
3832 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3833 sizeof(*image->channel_map));
3834 cache_info->metacontent_extent=image->metacontent_extent;
3835 cache_info->mode=mode;
3836 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3837 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3838 if (image->metacontent_extent != 0)
3839 packet_size+=cache_info->metacontent_extent;
3840 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3842 cache_info->storage_class=UndefinedClass;
3843 cache_info->length=0;
3844 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3847 columns=(size_t) (length/cache_info->rows/packet_size);
3848 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3849 ((ssize_t) cache_info->rows < 0))
3851 cache_info->storage_class=UndefinedClass;
3852 cache_info->length=0;
3853 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3856 cache_info->length=length;
3857 if (image->ping != MagickFalse)
3859 cache_info->type=PingCache;
3862 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3863 cache_info->columns*cache_info->rows);
3864 if (cache_info->mode == PersistMode)
3866 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3867 cache_info->metacontent_extent);
3868 if ((status != MagickFalse) &&
3869 (length == (MagickSizeType) ((
size_t) length)) &&
3870 ((cache_info->type == UndefinedCache) ||
3871 (cache_info->type == MemoryCache)))
3873 status=AcquireMagickResource(MemoryResource,cache_info->length);
3874 if (status != MagickFalse)
3877 if (cache_anonymous_memory <= 0)
3879 cache_info->mapped=MagickFalse;
3880 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3881 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3885 cache_info->mapped=MagickTrue;
3886 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3887 cache_info->length);
3889 if (cache_info->pixels == (Quantum *) NULL)
3891 cache_info->mapped=source_info.mapped;
3892 cache_info->pixels=source_info.pixels;
3899 cache_info->type=MemoryCache;
3900 cache_info->metacontent=(
void *) NULL;
3901 if (cache_info->metacontent_extent != 0)
3902 cache_info->metacontent=(
void *) (cache_info->pixels+
3903 cache_info->number_channels*number_pixels);
3904 if ((source_info.storage_class != UndefinedClass) &&
3907 status=ClonePixelCacheRepository(cache_info,&source_info,
3909 RelinquishPixelCachePixels(&source_info);
3911 if (cache_info->debug != MagickFalse)
3913 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3914 MagickPathExtent,format);
3915 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3917 (void) FormatLocaleString(message,MagickPathExtent,
3918 "open %s (%s %s, %.17gx%.17gx%.17g %s)",
3919 cache_info->filename,cache_info->mapped != MagickFalse ?
3920 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3921 (
double) cache_info->rows,(
double)
3922 cache_info->number_channels,format);
3923 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3926 cache_info->storage_class=image->storage_class;
3929 if ((source_info.storage_class != UndefinedClass) &&
3931 RelinquishPixelCachePixels(&source_info);
3932 cache_info->type=UndefinedCache;
3933 return(MagickFalse);
3939 status=AcquireMagickResource(DiskResource,cache_info->length);
3940 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3942 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3950 server_info=AcquireDistributeCacheInfo(exception);
3951 if (server_info != (DistributeCacheInfo *) NULL)
3953 status=OpenDistributePixelCache(server_info,image);
3954 if (status == MagickFalse)
3956 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3957 GetDistributeCacheHostname(server_info));
3958 server_info=DestroyDistributeCacheInfo(server_info);
3966 cache_info->type=DistributedCache;
3967 cache_info->server_info=server_info;
3968 (void) FormatLocaleString(cache_info->cache_filename,
3969 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3970 (DistributeCacheInfo *) cache_info->server_info),
3971 GetDistributeCachePort((DistributeCacheInfo *)
3972 cache_info->server_info));
3973 if ((source_info.storage_class != UndefinedClass) &&
3976 status=ClonePixelCacheRepository(cache_info,&source_info,
3978 RelinquishPixelCachePixels(&source_info);
3980 if (cache_info->debug != MagickFalse)
3982 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3983 MagickPathExtent,format);
3984 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3986 (void) FormatLocaleString(message,MagickPathExtent,
3987 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",
3988 cache_info->filename,cache_info->cache_filename,
3989 GetDistributeCacheFile((DistributeCacheInfo *)
3990 cache_info->server_info),type,(
double) cache_info->columns,
3991 (
double) cache_info->rows,(
double)
3992 cache_info->number_channels,format);
3993 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3998 if ((source_info.storage_class != UndefinedClass) &&
4000 RelinquishPixelCachePixels(&source_info);
4001 cache_info->type=UndefinedCache;
4002 return(MagickFalse);
4007 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4008 RelinquishPixelCachePixels(&source_info);
4009 cache_info->type=UndefinedCache;
4010 (void) memset(image->channel_map,0,MaxPixelChannels*
4011 sizeof(*image->channel_map));
4012 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4013 "CacheResourcesExhausted",
"`%s'",image->filename);
4014 return(MagickFalse);
4019 if (status == MagickFalse)
4021 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4022 RelinquishPixelCachePixels(&source_info);
4023 cache_info->type=UndefinedCache;
4024 (void) memset(image->channel_map,0,MaxPixelChannels*
4025 sizeof(*image->channel_map));
4026 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4027 "CacheResourcesExhausted",
"`%s'",image->filename);
4028 return(MagickFalse);
4030 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4031 (cache_info->mode != PersistMode))
4033 (void) ClosePixelCacheOnDisk(cache_info);
4034 *cache_info->cache_filename=
'\0';
4036 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4038 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4039 RelinquishPixelCachePixels(&source_info);
4040 cache_info->type=UndefinedCache;
4041 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4043 return(MagickFalse);
4045 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4046 cache_info->length);
4047 if (status == MagickFalse)
4049 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4050 RelinquishPixelCachePixels(&source_info);
4051 cache_info->type=UndefinedCache;
4052 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4054 return(MagickFalse);
4056 cache_info->type=DiskCache;
4057 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4058 cache_info->metacontent_extent);
4059 if (length == (MagickSizeType) ((
size_t) length))
4061 status=AcquireMagickResource(MapResource,cache_info->length);
4062 if (status != MagickFalse)
4064 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4065 cache_info->offset,(
size_t) cache_info->length);
4066 if (cache_info->pixels == (Quantum *) NULL)
4068 cache_info->mapped=source_info.mapped;
4069 cache_info->pixels=source_info.pixels;
4070 RelinquishMagickResource(MapResource,cache_info->length);
4077 (void) ClosePixelCacheOnDisk(cache_info);
4078 cache_info->type=MapCache;
4079 cache_info->mapped=MagickTrue;
4080 cache_info->metacontent=(
void *) NULL;
4081 if (cache_info->metacontent_extent != 0)
4082 cache_info->metacontent=(
void *) (cache_info->pixels+
4083 cache_info->number_channels*number_pixels);
4084 if ((source_info.storage_class != UndefinedClass) &&
4087 status=ClonePixelCacheRepository(cache_info,&source_info,
4089 RelinquishPixelCachePixels(&source_info);
4091 if (cache_info->debug != MagickFalse)
4093 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4094 MagickPathExtent,format);
4095 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4097 (void) FormatLocaleString(message,MagickPathExtent,
4098 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",
4099 cache_info->filename,cache_info->cache_filename,
4100 cache_info->file,type,(
double) cache_info->columns,
4101 (
double) cache_info->rows,(
double)
4102 cache_info->number_channels,format);
4103 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4108 if ((source_info.storage_class != UndefinedClass) &&
4110 RelinquishPixelCachePixels(&source_info);
4111 cache_info->type=UndefinedCache;
4112 return(MagickFalse);
4119 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4121 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4122 RelinquishPixelCachePixels(&source_info);
4124 if (cache_info->debug != MagickFalse)
4126 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4127 MagickPathExtent,format);
4128 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4130 (void) FormatLocaleString(message,MagickPathExtent,
4131 "open %s (%s[%d], %s, %.17gx%.17gx%.17g %s)",cache_info->filename,
4132 cache_info->cache_filename,cache_info->file,type,(
double)
4133 cache_info->columns,(
double) cache_info->rows,(
double)
4134 cache_info->number_channels,format);
4135 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4139 cache_info->type=UndefinedCache;
4140 return(MagickFalse);
4182MagickExport MagickBooleanType PersistPixelCache(Image *image,
4183 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4184 ExceptionInfo *exception)
4187 *magick_restrict cache_info,
4188 *magick_restrict clone_info;
4196 assert(image != (Image *) NULL);
4197 assert(image->signature == MagickCoreSignature);
4198 if (IsEventLogging() != MagickFalse)
4199 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4200 assert(image->cache != (
void *) NULL);
4201 assert(filename != (
const char *) NULL);
4202 assert(offset != (MagickOffsetType *) NULL);
4203 page_size=GetMagickPageSize();
4204 cache_info=(CacheInfo *) image->cache;
4205 assert(cache_info->signature == MagickCoreSignature);
4206#if defined(MAGICKCORE_OPENCL_SUPPORT)
4207 CopyOpenCLBuffer(cache_info);
4209 if (attach != MagickFalse)
4214 if (cache_info->debug != MagickFalse)
4215 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4216 "attach persistent cache");
4217 (void) CopyMagickString(cache_info->cache_filename,filename,
4219 cache_info->type=MapCache;
4220 cache_info->offset=(*offset);
4221 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4222 return(MagickFalse);
4223 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4224 ((MagickOffsetType) cache_info->length % page_size));
4230 status=AcquireMagickResource(DiskResource,cache_info->length);
4231 if (status == MagickFalse)
4233 cache_info->type=UndefinedCache;
4234 (void) memset(image->channel_map,0,MaxPixelChannels*
4235 sizeof(*image->channel_map));
4236 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4237 "CacheResourcesExhausted",
"`%s'",image->filename);
4238 return(MagickFalse);
4240 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4241 clone_info->type=DiskCache;
4242 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4243 clone_info->file=(-1);
4244 clone_info->storage_class=cache_info->storage_class;
4245 clone_info->colorspace=cache_info->colorspace;
4246 clone_info->alpha_trait=cache_info->alpha_trait;
4247 clone_info->channels=cache_info->channels;
4248 clone_info->columns=cache_info->columns;
4249 clone_info->rows=cache_info->rows;
4250 clone_info->number_channels=cache_info->number_channels;
4251 clone_info->metacontent_extent=cache_info->metacontent_extent;
4252 clone_info->mode=PersistMode;
4253 clone_info->length=cache_info->length;
4254 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4255 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4256 clone_info->offset=(*offset);
4257 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4258 if (status != MagickFalse)
4259 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4260 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4261 ((MagickOffsetType) cache_info->length % page_size));
4262 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4304MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4305 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4306 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4309 *magick_restrict cache_info;
4318 *magick_restrict pixels;
4323 assert(image != (
const Image *) NULL);
4324 assert(image->signature == MagickCoreSignature);
4325 assert(image->cache != (Cache) NULL);
4326 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4327 if (cache_info == (Cache) NULL)
4328 return((Quantum *) NULL);
4329 assert(cache_info->signature == MagickCoreSignature);
4330 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4331 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4332 (y >= (ssize_t) cache_info->rows))
4334 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4335 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4336 return((Quantum *) NULL);
4338 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4339 return((Quantum *) NULL);
4340 offset=y*(MagickOffsetType) cache_info->columns;
4341 if (IsOffsetOverflow(offset,(MagickOffsetType) x) == MagickFalse)
4342 return((Quantum *) NULL);
4345 return((Quantum *) NULL);
4346 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4347 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns;
4348 if (IsOffsetOverflow(offset,(MagickOffsetType) columns-1) == MagickFalse)
4349 return((Quantum *) NULL);
4350 offset+=(MagickOffsetType) columns-1;
4351 if ((MagickSizeType) offset >= number_pixels)
4352 return((Quantum *) NULL);
4356 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4357 ((image->channels & WriteMaskChannel) != 0) ||
4358 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4359 nexus_info,exception);
4396static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4397 const ssize_t y,
const size_t columns,
const size_t rows,
4398 ExceptionInfo *exception)
4401 *magick_restrict cache_info;
4404 id = GetOpenMPThreadId();
4407 *magick_restrict pixels;
4409 assert(image != (
const Image *) NULL);
4410 assert(image->signature == MagickCoreSignature);
4411 assert(image->cache != (Cache) NULL);
4412 cache_info=(CacheInfo *) image->cache;
4413 assert(cache_info->signature == MagickCoreSignature);
4414 assert(
id < (
int) cache_info->number_threads);
4415 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4416 cache_info->nexus_info[
id],exception);
4476MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4477 const ssize_t y,
const size_t columns,
const size_t rows,
4478 ExceptionInfo *exception)
4481 *magick_restrict cache_info;
4484 id = GetOpenMPThreadId();
4487 *magick_restrict pixels;
4489 assert(image != (Image *) NULL);
4490 assert(image->signature == MagickCoreSignature);
4491 assert(image->cache != (Cache) NULL);
4492 cache_info=(CacheInfo *) image->cache;
4493 assert(cache_info->signature == MagickCoreSignature);
4494 if (cache_info->methods.queue_authentic_pixels_handler !=
4495 (QueueAuthenticPixelsHandler) NULL)
4497 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4498 columns,rows,exception);
4501 assert(
id < (
int) cache_info->number_threads);
4502 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4503 cache_info->nexus_info[
id],exception);
4536static inline MagickOffsetType ReadPixelCacheRegion(
4537 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4538 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4546 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4547 return((MagickOffsetType) -1);
4548 for (i=0; i < (MagickOffsetType) length; i+=count)
4550 count=MagickRead(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4551 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4558static MagickBooleanType ReadPixelCacheMetacontent(
4559 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4560 ExceptionInfo *exception)
4579 if (cache_info->metacontent_extent == 0)
4580 return(MagickFalse);
4581 if (nexus_info->authentic_pixel_cache != MagickFalse)
4583 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4584 return(MagickFalse);
4585 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4586 nexus_info->region.x;
4587 length=(MagickSizeType) nexus_info->region.width*
4588 cache_info->metacontent_extent;
4589 extent=length*nexus_info->region.height;
4590 rows=nexus_info->region.height;
4592 q=(
unsigned char *) nexus_info->metacontent;
4593 switch (cache_info->type)
4604 if ((cache_info->columns == nexus_info->region.width) &&
4605 (extent == (MagickSizeType) ((
size_t) extent)))
4610 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4611 cache_info->metacontent_extent;
4612 for (y=0; y < (ssize_t) rows; y++)
4614 (void) memcpy(q,p,(
size_t) length);
4615 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4616 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4625 LockSemaphoreInfo(cache_info->file_semaphore);
4626 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4628 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4629 cache_info->cache_filename);
4630 UnlockSemaphoreInfo(cache_info->file_semaphore);
4631 return(MagickFalse);
4633 if ((cache_info->columns == nexus_info->region.width) &&
4634 (extent <= MagickMaxBufferExtent))
4639 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4640 for (y=0; y < (ssize_t) rows; y++)
4642 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4643 (MagickOffsetType) extent*(MagickOffsetType)
4644 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4645 (MagickOffsetType) cache_info->metacontent_extent,length,
4646 (
unsigned char *) q);
4647 if (count != (MagickOffsetType) length)
4649 offset+=(MagickOffsetType) cache_info->columns;
4650 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4652 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4653 (void) ClosePixelCacheOnDisk(cache_info);
4654 UnlockSemaphoreInfo(cache_info->file_semaphore);
4657 case DistributedCache:
4665 LockSemaphoreInfo(cache_info->file_semaphore);
4666 region=nexus_info->region;
4667 if ((cache_info->columns != nexus_info->region.width) ||
4668 (extent > MagickMaxBufferExtent))
4675 for (y=0; y < (ssize_t) rows; y++)
4677 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4678 cache_info->server_info,®ion,length,(
unsigned char *) q);
4679 if (count != (MagickOffsetType) length)
4681 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4684 UnlockSemaphoreInfo(cache_info->file_semaphore);
4690 if (y < (ssize_t) rows)
4692 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4693 cache_info->cache_filename);
4694 return(MagickFalse);
4696 if ((cache_info->debug != MagickFalse) &&
4697 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4698 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4699 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
4700 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4701 nexus_info->region.x,(
double) nexus_info->region.y);
4733static MagickBooleanType ReadPixelCachePixels(
4734 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4735 ExceptionInfo *exception)
4755 if (nexus_info->authentic_pixel_cache != MagickFalse)
4757 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4758 return(MagickFalse);
4759 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4760 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4761 return(MagickFalse);
4762 offset+=nexus_info->region.x;
4763 number_channels=cache_info->number_channels;
4764 length=(MagickSizeType) number_channels*nexus_info->region.width*
4766 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4767 return(MagickFalse);
4768 rows=nexus_info->region.height;
4770 if ((extent == 0) || ((extent/length) != rows))
4771 return(MagickFalse);
4773 q=nexus_info->pixels;
4774 switch (cache_info->type)
4785 if ((cache_info->columns == nexus_info->region.width) &&
4786 (extent == (MagickSizeType) ((
size_t) extent)))
4791 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4793 for (y=0; y < (ssize_t) rows; y++)
4795 (void) memcpy(q,p,(
size_t) length);
4796 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4797 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4806 LockSemaphoreInfo(cache_info->file_semaphore);
4807 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4809 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4810 cache_info->cache_filename);
4811 UnlockSemaphoreInfo(cache_info->file_semaphore);
4812 return(MagickFalse);
4814 if ((cache_info->columns == nexus_info->region.width) &&
4815 (extent <= MagickMaxBufferExtent))
4820 for (y=0; y < (ssize_t) rows; y++)
4822 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4823 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4824 sizeof(*q),length,(
unsigned char *) q);
4825 if (count != (MagickOffsetType) length)
4827 offset+=(MagickOffsetType) cache_info->columns;
4828 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4830 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4831 (void) ClosePixelCacheOnDisk(cache_info);
4832 UnlockSemaphoreInfo(cache_info->file_semaphore);
4835 case DistributedCache:
4843 LockSemaphoreInfo(cache_info->file_semaphore);
4844 region=nexus_info->region;
4845 if ((cache_info->columns != nexus_info->region.width) ||
4846 (extent > MagickMaxBufferExtent))
4853 for (y=0; y < (ssize_t) rows; y++)
4855 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4856 cache_info->server_info,®ion,length,(
unsigned char *) q);
4857 if (count != (MagickOffsetType) length)
4859 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4862 UnlockSemaphoreInfo(cache_info->file_semaphore);
4868 if (y < (ssize_t) rows)
4870 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4871 cache_info->cache_filename);
4872 return(MagickFalse);
4874 if ((cache_info->debug != MagickFalse) &&
4875 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4876 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4877 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
4878 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4879 nexus_info->region.x,(
double) nexus_info->region.y);
4906MagickPrivate Cache ReferencePixelCache(Cache cache)
4909 *magick_restrict cache_info;
4911 assert(cache != (Cache *) NULL);
4912 cache_info=(CacheInfo *) cache;
4913 assert(cache_info->signature == MagickCoreSignature);
4914 LockSemaphoreInfo(cache_info->semaphore);
4915 cache_info->reference_count++;
4916 UnlockSemaphoreInfo(cache_info->semaphore);
4942MagickPrivate
void ResetPixelCacheChannels(Image *image)
4945 *magick_restrict cache_info;
4947 assert(image != (
const Image *) NULL);
4948 assert(image->signature == MagickCoreSignature);
4949 assert(image->cache != (Cache) NULL);
4950 cache_info=(CacheInfo *) image->cache;
4951 assert(cache_info->signature == MagickCoreSignature);
4952 cache_info->number_channels=GetPixelChannels(image);
4973MagickPrivate
void ResetCacheAnonymousMemory(
void)
4975 cache_anonymous_memory=0;
5007MagickExport MagickBooleanType ReshapePixelCache(Image *image,
5008 const size_t columns,
const size_t rows,ExceptionInfo *exception)
5016 assert(image != (Image *) NULL);
5017 assert(image->signature == MagickCoreSignature);
5018 if (IsEventLogging() != MagickFalse)
5019 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5020 assert(image->cache != (
void *) NULL);
5021 extent=(MagickSizeType) columns*rows;
5022 if (extent > ((MagickSizeType) image->columns*image->rows))
5023 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5025 image->columns=columns;
5027 cache_info=(CacheInfo *) image->cache;
5028 cache_info->columns=columns;
5029 cache_info->rows=rows;
5030 return(SyncImagePixelCache(image,exception));
5057MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5060 *magick_restrict cache_info;
5062 GetOneAuthenticPixelFromHandler
5063 get_one_authentic_pixel_from_handler;
5065 GetOneVirtualPixelFromHandler
5066 get_one_virtual_pixel_from_handler;
5071 assert(cache != (Cache) NULL);
5072 assert(cache_methods != (CacheMethods *) NULL);
5073 cache_info=(CacheInfo *) cache;
5074 assert(cache_info->signature == MagickCoreSignature);
5075 if (IsEventLogging() != MagickFalse)
5076 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5077 cache_info->filename);
5078 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5079 cache_info->methods.get_virtual_pixel_handler=
5080 cache_methods->get_virtual_pixel_handler;
5081 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5082 cache_info->methods.destroy_pixel_handler=
5083 cache_methods->destroy_pixel_handler;
5084 if (cache_methods->get_virtual_metacontent_from_handler !=
5085 (GetVirtualMetacontentFromHandler) NULL)
5086 cache_info->methods.get_virtual_metacontent_from_handler=
5087 cache_methods->get_virtual_metacontent_from_handler;
5088 if (cache_methods->get_authentic_pixels_handler !=
5089 (GetAuthenticPixelsHandler) NULL)
5090 cache_info->methods.get_authentic_pixels_handler=
5091 cache_methods->get_authentic_pixels_handler;
5092 if (cache_methods->queue_authentic_pixels_handler !=
5093 (QueueAuthenticPixelsHandler) NULL)
5094 cache_info->methods.queue_authentic_pixels_handler=
5095 cache_methods->queue_authentic_pixels_handler;
5096 if (cache_methods->sync_authentic_pixels_handler !=
5097 (SyncAuthenticPixelsHandler) NULL)
5098 cache_info->methods.sync_authentic_pixels_handler=
5099 cache_methods->sync_authentic_pixels_handler;
5100 if (cache_methods->get_authentic_pixels_from_handler !=
5101 (GetAuthenticPixelsFromHandler) NULL)
5102 cache_info->methods.get_authentic_pixels_from_handler=
5103 cache_methods->get_authentic_pixels_from_handler;
5104 if (cache_methods->get_authentic_metacontent_from_handler !=
5105 (GetAuthenticMetacontentFromHandler) NULL)
5106 cache_info->methods.get_authentic_metacontent_from_handler=
5107 cache_methods->get_authentic_metacontent_from_handler;
5108 get_one_virtual_pixel_from_handler=
5109 cache_info->methods.get_one_virtual_pixel_from_handler;
5110 if (get_one_virtual_pixel_from_handler !=
5111 (GetOneVirtualPixelFromHandler) NULL)
5112 cache_info->methods.get_one_virtual_pixel_from_handler=
5113 cache_methods->get_one_virtual_pixel_from_handler;
5114 get_one_authentic_pixel_from_handler=
5115 cache_methods->get_one_authentic_pixel_from_handler;
5116 if (get_one_authentic_pixel_from_handler !=
5117 (GetOneAuthenticPixelFromHandler) NULL)
5118 cache_info->methods.get_one_authentic_pixel_from_handler=
5119 cache_methods->get_one_authentic_pixel_from_handler;
5160static inline MagickBooleanType AcquireCacheNexusPixels(
5161 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5162 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5164 if (length != (MagickSizeType) ((
size_t) length))
5166 (void) ThrowMagickException(exception,GetMagickModule(),
5167 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5168 cache_info->filename);
5169 return(MagickFalse);
5171 nexus_info->length=0;
5172 nexus_info->mapped=MagickFalse;
5173 if (cache_anonymous_memory <= 0)
5175 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5177 if (nexus_info->cache != (Quantum *) NULL)
5178 (void) memset(nexus_info->cache,0,(
size_t) length);
5182 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5183 if (nexus_info->cache != (Quantum *) NULL)
5184 nexus_info->mapped=MagickTrue;
5186 if (nexus_info->cache == (Quantum *) NULL)
5188 (void) ThrowMagickException(exception,GetMagickModule(),
5189 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5190 cache_info->filename);
5191 return(MagickFalse);
5193 nexus_info->length=length;
5197static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5200 if (nexus_info->length < CACHE_LINE_SIZE)
5202 if (mode == ReadMode)
5204 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5208 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5211static Quantum *SetPixelCacheNexusPixels(
5212 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5213 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5214 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5215 ExceptionInfo *exception)
5224 assert(cache_info != (
const CacheInfo *) NULL);
5225 assert(cache_info->signature == MagickCoreSignature);
5226 if (cache_info->type == UndefinedCache)
5227 return((Quantum *) NULL);
5228 assert(nexus_info->signature == MagickCoreSignature);
5229 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5230 if ((width == 0) || (height == 0))
5232 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5233 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5234 return((Quantum *) NULL);
5236 if (((MagickSizeType) width > cache_info->width_limit) ||
5237 ((MagickSizeType) height > cache_info->height_limit))
5239 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5240 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5241 return((Quantum *) NULL);
5243 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5244 (IsValidPixelOffset(y,height) == MagickFalse))
5246 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5247 "InvalidPixel",
"`%s'",cache_info->filename);
5248 return((Quantum *) NULL);
5250 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5251 (buffered == MagickFalse))
5253 if (((x >= 0) && (y >= 0) &&
5254 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5255 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5256 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5264 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5265 return((Quantum *) NULL);
5266 offset=y*(MagickOffsetType) cache_info->columns+x;
5267 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5268 cache_info->number_channels*offset;
5269 nexus_info->metacontent=(
void *) NULL;
5270 if (cache_info->metacontent_extent != 0)
5271 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5272 offset*(MagickOffsetType) cache_info->metacontent_extent;
5273 nexus_info->region.width=width;
5274 nexus_info->region.height=height;
5275 nexus_info->region.x=x;
5276 nexus_info->region.y=y;
5277 nexus_info->authentic_pixel_cache=MagickTrue;
5278 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5279 return(nexus_info->pixels);
5285 number_pixels=(MagickSizeType) width*height;
5286 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5287 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5288 if (cache_info->metacontent_extent != 0)
5289 length+=number_pixels*cache_info->metacontent_extent;
5291 if (nexus_info->cache == (Quantum *) NULL)
5292 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5294 if (nexus_info->length < length)
5296 RelinquishCacheNexusPixels(nexus_info);
5297 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5299 if (status == MagickFalse)
5300 return((Quantum *) NULL);
5301 nexus_info->pixels=nexus_info->cache;
5302 nexus_info->metacontent=(
void *) NULL;
5303 if (cache_info->metacontent_extent != 0)
5304 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5305 cache_info->number_channels*number_pixels);
5306 nexus_info->region.width=width;
5307 nexus_info->region.height=height;
5308 nexus_info->region.x=x;
5309 nexus_info->region.y=y;
5310 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5311 MagickTrue : MagickFalse;
5312 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5313 return(nexus_info->pixels);
5346static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5347 ExceptionInfo *exception)
5350 *magick_restrict image_view;
5358 assert(image != (Image *) NULL);
5359 assert(image->signature == MagickCoreSignature);
5360 if (IsEventLogging() != MagickFalse)
5361 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5362 assert(image->cache != (Cache) NULL);
5363 image->alpha_trait=BlendPixelTrait;
5365 image_view=AcquireVirtualCacheView(image,exception);
5366#if defined(MAGICKCORE_OPENMP_SUPPORT)
5367 #pragma omp parallel for schedule(static) shared(status) \
5368 magick_number_threads(image,image,image->rows,2)
5370 for (y=0; y < (ssize_t) image->rows; y++)
5378 if (status == MagickFalse)
5380 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5381 if (q == (Quantum *) NULL)
5386 for (x=0; x < (ssize_t) image->columns; x++)
5388 SetPixelAlpha(image,alpha,q);
5389 q+=(ptrdiff_t) GetPixelChannels(image);
5391 status=SyncCacheViewAuthenticPixels(image_view,exception);
5393 image_view=DestroyCacheView(image_view);
5397MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5398 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5401 *magick_restrict cache_info;
5406 assert(image != (Image *) NULL);
5407 assert(image->signature == MagickCoreSignature);
5408 if (IsEventLogging() != MagickFalse)
5409 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5410 assert(image->cache != (Cache) NULL);
5411 cache_info=(CacheInfo *) image->cache;
5412 assert(cache_info->signature == MagickCoreSignature);
5413 method=cache_info->virtual_pixel_method;
5414 cache_info->virtual_pixel_method=virtual_pixel_method;
5415 if ((image->columns != 0) && (image->rows != 0))
5416 switch (virtual_pixel_method)
5418 case BackgroundVirtualPixelMethod:
5420 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5421 ((image->alpha_trait & BlendPixelTrait) == 0))
5422 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5423 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5424 (IsGrayColorspace(image->colorspace) != MagickFalse))
5425 (void) SetImageColorspace(image,sRGBColorspace,exception);
5428 case TransparentVirtualPixelMethod:
5430 if ((image->alpha_trait & BlendPixelTrait) == 0)
5431 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5440#if defined(MAGICKCORE_OPENCL_SUPPORT)
5465static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5467 assert(cache_info != (CacheInfo *) NULL);
5468 assert(cache_info->signature == MagickCoreSignature);
5469 if ((cache_info->type != MemoryCache) ||
5470 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5475 LockSemaphoreInfo(cache_info->semaphore);
5476 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5477 UnlockSemaphoreInfo(cache_info->semaphore);
5480MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5483 *magick_restrict cache_info;
5485 assert(image != (
const Image *) NULL);
5486 cache_info=(CacheInfo *) image->cache;
5487 CopyOpenCLBuffer(cache_info);
5520MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5521 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5524 *magick_restrict cache_info;
5532 assert(image != (Image *) NULL);
5533 assert(image->signature == MagickCoreSignature);
5534 if (image->cache == (Cache) NULL)
5535 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5536 cache_info=(CacheInfo *) image->cache;
5537 assert(cache_info->signature == MagickCoreSignature);
5538 if (cache_info->type == UndefinedCache)
5539 return(MagickFalse);
5540 if ((image->mask_trait & UpdatePixelTrait) != 0)
5542 if (((image->channels & WriteMaskChannel) != 0) &&
5543 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5544 return(MagickFalse);
5545 if (((image->channels & CompositeMaskChannel) != 0) &&
5546 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5547 return(MagickFalse);
5549 if (nexus_info->authentic_pixel_cache != MagickFalse)
5551 if (image->taint == MagickFalse)
5552 image->taint=MagickTrue;
5555 assert(cache_info->signature == MagickCoreSignature);
5556 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5557 if ((cache_info->metacontent_extent != 0) &&
5558 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5559 return(MagickFalse);
5560 if ((status != MagickFalse) && (image->taint == MagickFalse))
5561 image->taint=MagickTrue;
5592static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5593 ExceptionInfo *exception)
5596 *magick_restrict cache_info;
5599 id = GetOpenMPThreadId();
5604 assert(image != (Image *) NULL);
5605 assert(image->signature == MagickCoreSignature);
5606 assert(image->cache != (Cache) NULL);
5607 cache_info=(CacheInfo *) image->cache;
5608 assert(cache_info->signature == MagickCoreSignature);
5609 assert(
id < (
int) cache_info->number_threads);
5610 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5642MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5643 ExceptionInfo *exception)
5646 *magick_restrict cache_info;
5649 id = GetOpenMPThreadId();
5654 assert(image != (Image *) NULL);
5655 assert(image->signature == MagickCoreSignature);
5656 assert(image->cache != (Cache) NULL);
5657 cache_info=(CacheInfo *) image->cache;
5658 assert(cache_info->signature == MagickCoreSignature);
5659 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5661 status=cache_info->methods.sync_authentic_pixels_handler(image,
5665 assert(
id < (
int) cache_info->number_threads);
5666 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5698MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5699 ExceptionInfo *exception)
5702 *magick_restrict cache_info;
5704 assert(image != (Image *) NULL);
5705 assert(exception != (ExceptionInfo *) NULL);
5706 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5707 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5738static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5739 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5758 if (cache_info->metacontent_extent == 0)
5759 return(MagickFalse);
5760 if (nexus_info->authentic_pixel_cache != MagickFalse)
5762 if (nexus_info->metacontent == (
unsigned char *) NULL)
5763 return(MagickFalse);
5764 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5765 return(MagickFalse);
5766 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5767 nexus_info->region.x;
5768 length=(MagickSizeType) nexus_info->region.width*
5769 cache_info->metacontent_extent;
5770 extent=(MagickSizeType) length*nexus_info->region.height;
5771 rows=nexus_info->region.height;
5773 p=(
unsigned char *) nexus_info->metacontent;
5774 switch (cache_info->type)
5785 if ((cache_info->columns == nexus_info->region.width) &&
5786 (extent == (MagickSizeType) ((
size_t) extent)))
5791 q=(
unsigned char *) cache_info->metacontent+offset*
5792 (MagickOffsetType) cache_info->metacontent_extent;
5793 for (y=0; y < (ssize_t) rows; y++)
5795 (void) memcpy(q,p,(
size_t) length);
5796 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5797 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5806 LockSemaphoreInfo(cache_info->file_semaphore);
5807 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5809 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5810 cache_info->cache_filename);
5811 UnlockSemaphoreInfo(cache_info->file_semaphore);
5812 return(MagickFalse);
5814 if ((cache_info->columns == nexus_info->region.width) &&
5815 (extent <= MagickMaxBufferExtent))
5820 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5821 for (y=0; y < (ssize_t) rows; y++)
5823 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5824 (MagickOffsetType) extent*(MagickOffsetType)
5825 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5826 (MagickOffsetType) cache_info->metacontent_extent,length,
5827 (
const unsigned char *) p);
5828 if (count != (MagickOffsetType) length)
5830 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5831 offset+=(MagickOffsetType) cache_info->columns;
5833 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5834 (void) ClosePixelCacheOnDisk(cache_info);
5835 UnlockSemaphoreInfo(cache_info->file_semaphore);
5838 case DistributedCache:
5846 LockSemaphoreInfo(cache_info->file_semaphore);
5847 region=nexus_info->region;
5848 if ((cache_info->columns != nexus_info->region.width) ||
5849 (extent > MagickMaxBufferExtent))
5856 for (y=0; y < (ssize_t) rows; y++)
5858 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5859 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5860 if (count != (MagickOffsetType) length)
5862 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5865 UnlockSemaphoreInfo(cache_info->file_semaphore);
5871 if (y < (ssize_t) rows)
5873 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5874 cache_info->cache_filename);
5875 return(MagickFalse);
5877 if ((cache_info->debug != MagickFalse) &&
5878 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5879 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5880 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
5881 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5882 nexus_info->region.x,(
double) nexus_info->region.y);
5914static MagickBooleanType WritePixelCachePixels(
5915 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5916 ExceptionInfo *exception)
5935 if (nexus_info->authentic_pixel_cache != MagickFalse)
5937 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5938 return(MagickFalse);
5939 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5940 nexus_info->region.x;
5941 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5943 extent=length*nexus_info->region.height;
5944 rows=nexus_info->region.height;
5946 p=nexus_info->pixels;
5947 switch (cache_info->type)
5958 if ((cache_info->columns == nexus_info->region.width) &&
5959 (extent == (MagickSizeType) ((
size_t) extent)))
5964 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5966 for (y=0; y < (ssize_t) rows; y++)
5968 (void) memcpy(q,p,(
size_t) length);
5969 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5970 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5979 LockSemaphoreInfo(cache_info->file_semaphore);
5980 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5982 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5983 cache_info->cache_filename);
5984 UnlockSemaphoreInfo(cache_info->file_semaphore);
5985 return(MagickFalse);
5987 if ((cache_info->columns == nexus_info->region.width) &&
5988 (extent <= MagickMaxBufferExtent))
5993 for (y=0; y < (ssize_t) rows; y++)
5995 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5996 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5997 sizeof(*p),length,(
const unsigned char *) p);
5998 if (count != (MagickOffsetType) length)
6000 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6001 offset+=(MagickOffsetType) cache_info->columns;
6003 if (IsFileDescriptorLimitExceeded() != MagickFalse)
6004 (void) ClosePixelCacheOnDisk(cache_info);
6005 UnlockSemaphoreInfo(cache_info->file_semaphore);
6008 case DistributedCache:
6016 LockSemaphoreInfo(cache_info->file_semaphore);
6017 region=nexus_info->region;
6018 if ((cache_info->columns != nexus_info->region.width) ||
6019 (extent > MagickMaxBufferExtent))
6026 for (y=0; y < (ssize_t) rows; y++)
6028 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6029 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6030 if (count != (MagickOffsetType) length)
6032 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6035 UnlockSemaphoreInfo(cache_info->file_semaphore);
6041 if (y < (ssize_t) rows)
6043 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6044 cache_info->cache_filename);
6045 return(MagickFalse);
6047 if ((cache_info->debug != MagickFalse) &&
6048 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6049 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6050 "%s[%.17gx%.17g%+.20g%+.20g]",cache_info->filename,(
double)
6051 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6052 nexus_info->region.x,(
double) nexus_info->region.y);