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_SYS_LOADAVG_H)
79# include <sys/loadavg.h>
81#if defined(MAGICKCORE_ZLIB_DELEGATE)
88#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
89#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
90 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
105#if defined(__cplusplus) || defined(c_plusplus)
110 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
114 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
115 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
116 *GetVirtualPixelsCache(
const Image *);
119 *GetVirtualMetacontentFromCache(
const Image *);
121static MagickBooleanType
122 GetOneAuthenticPixelFromCache(Image *,
const ssize_t,
const ssize_t,Quantum *,
124 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
125 const ssize_t,
const ssize_t,Quantum *,ExceptionInfo *),
126 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
127 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
128 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
130 ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
131 NexusInfo *magick_restrict,ExceptionInfo *),
132 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
133 WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
135 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
139 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
140 const size_t,ExceptionInfo *),
141 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
142 const size_t,ExceptionInfo *),
143 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
144 const ssize_t,
const ssize_t,
const size_t,
const size_t,
145 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
148#if defined(MAGICKCORE_OPENCL_SUPPORT)
150 CopyOpenCLBuffer(CacheInfo *magick_restrict);
153#if defined(__cplusplus) || defined(c_plusplus)
164 cache_anonymous_memory = (-1);
188MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
191 *magick_restrict cache_info;
196 cache_info=(CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
197 if (cache_info == (CacheInfo *) NULL)
198 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
199 (void) memset(cache_info,0,
sizeof(*cache_info));
200 cache_info->type=UndefinedCache;
201 cache_info->mode=IOMode;
202 cache_info->disk_mode=IOMode;
203 cache_info->colorspace=sRGBColorspace;
204 cache_info->file=(-1);
205 cache_info->id=GetMagickThreadId();
206 cache_info->number_threads=number_threads;
207 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
208 cache_info->number_threads=GetOpenMPMaximumThreads();
209 if (cache_info->number_threads == 0)
210 cache_info->number_threads=1;
211 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
212 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
213 if (value != (
const char *) NULL)
215 cache_info->synchronize=IsStringTrue(value);
216 value=DestroyString(value);
218 value=GetPolicyValue(
"cache:synchronize");
219 if (value != (
const char *) NULL)
221 cache_info->synchronize=IsStringTrue(value);
222 value=DestroyString(value);
224 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
225 (MagickSizeType) MAGICK_SSIZE_MAX);
226 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
227 (MagickSizeType) MAGICK_SSIZE_MAX);
228 cache_info->semaphore=AcquireSemaphoreInfo();
229 cache_info->reference_count=1;
230 cache_info->file_semaphore=AcquireSemaphoreInfo();
231 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
233 cache_info->signature=MagickCoreSignature;
234 return((Cache ) cache_info);
259MagickPrivate NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
262 **magick_restrict nexus_info;
267 nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
268 number_threads,
sizeof(*nexus_info)));
269 if (nexus_info == (NexusInfo **) NULL)
270 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
271 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
272 2*
sizeof(**nexus_info));
273 if (*nexus_info == (NexusInfo *) NULL)
274 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
275 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
276 for (i=0; i < (ssize_t) (2*number_threads); i++)
278 nexus_info[i]=(*nexus_info+i);
279 if (i < (ssize_t) number_threads)
280 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
281 nexus_info[i]->signature=MagickCoreSignature;
314MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
315 ExceptionInfo *exception)
318 *magick_restrict cache_info;
320 assert(image != (
const Image *) NULL);
321 assert(image->signature == MagickCoreSignature);
322 assert(exception != (ExceptionInfo *) NULL);
323 assert(exception->signature == MagickCoreSignature);
324 assert(image->cache != (Cache) NULL);
326 cache_info=(CacheInfo *) image->cache;
327 assert(cache_info->signature == MagickCoreSignature);
329 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
330 return((
void *) NULL);
331 *length=(size_t) cache_info->length;
332 return(cache_info->pixels);
353MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
356 cache_semaphore=AcquireSemaphoreInfo();
378MagickPrivate
void CacheComponentTerminus(
void)
381 ActivateSemaphoreInfo(&cache_semaphore);
383 RelinquishSemaphoreInfo(&cache_semaphore);
415static MagickBooleanType ClipPixelCacheNexus(Image *image,
416 NexusInfo *nexus_info,ExceptionInfo *exception)
419 *magick_restrict cache_info;
431 if (IsEventLogging() != MagickFalse)
432 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
433 if ((image->channels & WriteMaskChannel) == 0)
435 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
437 cache_info=(CacheInfo *) image->cache;
438 if (cache_info == (CacheInfo *) NULL)
440 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
441 nexus_info->region.width,nexus_info->region.height,
442 nexus_info->virtual_nexus,exception);
443 q=nexus_info->pixels;
444 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
446 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
451 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
459 mask=(double) GetPixelWriteMask(image,p);
460 if (fabs(mask) >= MagickEpsilon)
469 src_alpha=GetPixelAlpha(image,p);
470 mask_alpha=QuantumScale*mask*(double) src_alpha;
471 dst_alpha=(double) GetPixelAlpha(image,q);
472 for (i=0; i < (ssize_t) image->number_channels; i++)
477 PixelChannel channel = GetPixelChannelChannel(image,i);
478 if (channel == AlphaPixelChannel)
480 traits=GetPixelChannelTraits(image,channel);
481 if ((traits & UpdatePixelTrait) == 0)
483 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha,
484 (
double) q[i],dst_alpha));
486 SetPixelAlpha(image,src_alpha,q);
488 p+=(ptrdiff_t) GetPixelChannels(image);
489 q+=(ptrdiff_t) GetPixelChannels(image);
517MagickPrivate Cache ClonePixelCache(
const Cache cache)
520 *magick_restrict clone_info;
523 *magick_restrict cache_info;
525 assert(cache != NULL);
526 cache_info=(
const CacheInfo *) cache;
527 assert(cache_info->signature == MagickCoreSignature);
528 if (IsEventLogging() != MagickFalse)
529 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
530 cache_info->filename);
531 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
532 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
533 return((Cache ) clone_info);
561MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
564 *magick_restrict cache_info,
565 *magick_restrict source_info;
567 assert(clone != (Cache) NULL);
568 source_info=(CacheInfo *) clone;
569 assert(source_info->signature == MagickCoreSignature);
570 if (IsEventLogging() != MagickFalse)
571 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
572 source_info->filename);
573 assert(cache != (Cache) NULL);
574 cache_info=(CacheInfo *) cache;
575 assert(cache_info->signature == MagickCoreSignature);
576 source_info->methods=cache_info->methods;
608static MagickBooleanType ClonePixelCacheOnDisk(
609 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
629 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
630 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
632 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
633 (lseek(clone_info->file,0,SEEK_SET) < 0))
635 quantum=(size_t) MagickMaxBufferExtent;
636 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
638#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
639 if (cache_info->length < 0x7ffff000)
641 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
642 (
size_t) cache_info->length);
643 if (count == (ssize_t) cache_info->length)
645 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
646 (lseek(clone_info->file,0,SEEK_SET) < 0))
650 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
652 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
653 if (buffer == (
unsigned char *) NULL)
654 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
656 while ((count=read(cache_info->file,buffer,quantum)) > 0)
661 number_bytes=write(clone_info->file,buffer,(
size_t) count);
662 if (number_bytes != count)
664 extent+=(size_t) number_bytes;
666 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
667 if (extent != cache_info->length)
672#if defined(MAGICKCORE_OPENMP_SUPPORT)
673static inline int GetCacheNumberThreads(
const CacheInfo *source,
674 const CacheInfo *destination,
const size_t chunk,
const int factor)
677 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
678 number_threads = 1UL,
679 workload_factor = 64UL << factor;
684 number_threads=(chunk <= workload_factor) ? 1UL :
685 (chunk >= (workload_factor << 6)) ? max_threads :
686 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
690 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
691 ((destination->type != MemoryCache) && (destination->type != MapCache)))
692 number_threads=MagickMin(number_threads,4);
693 return((
int) number_threads);
697static MagickBooleanType ClonePixelCacheRepository(
698 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
699 ExceptionInfo *exception)
701#define cache_number_threads(source,destination,chunk,factor) \
702 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
709 **magick_restrict cache_nexus,
710 **magick_restrict clone_nexus;
718 assert(cache_info != (CacheInfo *) NULL);
719 assert(clone_info != (CacheInfo *) NULL);
720 assert(exception != (ExceptionInfo *) NULL);
721 if (cache_info->type == PingCache)
723 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
724 if ((cache_info->storage_class == clone_info->storage_class) &&
725 (cache_info->colorspace == clone_info->colorspace) &&
726 (cache_info->alpha_trait == clone_info->alpha_trait) &&
727 (cache_info->channels == clone_info->channels) &&
728 (cache_info->columns == clone_info->columns) &&
729 (cache_info->rows == clone_info->rows) &&
730 (cache_info->number_channels == clone_info->number_channels) &&
731 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
732 (cache_info->metacontent_extent == clone_info->metacontent_extent))
737 if (((cache_info->type == MemoryCache) ||
738 (cache_info->type == MapCache)) &&
739 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
741 (void) memcpy(clone_info->pixels,cache_info->pixels,
742 cache_info->number_channels*cache_info->columns*cache_info->rows*
743 sizeof(*cache_info->pixels));
744 if ((cache_info->metacontent_extent != 0) &&
745 (clone_info->metacontent_extent != 0))
746 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
747 cache_info->columns*cache_info->rows*
748 clone_info->metacontent_extent*
sizeof(
unsigned char));
751 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
752 return(ClonePixelCacheOnDisk(cache_info,clone_info));
757 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
758 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
759 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
760 optimize=(cache_info->number_channels == clone_info->number_channels) &&
761 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
762 MagickTrue : MagickFalse;
763 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
764 clone_info->number_channels*clone_info->columns);
766#if defined(MAGICKCORE_OPENMP_SUPPORT)
767 #pragma omp parallel for schedule(static) shared(status) \
768 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
770 for (y=0; y < (ssize_t) cache_info->rows; y++)
773 id = GetOpenMPThreadId();
781 if (status == MagickFalse)
783 if (y >= (ssize_t) clone_info->rows)
785 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
786 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
787 if (pixels == (Quantum *) NULL)
789 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
790 if (status == MagickFalse)
792 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
793 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
794 if (pixels == (Quantum *) NULL)
796 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
797 if (optimize != MagickFalse)
798 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
811 p=cache_nexus[id]->pixels;
812 q=clone_nexus[id]->pixels;
813 for (x=0; x < (ssize_t) cache_info->columns; x++)
818 if (x == (ssize_t) clone_info->columns)
820 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
828 channel=clone_info->channel_map[i].channel;
829 traits=cache_info->channel_map[channel].traits;
830 if (traits != UndefinedPixelTrait)
831 *q=*(p+cache_info->channel_map[channel].offset);
834 p+=(ptrdiff_t) cache_info->number_channels;
837 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
839 if ((cache_info->metacontent_extent != 0) &&
840 (clone_info->metacontent_extent != 0))
845 length=(size_t) MagickMin(cache_info->metacontent_extent,
846 clone_info->metacontent_extent);
847#if defined(MAGICKCORE_OPENMP_SUPPORT)
848 #pragma omp parallel for schedule(static) shared(status) \
849 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
851 for (y=0; y < (ssize_t) cache_info->rows; y++)
854 id = GetOpenMPThreadId();
859 if (status == MagickFalse)
861 if (y >= (ssize_t) clone_info->rows)
863 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
864 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
865 if (pixels == (Quantum *) NULL)
867 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
868 if (status == MagickFalse)
870 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
871 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
872 if (pixels == (Quantum *) NULL)
874 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
875 (cache_nexus[
id]->metacontent != (
void *) NULL))
876 (void) memcpy(clone_nexus[
id]->metacontent,
877 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
878 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
881 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
882 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
883 if (cache_info->debug != MagickFalse)
886 message[MagickPathExtent];
888 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
889 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
890 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
891 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
918static void DestroyImagePixelCache(Image *image)
920 assert(image != (Image *) NULL);
921 assert(image->signature == MagickCoreSignature);
922 if (IsEventLogging() != MagickFalse)
923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
924 if (image->cache != (
void *) NULL)
925 image->cache=DestroyPixelCache(image->cache);
950MagickExport
void DestroyImagePixels(Image *image)
953 *magick_restrict cache_info;
955 assert(image != (
const Image *) NULL);
956 assert(image->signature == MagickCoreSignature);
957 if (IsEventLogging() != MagickFalse)
958 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
959 assert(image->cache != (Cache) NULL);
960 cache_info=(CacheInfo *) image->cache;
961 assert(cache_info->signature == MagickCoreSignature);
962 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
964 cache_info->methods.destroy_pixel_handler(image);
967 image->cache=DestroyPixelCache(image->cache);
993static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
999 if (cache_info->file != -1)
1001 status=close_utf8(cache_info->file);
1002 cache_info->file=(-1);
1003 RelinquishMagickResource(FileResource,1);
1005 return(status == -1 ? MagickFalse : MagickTrue);
1008static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
1010 switch (cache_info->type)
1014 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1015#if defined(MAGICKCORE_OPENCL_SUPPORT)
1016 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1018 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1020 cache_info->pixels=(Quantum *) NULL;
1024 if (cache_info->mapped == MagickFalse)
1025 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1026 cache_info->pixels);
1029 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1030 cache_info->pixels=(Quantum *) NULL;
1032 RelinquishMagickResource(MemoryResource,cache_info->length);
1037 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1038 cache_info->pixels=(Quantum *) NULL;
1039 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1040 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1041 *cache_info->cache_filename=
'\0';
1042 RelinquishMagickResource(MapResource,cache_info->length);
1047 if (cache_info->file != -1)
1048 (void) ClosePixelCacheOnDisk(cache_info);
1049 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1050 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1051 *cache_info->cache_filename=
'\0';
1052 RelinquishMagickResource(DiskResource,cache_info->length);
1055 case DistributedCache:
1057 *cache_info->cache_filename=
'\0';
1058 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1059 cache_info->server_info);
1065 cache_info->type=UndefinedCache;
1066 cache_info->mapped=MagickFalse;
1067 cache_info->metacontent=(
void *) NULL;
1070MagickPrivate Cache DestroyPixelCache(Cache cache)
1073 *magick_restrict cache_info;
1075 assert(cache != (Cache) NULL);
1076 cache_info=(CacheInfo *) cache;
1077 assert(cache_info->signature == MagickCoreSignature);
1078 if (IsEventLogging() != MagickFalse)
1079 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1080 cache_info->filename);
1081 LockSemaphoreInfo(cache_info->semaphore);
1082 cache_info->reference_count--;
1083 if (cache_info->reference_count != 0)
1085 UnlockSemaphoreInfo(cache_info->semaphore);
1086 return((Cache) NULL);
1088 UnlockSemaphoreInfo(cache_info->semaphore);
1089 if (cache_info->debug != MagickFalse)
1092 message[MagickPathExtent];
1094 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1095 cache_info->filename);
1096 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1098 RelinquishPixelCachePixels(cache_info);
1099 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1100 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1101 cache_info->server_info);
1102 if (cache_info->nexus_info != (NexusInfo **) NULL)
1103 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1104 cache_info->number_threads);
1105 if (cache_info->random_info != (RandomInfo *) NULL)
1106 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1108 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1110 RelinquishSemaphoreInfo(&cache_info->semaphore);
1111 cache_info->signature=(~MagickCoreSignature);
1112 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1143static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1145 if (nexus_info->mapped == MagickFalse)
1146 (void) RelinquishAlignedMemory(nexus_info->cache);
1148 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1149 nexus_info->cache=(Quantum *) NULL;
1150 nexus_info->pixels=(Quantum *) NULL;
1151 nexus_info->metacontent=(
void *) NULL;
1152 nexus_info->length=0;
1153 nexus_info->mapped=MagickFalse;
1156MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1157 const size_t number_threads)
1162 assert(nexus_info != (NexusInfo **) NULL);
1163 for (i=0; i < (ssize_t) (2*number_threads); i++)
1165 if (nexus_info[i]->cache != (Quantum *) NULL)
1166 RelinquishCacheNexusPixels(nexus_info[i]);
1167 nexus_info[i]->signature=(~MagickCoreSignature);
1169 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1170 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1199MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1202 *magick_restrict cache_info;
1205 id = GetOpenMPThreadId();
1207 assert(image != (
const Image *) NULL);
1208 assert(image->signature == MagickCoreSignature);
1209 assert(image->cache != (Cache) NULL);
1210 cache_info=(CacheInfo *) image->cache;
1211 assert(cache_info->signature == MagickCoreSignature);
1212 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1213 (GetAuthenticMetacontentFromHandler) NULL)
1218 metacontent=cache_info->methods.
1219 get_authentic_metacontent_from_handler(image);
1220 return(metacontent);
1222 assert(
id < (
int) cache_info->number_threads);
1223 return(cache_info->nexus_info[
id]->metacontent);
1250static void *GetAuthenticMetacontentFromCache(
const Image *image)
1253 *magick_restrict cache_info;
1256 id = GetOpenMPThreadId();
1258 assert(image != (
const Image *) NULL);
1259 assert(image->signature == MagickCoreSignature);
1260 assert(image->cache != (Cache) NULL);
1261 cache_info=(CacheInfo *) image->cache;
1262 assert(cache_info->signature == MagickCoreSignature);
1263 assert(
id < (
int) cache_info->number_threads);
1264 return(cache_info->nexus_info[
id]->metacontent);
1267#if defined(MAGICKCORE_OPENCL_SUPPORT)
1296MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1297 MagickCLDevice device,ExceptionInfo *exception)
1300 *magick_restrict cache_info;
1302 assert(image != (
const Image *) NULL);
1303 assert(device != (
const MagickCLDevice) NULL);
1304 cache_info=(CacheInfo *) image->cache;
1305 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1307 (void) SyncImagePixelCache((Image *) image,exception);
1308 cache_info=(CacheInfo *) image->cache;
1310 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1311 return((cl_mem) NULL);
1312 LockSemaphoreInfo(cache_info->semaphore);
1313 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1314 (cache_info->opencl->device->context != device->context))
1315 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1316 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1318 assert(cache_info->pixels != (Quantum *) NULL);
1319 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1320 cache_info->length);
1322 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1323 RetainOpenCLMemObject(cache_info->opencl->buffer);
1324 UnlockSemaphoreInfo(cache_info->semaphore);
1325 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1326 return((cl_mem) NULL);
1327 assert(cache_info->opencl->pixels == cache_info->pixels);
1328 return(cache_info->opencl->buffer);
1367MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
const ssize_t x,
1368 const ssize_t y,
const size_t columns,
const size_t rows,NexusInfo *nexus_info,
1369 ExceptionInfo *exception)
1372 *magick_restrict cache_info;
1375 *magick_restrict pixels;
1380 assert(image != (Image *) NULL);
1381 assert(image->signature == MagickCoreSignature);
1382 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1383 nexus_info,exception);
1384 if (pixels == (Quantum *) NULL)
1385 return((Quantum *) NULL);
1386 cache_info=(CacheInfo *) image->cache;
1387 assert(cache_info->signature == MagickCoreSignature);
1388 if (nexus_info->authentic_pixel_cache != MagickFalse)
1390 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1391 return((Quantum *) NULL);
1392 if (cache_info->metacontent_extent != 0)
1393 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1394 return((Quantum *) NULL);
1421static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1424 *magick_restrict cache_info;
1427 id = GetOpenMPThreadId();
1429 assert(image != (
const Image *) NULL);
1430 assert(image->signature == MagickCoreSignature);
1431 assert(image->cache != (Cache) NULL);
1432 cache_info=(CacheInfo *) image->cache;
1433 assert(cache_info->signature == MagickCoreSignature);
1434 assert(
id < (
int) cache_info->number_threads);
1435 return(cache_info->nexus_info[
id]->pixels);
1462MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1465 *magick_restrict cache_info;
1468 id = GetOpenMPThreadId();
1470 assert(image != (
const Image *) NULL);
1471 assert(image->signature == MagickCoreSignature);
1472 assert(image->cache != (Cache) NULL);
1473 cache_info=(CacheInfo *) image->cache;
1474 assert(cache_info->signature == MagickCoreSignature);
1475 if (cache_info->methods.get_authentic_pixels_from_handler !=
1476 (GetAuthenticPixelsFromHandler) NULL)
1477 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1478 assert(
id < (
int) cache_info->number_threads);
1479 return(cache_info->nexus_info[
id]->pixels);
1527MagickExport Quantum *GetAuthenticPixels(Image *image,
const ssize_t x,
1528 const ssize_t y,
const size_t columns,
const size_t rows,
1529 ExceptionInfo *exception)
1532 *magick_restrict cache_info;
1535 id = GetOpenMPThreadId();
1540 assert(image != (Image *) NULL);
1541 assert(image->signature == MagickCoreSignature);
1542 assert(image->cache != (Cache) NULL);
1543 cache_info=(CacheInfo *) image->cache;
1544 assert(cache_info->signature == MagickCoreSignature);
1545 if (cache_info->methods.get_authentic_pixels_handler !=
1546 (GetAuthenticPixelsHandler) NULL)
1548 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1552 assert(
id < (
int) cache_info->number_threads);
1553 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1554 cache_info->nexus_info[
id],exception);
1589static Quantum *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1590 const ssize_t y,
const size_t columns,
const size_t rows,
1591 ExceptionInfo *exception)
1594 *magick_restrict cache_info;
1597 id = GetOpenMPThreadId();
1600 *magick_restrict pixels;
1602 assert(image != (
const Image *) NULL);
1603 assert(image->signature == MagickCoreSignature);
1604 assert(image->cache != (Cache) NULL);
1605 cache_info=(CacheInfo *) image->cache;
1606 if (cache_info == (Cache) NULL)
1607 return((Quantum *) NULL);
1608 assert(cache_info->signature == MagickCoreSignature);
1609 assert(
id < (
int) cache_info->number_threads);
1610 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1611 cache_info->nexus_info[
id],exception);
1638MagickExport MagickSizeType GetImageExtent(
const Image *image)
1641 *magick_restrict cache_info;
1644 id = GetOpenMPThreadId();
1646 assert(image != (Image *) NULL);
1647 assert(image->signature == MagickCoreSignature);
1648 if (IsEventLogging() != MagickFalse)
1649 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1650 assert(image->cache != (Cache) NULL);
1651 cache_info=(CacheInfo *) image->cache;
1652 assert(cache_info->signature == MagickCoreSignature);
1653 assert(
id < (
int) cache_info->number_threads);
1654 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1687static MagickBooleanType GetDynamicThrottlePolicy(
void)
1689 static MagickBooleanType
1690 check_policy = MagickTrue;
1692 static MagickBooleanType
1693 dynamic_throttle = MagickFalse;
1695 if (check_policy != MagickFalse)
1697 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1698 if (value != (
char *) NULL)
1700 dynamic_throttle=IsStringTrue(value);
1701 value=DestroyString(value);
1703 check_policy=MagickFalse;
1705 return(dynamic_throttle);
1708static inline MagickBooleanType ValidatePixelCacheMorphology(
1709 const Image *magick_restrict image)
1712 *magick_restrict cache_info;
1714 const PixelChannelMap
1721 cache_info=(CacheInfo *) image->cache;
1722 p=image->channel_map;
1723 q=cache_info->channel_map;
1724 if ((image->storage_class != cache_info->storage_class) ||
1725 (image->colorspace != cache_info->colorspace) ||
1726 (image->alpha_trait != cache_info->alpha_trait) ||
1727 (image->channels != cache_info->channels) ||
1728 (image->columns != cache_info->columns) ||
1729 (image->rows != cache_info->rows) ||
1730 (image->number_channels != cache_info->number_channels) ||
1731 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1732 (image->metacontent_extent != cache_info->metacontent_extent) ||
1733 (cache_info->nexus_info == (NexusInfo **) NULL))
1734 return(MagickFalse);
1738static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1739 ExceptionInfo *exception)
1742 *magick_restrict cache_info;
1746 status = MagickTrue;
1748 static MagickSizeType
1749 cpu_throttle = MagickResourceInfinity,
1752 if (IsImageTTLExpired(image) != MagickFalse)
1757 (void) ThrowMagickException(exception,GetMagickModule(),
1758 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1759 return((Cache) NULL);
1761 if (cpu_throttle == MagickResourceInfinity)
1762 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1763 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1776#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1777 if (getloadavg(&load_average,1) != 1)
1780 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1781 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1783 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1784 MagickDelay(cpu_throttle);
1786 LockSemaphoreInfo(image->semaphore);
1787 assert(image->cache != (Cache) NULL);
1788 cache_info=(CacheInfo *) image->cache;
1789#if defined(MAGICKCORE_OPENCL_SUPPORT)
1790 CopyOpenCLBuffer(cache_info);
1792 destroy=MagickFalse;
1793 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1795 LockSemaphoreInfo(cache_info->semaphore);
1796 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1807 clone_image=(*image);
1808 clone_image.semaphore=AcquireSemaphoreInfo();
1809 clone_image.reference_count=1;
1810 clone_image.cache=ClonePixelCache(cache_info);
1811 clone_info=(CacheInfo *) clone_image.cache;
1812 status=OpenPixelCache(&clone_image,IOMode,exception);
1813 if (status == MagickFalse)
1814 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1817 if (clone != MagickFalse)
1818 status=ClonePixelCacheRepository(clone_info,cache_info,
1820 if (status == MagickFalse)
1821 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1825 image->cache=clone_info;
1828 RelinquishSemaphoreInfo(&clone_image.semaphore);
1830 UnlockSemaphoreInfo(cache_info->semaphore);
1832 if (destroy != MagickFalse)
1833 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1834 if (status != MagickFalse)
1839 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1841 image->type=UndefinedType;
1842 status=OpenPixelCache(image,IOMode,exception);
1843 cache_info=(CacheInfo *) image->cache;
1844 if (cache_info->file != -1)
1845 (void) ClosePixelCacheOnDisk(cache_info);
1848 UnlockSemaphoreInfo(image->semaphore);
1849 if (status == MagickFalse)
1850 return((Cache) NULL);
1851 return(image->cache);
1877MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1880 *magick_restrict cache_info;
1882 assert(image != (Image *) NULL);
1883 assert(image->signature == MagickCoreSignature);
1884 assert(image->cache != (Cache) NULL);
1885 cache_info=(CacheInfo *) image->cache;
1886 assert(cache_info->signature == MagickCoreSignature);
1887 return(cache_info->type);
1921static inline MagickBooleanType CopyPixel(
const Image *image,
1922 const Quantum *source,Quantum *destination)
1927 if (source == (
const Quantum *) NULL)
1929 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1930 destination[GreenPixelChannel]=ClampToQuantum(
1931 image->background_color.green);
1932 destination[BluePixelChannel]=ClampToQuantum(
1933 image->background_color.blue);
1934 destination[BlackPixelChannel]=ClampToQuantum(
1935 image->background_color.black);
1936 destination[AlphaPixelChannel]=ClampToQuantum(
1937 image->background_color.alpha);
1938 return(MagickFalse);
1940 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1942 PixelChannel channel = GetPixelChannelChannel(image,i);
1943 destination[channel]=source[i];
1948MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1949 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1952 *magick_restrict cache_info;
1957 assert(image != (Image *) NULL);
1958 assert(image->signature == MagickCoreSignature);
1959 assert(image->cache != (Cache) NULL);
1960 cache_info=(CacheInfo *) image->cache;
1961 assert(cache_info->signature == MagickCoreSignature);
1962 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1963 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1964 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1965 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1966 return(CopyPixel(image,q,pixel));
2000static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
2001 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2004 *magick_restrict cache_info;
2007 id = GetOpenMPThreadId();
2012 assert(image != (
const Image *) NULL);
2013 assert(image->signature == MagickCoreSignature);
2014 assert(image->cache != (Cache) NULL);
2015 cache_info=(CacheInfo *) image->cache;
2016 assert(cache_info->signature == MagickCoreSignature);
2017 assert(
id < (
int) cache_info->number_threads);
2018 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2019 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2021 return(CopyPixel(image,q,pixel));
2055MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2056 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2059 *magick_restrict cache_info;
2062 id = GetOpenMPThreadId();
2067 assert(image != (
const Image *) NULL);
2068 assert(image->signature == MagickCoreSignature);
2069 assert(image->cache != (Cache) NULL);
2070 cache_info=(CacheInfo *) image->cache;
2071 assert(cache_info->signature == MagickCoreSignature);
2072 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2073 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2074 (GetOneVirtualPixelFromHandler) NULL)
2075 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2076 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2077 assert(
id < (
int) cache_info->number_threads);
2078 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2079 1UL,1UL,cache_info->nexus_info[
id],exception);
2080 return(CopyPixel(image,p,pixel));
2117static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2118 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2119 Quantum *pixel,ExceptionInfo *exception)
2122 *magick_restrict cache_info;
2125 id = GetOpenMPThreadId();
2130 assert(image != (
const Image *) NULL);
2131 assert(image->signature == MagickCoreSignature);
2132 assert(image->cache != (Cache) NULL);
2133 cache_info=(CacheInfo *) image->cache;
2134 assert(cache_info->signature == MagickCoreSignature);
2135 assert(
id < (
int) cache_info->number_threads);
2136 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2137 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2138 cache_info->nexus_info[
id],exception);
2139 return(CopyPixel(image,p,pixel));
2176MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2177 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2178 PixelInfo *pixel,ExceptionInfo *exception)
2181 *magick_restrict cache_info;
2184 id = GetOpenMPThreadId();
2189 assert(image != (
const Image *) NULL);
2190 assert(image->signature == MagickCoreSignature);
2191 assert(image->cache != (Cache) NULL);
2192 cache_info=(CacheInfo *) image->cache;
2193 assert(cache_info->signature == MagickCoreSignature);
2194 assert(
id < (
int) cache_info->number_threads);
2195 GetPixelInfo(image,pixel);
2196 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2197 cache_info->nexus_info[
id],exception);
2198 if (p == (
const Quantum *) NULL)
2199 return(MagickFalse);
2200 GetPixelInfoPixel(image,p,pixel);
2226MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2229 *magick_restrict cache_info;
2231 assert(cache != (Cache) NULL);
2232 cache_info=(CacheInfo *) cache;
2233 assert(cache_info->signature == MagickCoreSignature);
2234 if (IsEventLogging() != MagickFalse)
2235 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2236 cache_info->filename);
2237 return(cache_info->colorspace);
2263MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2266 *magick_restrict cache_info;
2268 assert(image != (
const Image *) NULL);
2269 assert(image->signature == MagickCoreSignature);
2270 assert(image->cache != (Cache) NULL);
2271 cache_info=(CacheInfo *) image->cache;
2272 assert(cache_info->signature == MagickCoreSignature);
2273 return(cache_info->cache_filename);
2298MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2300 assert(cache_methods != (CacheMethods *) NULL);
2301 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2302 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2303 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2304 cache_methods->get_virtual_metacontent_from_handler=
2305 GetVirtualMetacontentFromCache;
2306 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2307 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2308 cache_methods->get_authentic_metacontent_from_handler=
2309 GetAuthenticMetacontentFromCache;
2310 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2311 cache_methods->get_one_authentic_pixel_from_handler=
2312 GetOneAuthenticPixelFromCache;
2313 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2314 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2315 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2343MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2344 NexusInfo *magick_restrict nexus_info)
2347 *magick_restrict cache_info;
2352 assert(cache != NULL);
2353 cache_info=(CacheInfo *) cache;
2354 assert(cache_info->signature == MagickCoreSignature);
2355 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2357 return((MagickSizeType) cache_info->columns*cache_info->rows);
2388MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2389 ExceptionInfo *magick_unused(exception))
2392 *magick_restrict cache_info;
2394 assert(image != (
const Image *) NULL);
2395 assert(image->signature == MagickCoreSignature);
2396 assert(image->cache != (Cache) NULL);
2397 assert(length != (MagickSizeType *) NULL);
2398 magick_unreferenced(exception);
2399 cache_info=(CacheInfo *) image->cache;
2400 assert(cache_info->signature == MagickCoreSignature);
2401 *length=cache_info->length;
2402 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2403 return((
void *) NULL);
2404 return((
void *) cache_info->pixels);
2431MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2434 *magick_restrict cache_info;
2436 assert(cache != (Cache) NULL);
2437 cache_info=(CacheInfo *) cache;
2438 assert(cache_info->signature == MagickCoreSignature);
2439 if (IsEventLogging() != MagickFalse)
2440 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2441 cache_info->filename);
2442 return(cache_info->storage_class);
2472MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2476 *magick_restrict cache_info;
2478 assert(image != (Image *) NULL);
2479 assert(image->signature == MagickCoreSignature);
2480 if (IsEventLogging() != MagickFalse)
2481 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2482 cache_info=(CacheInfo *) image->cache;
2483 assert(cache_info->signature == MagickCoreSignature);
2484 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2485 if (GetImagePixelCacheType(image) == DiskCache)
2486 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2514MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2517 *magick_restrict cache_info;
2519 assert(image != (Image *) NULL);
2520 assert(image->signature == MagickCoreSignature);
2521 assert(image->cache != (Cache) NULL);
2522 cache_info=(CacheInfo *) image->cache;
2523 assert(cache_info->signature == MagickCoreSignature);
2524 return(cache_info->virtual_pixel_method);
2550static const void *GetVirtualMetacontentFromCache(
const Image *image)
2553 *magick_restrict cache_info;
2556 id = GetOpenMPThreadId();
2559 *magick_restrict metacontent;
2561 assert(image != (
const Image *) NULL);
2562 assert(image->signature == MagickCoreSignature);
2563 assert(image->cache != (Cache) NULL);
2564 cache_info=(CacheInfo *) image->cache;
2565 assert(cache_info->signature == MagickCoreSignature);
2566 assert(
id < (
int) cache_info->number_threads);
2567 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2568 cache_info->nexus_info[
id]);
2569 return(metacontent);
2598MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2599 NexusInfo *magick_restrict nexus_info)
2602 *magick_restrict cache_info;
2604 assert(cache != (Cache) NULL);
2605 cache_info=(CacheInfo *) cache;
2606 assert(cache_info->signature == MagickCoreSignature);
2607 if (cache_info->storage_class == UndefinedClass)
2608 return((
void *) NULL);
2609 return(nexus_info->metacontent);
2636MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2639 *magick_restrict cache_info;
2642 id = GetOpenMPThreadId();
2645 *magick_restrict metacontent;
2647 assert(image != (
const Image *) NULL);
2648 assert(image->signature == MagickCoreSignature);
2649 assert(image->cache != (Cache) NULL);
2650 cache_info=(CacheInfo *) image->cache;
2651 assert(cache_info->signature == MagickCoreSignature);
2652 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2654 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2656 if (metacontent != (
const void *) NULL)
2657 return(metacontent);
2659 assert(
id < (
int) cache_info->number_threads);
2660 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2661 cache_info->nexus_info[
id]);
2662 return(metacontent);
2705 0, 48, 12, 60, 3, 51, 15, 63,
2706 32, 16, 44, 28, 35, 19, 47, 31,
2707 8, 56, 4, 52, 11, 59, 7, 55,
2708 40, 24, 36, 20, 43, 27, 39, 23,
2709 2, 50, 14, 62, 1, 49, 13, 61,
2710 34, 18, 46, 30, 33, 17, 45, 29,
2711 10, 58, 6, 54, 9, 57, 5, 53,
2712 42, 26, 38, 22, 41, 25, 37, 21
2715static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2720 index=x+DitherMatrix[x & 0x07]-32L;
2723 if (index >= (ssize_t) columns)
2724 return((ssize_t) columns-1L);
2728static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2733 index=y+DitherMatrix[y & 0x07]-32L;
2736 if (index >= (ssize_t) rows)
2737 return((ssize_t) rows-1L);
2741static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2745 if (x >= (ssize_t) columns)
2746 return((ssize_t) (columns-1));
2750static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2754 if (y >= (ssize_t) rows)
2755 return((ssize_t) (rows-1));
2759static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2760 const MagickOffsetType y)
2762 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2763 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2764 return(MagickFalse);
2768static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2770 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2773static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2775 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2778static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2779 const size_t extent)
2784 modulo.quotient=offset;
2788 modulo.quotient=offset/((ssize_t) extent);
2789 modulo.remainder=offset % ((ssize_t) extent);
2791 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2794 modulo.remainder+=((ssize_t) extent);
2799MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2800 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2801 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2802 ExceptionInfo *exception)
2805 *magick_restrict cache_info;
2821 *magick_restrict virtual_nexus;
2824 *magick_restrict pixels,
2826 virtual_pixel[MaxPixelChannels];
2837 *magick_restrict virtual_metacontent;
2842 assert(image != (
const Image *) NULL);
2843 assert(image->signature == MagickCoreSignature);
2844 assert(image->cache != (Cache) NULL);
2845 cache_info=(CacheInfo *) image->cache;
2846 assert(cache_info->signature == MagickCoreSignature);
2847 if (cache_info->type == UndefinedCache)
2848 return((
const Quantum *) NULL);
2849#if defined(MAGICKCORE_OPENCL_SUPPORT)
2850 CopyOpenCLBuffer(cache_info);
2852 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2853 ((image->channels & WriteMaskChannel) != 0) ||
2854 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2855 nexus_info,exception);
2856 if (pixels == (Quantum *) NULL)
2857 return((
const Quantum *) NULL);
2858 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2859 return((
const Quantum *) NULL);
2860 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2861 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2862 return((
const Quantum *) NULL);
2863 offset+=nexus_info->region.x;
2864 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2865 nexus_info->region.width-1L;
2866 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2867 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2868 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2869 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2877 if (nexus_info->authentic_pixel_cache != MagickFalse)
2879 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2880 if (status == MagickFalse)
2881 return((
const Quantum *) NULL);
2882 if (cache_info->metacontent_extent != 0)
2884 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2885 if (status == MagickFalse)
2886 return((
const Quantum *) NULL);
2893 virtual_nexus=nexus_info->virtual_nexus;
2895 s=(
unsigned char *) nexus_info->metacontent;
2896 (void) memset(virtual_pixel,0,cache_info->number_channels*
2897 sizeof(*virtual_pixel));
2898 virtual_metacontent=(
void *) NULL;
2899 switch (virtual_pixel_method)
2901 case BackgroundVirtualPixelMethod:
2902 case BlackVirtualPixelMethod:
2903 case GrayVirtualPixelMethod:
2904 case TransparentVirtualPixelMethod:
2905 case MaskVirtualPixelMethod:
2906 case WhiteVirtualPixelMethod:
2907 case EdgeVirtualPixelMethod:
2908 case CheckerTileVirtualPixelMethod:
2909 case HorizontalTileVirtualPixelMethod:
2910 case VerticalTileVirtualPixelMethod:
2912 if (cache_info->metacontent_extent != 0)
2917 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2918 cache_info->metacontent_extent);
2919 if (virtual_metacontent == (
void *) NULL)
2921 (void) ThrowMagickException(exception,GetMagickModule(),
2922 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2923 return((
const Quantum *) NULL);
2925 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2927 switch (virtual_pixel_method)
2929 case BlackVirtualPixelMethod:
2931 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2932 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2933 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2936 case GrayVirtualPixelMethod:
2938 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2939 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2941 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2944 case TransparentVirtualPixelMethod:
2946 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2947 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2948 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2951 case MaskVirtualPixelMethod:
2952 case WhiteVirtualPixelMethod:
2954 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2955 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2956 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2961 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2963 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2965 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2967 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2969 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2979 for (v=0; v < (ssize_t) rows; v++)
2985 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2986 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2987 y_offset=EdgeY(y_offset,cache_info->rows);
2988 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2994 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2995 x_offset,(ssize_t) columns-u);
2996 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2997 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
3007 length=(MagickSizeType) 1;
3008 switch (virtual_pixel_method)
3010 case EdgeVirtualPixelMethod:
3013 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3014 EdgeX(x_offset,cache_info->columns),
3015 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3017 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3020 case RandomVirtualPixelMethod:
3022 if (cache_info->random_info == (RandomInfo *) NULL)
3023 cache_info->random_info=AcquireRandomInfo();
3024 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3025 RandomX(cache_info->random_info,cache_info->columns),
3026 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3027 virtual_nexus,exception);
3028 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3031 case DitherVirtualPixelMethod:
3033 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3034 DitherX(x_offset,cache_info->columns),
3035 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3037 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3040 case TileVirtualPixelMethod:
3042 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3043 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3044 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3045 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3047 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3050 case MirrorVirtualPixelMethod:
3052 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3053 if ((x_modulo.quotient & 0x01) == 1L)
3054 x_modulo.remainder=(ssize_t) cache_info->columns-
3055 x_modulo.remainder-1L;
3056 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3057 if ((y_modulo.quotient & 0x01) == 1L)
3058 y_modulo.remainder=(ssize_t) cache_info->rows-
3059 y_modulo.remainder-1L;
3060 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3061 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3063 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3066 case HorizontalTileEdgeVirtualPixelMethod:
3068 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3069 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3070 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3071 virtual_nexus,exception);
3072 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3075 case VerticalTileEdgeVirtualPixelMethod:
3077 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3078 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3079 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3080 virtual_nexus,exception);
3081 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3084 case BackgroundVirtualPixelMethod:
3085 case BlackVirtualPixelMethod:
3086 case GrayVirtualPixelMethod:
3087 case TransparentVirtualPixelMethod:
3088 case MaskVirtualPixelMethod:
3089 case WhiteVirtualPixelMethod:
3092 r=virtual_metacontent;
3095 case CheckerTileVirtualPixelMethod:
3097 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3098 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3099 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3102 r=virtual_metacontent;
3105 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3106 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3108 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3111 case HorizontalTileVirtualPixelMethod:
3113 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3116 r=virtual_metacontent;
3119 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3120 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3121 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3122 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3124 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3127 case VerticalTileVirtualPixelMethod:
3129 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3132 r=virtual_metacontent;
3135 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3136 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3137 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3138 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3140 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3144 if (p == (
const Quantum *) NULL)
3146 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3148 q+=(ptrdiff_t) cache_info->number_channels;
3149 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3151 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3152 s+=(ptrdiff_t) cache_info->metacontent_extent;
3159 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3160 (
size_t) length,1UL,virtual_nexus,exception);
3161 if (p == (
const Quantum *) NULL)
3163 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3164 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3166 q+=(ptrdiff_t) cache_info->number_channels*length;
3167 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3169 (void) memcpy(s,r,(
size_t) length);
3170 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3173 if (u < (ssize_t) columns)
3179 if (virtual_metacontent != (
void *) NULL)
3180 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3181 if (v < (ssize_t) rows)
3182 return((
const Quantum *) NULL);
3220static const Quantum *GetVirtualPixelCache(
const Image *image,
3221 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3222 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3225 *magick_restrict cache_info;
3228 id = GetOpenMPThreadId();
3233 assert(image != (
const Image *) NULL);
3234 assert(image->signature == MagickCoreSignature);
3235 assert(image->cache != (Cache) NULL);
3236 cache_info=(CacheInfo *) image->cache;
3237 assert(cache_info->signature == MagickCoreSignature);
3238 assert(
id < (
int) cache_info->number_threads);
3239 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3240 cache_info->nexus_info[
id],exception);
3267MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3270 *magick_restrict cache_info;
3273 id = GetOpenMPThreadId();
3275 assert(image != (
const Image *) NULL);
3276 assert(image->signature == MagickCoreSignature);
3277 assert(image->cache != (Cache) NULL);
3278 cache_info=(CacheInfo *) image->cache;
3279 assert(cache_info->signature == MagickCoreSignature);
3280 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3281 return(cache_info->methods.get_virtual_pixels_handler(image));
3282 assert(
id < (
int) cache_info->number_threads);
3283 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3334MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3335 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3336 ExceptionInfo *exception)
3339 *magick_restrict cache_info;
3342 id = GetOpenMPThreadId();
3347 assert(image != (
const Image *) NULL);
3348 assert(image->signature == MagickCoreSignature);
3349 assert(image->cache != (Cache) NULL);
3350 cache_info=(CacheInfo *) image->cache;
3351 assert(cache_info->signature == MagickCoreSignature);
3352 if (cache_info->methods.get_virtual_pixel_handler !=
3353 (GetVirtualPixelHandler) NULL)
3354 return(cache_info->methods.get_virtual_pixel_handler(image,
3355 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3356 assert(
id < (
int) cache_info->number_threads);
3357 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3358 columns,rows,cache_info->nexus_info[
id],exception);
3385static const Quantum *GetVirtualPixelsCache(
const Image *image)
3388 *magick_restrict cache_info;
3391 id = GetOpenMPThreadId();
3393 assert(image != (
const Image *) NULL);
3394 assert(image->signature == MagickCoreSignature);
3395 assert(image->cache != (Cache) NULL);
3396 cache_info=(CacheInfo *) image->cache;
3397 assert(cache_info->signature == MagickCoreSignature);
3398 assert(
id < (
int) cache_info->number_threads);
3399 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3428MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3429 NexusInfo *magick_restrict nexus_info)
3432 *magick_restrict cache_info;
3434 assert(cache != (Cache) NULL);
3435 cache_info=(CacheInfo *) cache;
3436 assert(cache_info->signature == MagickCoreSignature);
3437 if (cache_info->storage_class == UndefinedClass)
3438 return((Quantum *) NULL);
3439 return((
const Quantum *) nexus_info->pixels);
3472static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3473 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3478 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3480 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3481 gamma=MagickSafeReciprocal(gamma);
3482 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3485static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3486 ExceptionInfo *exception)
3489 *magick_restrict cache_info;
3501 if (IsEventLogging() != MagickFalse)
3502 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3503 if ((image->channels & CompositeMaskChannel) == 0)
3505 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3507 cache_info=(CacheInfo *) image->cache;
3508 if (cache_info == (Cache) NULL)
3509 return(MagickFalse);
3510 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3511 nexus_info->region.width,nexus_info->region.height,
3512 nexus_info->virtual_nexus,exception);
3513 q=nexus_info->pixels;
3514 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3515 return(MagickFalse);
3516 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3521 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3529 alpha=(double) GetPixelCompositeMask(image,p);
3530 for (i=0; i < (ssize_t) image->number_channels; i++)
3532 PixelChannel channel = GetPixelChannelChannel(image,i);
3533 PixelTrait traits = GetPixelChannelTraits(image,channel);
3534 if ((traits & UpdatePixelTrait) == 0)
3536 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3538 p+=(ptrdiff_t) GetPixelChannels(image);
3539 q+=(ptrdiff_t) GetPixelChannels(image);
3576static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3577 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3582 if ((count == 0) || (quantum == 0))
3584 length=count*quantum;
3585 if (quantum != (length/count))
3592 return(MagickFalse);
3595static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3604 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3606 if (*cache_info->cache_filename ==
'\0')
3607 file=AcquireUniqueFileResource(cache_info->cache_filename);
3613 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3618 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3619 O_BINARY | O_EXCL,S_MODE);
3621 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3627 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3630 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3635 return(MagickFalse);
3636 (void) AcquireMagickResource(FileResource,1);
3637 if (cache_info->file != -1)
3638 (void) ClosePixelCacheOnDisk(cache_info);
3639 cache_info->file=file;
3640 cache_info->disk_mode=mode;
3644static inline MagickOffsetType WritePixelCacheRegion(
3645 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3646 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3654#if !defined(MAGICKCORE_HAVE_PWRITE)
3655 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3656 return((MagickOffsetType) -1);
3658 for (i=0; i < (MagickOffsetType) length; i+=count)
3660#if !defined(MAGICKCORE_HAVE_PWRITE)
3661 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3662 (MagickSizeType) i,MagickMaxBufferExtent));
3664 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3665 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3677static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3680 *magick_restrict cache_info;
3685 cache_info=(CacheInfo *) image->cache;
3686 if (cache_info->debug != MagickFalse)
3689 format[MagickPathExtent],
3690 message[MagickPathExtent];
3692 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3693 (void) FormatLocaleString(message,MagickPathExtent,
3694 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3695 cache_info->cache_filename,cache_info->file,format);
3696 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3698 if (length != (MagickSizeType) ((MagickOffsetType) length))
3699 return(MagickFalse);
3700 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3702 return(MagickFalse);
3703 if ((MagickSizeType) offset < length)
3709 extent=(MagickOffsetType) length-1;
3710 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3713 return(MagickFalse);
3714#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3715 if (cache_info->synchronize != MagickFalse)
3716 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3717 return(MagickFalse);
3720 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3722 return(MagickFalse);
3726static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3727 ExceptionInfo *exception)
3730 *magick_restrict cache_info,
3734 format[MagickPathExtent],
3735 message[MagickPathExtent];
3752 assert(image != (
const Image *) NULL);
3753 assert(image->signature == MagickCoreSignature);
3754 assert(image->cache != (Cache) NULL);
3755 if (IsEventLogging() != MagickFalse)
3756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3757 if (cache_anonymous_memory < 0)
3765 cache_anonymous_memory=0;
3766 value=GetPolicyValue(
"pixel-cache-memory");
3767 if (value == (
char *) NULL)
3768 value=GetPolicyValue(
"cache:memory-map");
3769 if (LocaleCompare(value,
"anonymous") == 0)
3771#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3772 cache_anonymous_memory=1;
3774 (void) ThrowMagickException(exception,GetMagickModule(),
3775 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3776 "`%s' (policy requires anonymous memory mapping)",image->filename);
3779 value=DestroyString(value);
3781 if ((image->columns == 0) || (image->rows == 0))
3782 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3783 cache_info=(CacheInfo *) image->cache;
3784 assert(cache_info->signature == MagickCoreSignature);
3785 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3786 ((MagickSizeType) image->rows > cache_info->height_limit))
3788 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3789 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3790 image->filename, (
double) image->columns, (
double) image->rows,
3791 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3792 return(MagickFalse);
3794 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3796 length=GetImageListLength(image);
3797 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3798 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3801 source_info=(*cache_info);
3802 source_info.file=(-1);
3803 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3804 image->filename,(
double) image->scene);
3805 cache_info->storage_class=image->storage_class;
3806 cache_info->colorspace=image->colorspace;
3807 cache_info->alpha_trait=image->alpha_trait;
3808 cache_info->channels=image->channels;
3809 cache_info->rows=image->rows;
3810 cache_info->columns=image->columns;
3811 status=ResetPixelChannelMap(image,exception);
3812 if (status == MagickFalse)
3813 return(MagickFalse);
3814 cache_info->number_channels=GetPixelChannels(image);
3815 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3816 sizeof(*image->channel_map));
3817 cache_info->metacontent_extent=image->metacontent_extent;
3818 cache_info->mode=mode;
3819 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3820 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3821 if (image->metacontent_extent != 0)
3822 packet_size+=cache_info->metacontent_extent;
3823 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3825 cache_info->storage_class=UndefinedClass;
3826 cache_info->length=0;
3827 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3830 columns=(size_t) (length/cache_info->rows/packet_size);
3831 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3832 ((ssize_t) cache_info->rows < 0))
3834 cache_info->storage_class=UndefinedClass;
3835 cache_info->length=0;
3836 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3839 cache_info->length=length;
3840 if (image->ping != MagickFalse)
3842 cache_info->type=PingCache;
3845 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3846 cache_info->columns*cache_info->rows);
3847 if (cache_info->mode == PersistMode)
3849 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3850 cache_info->metacontent_extent);
3851 if ((status != MagickFalse) &&
3852 (length == (MagickSizeType) ((
size_t) length)) &&
3853 ((cache_info->type == UndefinedCache) ||
3854 (cache_info->type == MemoryCache)))
3856 status=AcquireMagickResource(MemoryResource,cache_info->length);
3857 if (status != MagickFalse)
3860 if (cache_anonymous_memory <= 0)
3862 cache_info->mapped=MagickFalse;
3863 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3864 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3868 cache_info->mapped=MagickTrue;
3869 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3870 cache_info->length);
3872 if (cache_info->pixels == (Quantum *) NULL)
3874 cache_info->mapped=source_info.mapped;
3875 cache_info->pixels=source_info.pixels;
3882 cache_info->type=MemoryCache;
3883 cache_info->metacontent=(
void *) NULL;
3884 if (cache_info->metacontent_extent != 0)
3885 cache_info->metacontent=(
void *) (cache_info->pixels+
3886 cache_info->number_channels*number_pixels);
3887 if ((source_info.storage_class != UndefinedClass) &&
3890 status=ClonePixelCacheRepository(cache_info,&source_info,
3892 RelinquishPixelCachePixels(&source_info);
3894 if (cache_info->debug != MagickFalse)
3896 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3897 MagickPathExtent,format);
3898 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3900 (void) FormatLocaleString(message,MagickPathExtent,
3901 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3902 cache_info->filename,cache_info->mapped != MagickFalse ?
3903 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3904 (
double) cache_info->rows,(
double)
3905 cache_info->number_channels,format);
3906 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3909 cache_info->storage_class=image->storage_class;
3912 if ((source_info.storage_class != UndefinedClass) &&
3914 RelinquishPixelCachePixels(&source_info);
3915 cache_info->type=UndefinedCache;
3916 return(MagickFalse);
3922 status=AcquireMagickResource(DiskResource,cache_info->length);
3923 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3925 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3933 server_info=AcquireDistributeCacheInfo(exception);
3934 if (server_info != (DistributeCacheInfo *) NULL)
3936 status=OpenDistributePixelCache(server_info,image);
3937 if (status == MagickFalse)
3939 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3940 GetDistributeCacheHostname(server_info));
3941 server_info=DestroyDistributeCacheInfo(server_info);
3949 cache_info->type=DistributedCache;
3950 cache_info->server_info=server_info;
3951 (void) FormatLocaleString(cache_info->cache_filename,
3952 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3953 (DistributeCacheInfo *) cache_info->server_info),
3954 GetDistributeCachePort((DistributeCacheInfo *)
3955 cache_info->server_info));
3956 if ((source_info.storage_class != UndefinedClass) &&
3959 status=ClonePixelCacheRepository(cache_info,&source_info,
3961 RelinquishPixelCachePixels(&source_info);
3963 if (cache_info->debug != MagickFalse)
3965 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3966 MagickPathExtent,format);
3967 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3969 (void) FormatLocaleString(message,MagickPathExtent,
3970 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3971 cache_info->filename,cache_info->cache_filename,
3972 GetDistributeCacheFile((DistributeCacheInfo *)
3973 cache_info->server_info),type,(
double) cache_info->columns,
3974 (
double) cache_info->rows,(
double)
3975 cache_info->number_channels,format);
3976 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3981 if ((source_info.storage_class != UndefinedClass) &&
3983 RelinquishPixelCachePixels(&source_info);
3984 cache_info->type=UndefinedCache;
3985 return(MagickFalse);
3990 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3991 RelinquishPixelCachePixels(&source_info);
3992 cache_info->type=UndefinedCache;
3993 (void) memset(image->channel_map,0,MaxPixelChannels*
3994 sizeof(*image->channel_map));
3995 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3996 "CacheResourcesExhausted",
"`%s'",image->filename);
3997 return(MagickFalse);
4002 if (status == MagickFalse)
4004 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4005 RelinquishPixelCachePixels(&source_info);
4006 cache_info->type=UndefinedCache;
4007 (void) memset(image->channel_map,0,MaxPixelChannels*
4008 sizeof(*image->channel_map));
4009 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4010 "CacheResourcesExhausted",
"`%s'",image->filename);
4011 return(MagickFalse);
4013 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4014 (cache_info->mode != PersistMode))
4016 (void) ClosePixelCacheOnDisk(cache_info);
4017 *cache_info->cache_filename=
'\0';
4019 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4021 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4022 RelinquishPixelCachePixels(&source_info);
4023 cache_info->type=UndefinedCache;
4024 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4026 return(MagickFalse);
4028 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4029 cache_info->length);
4030 if (status == MagickFalse)
4032 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4033 RelinquishPixelCachePixels(&source_info);
4034 cache_info->type=UndefinedCache;
4035 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4037 return(MagickFalse);
4039 cache_info->type=DiskCache;
4040 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4041 cache_info->metacontent_extent);
4042 if (length == (MagickSizeType) ((
size_t) length))
4044 status=AcquireMagickResource(MapResource,cache_info->length);
4045 if (status != MagickFalse)
4047 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4048 cache_info->offset,(
size_t) cache_info->length);
4049 if (cache_info->pixels == (Quantum *) NULL)
4051 cache_info->mapped=source_info.mapped;
4052 cache_info->pixels=source_info.pixels;
4053 RelinquishMagickResource(MapResource,cache_info->length);
4060 (void) ClosePixelCacheOnDisk(cache_info);
4061 cache_info->type=MapCache;
4062 cache_info->mapped=MagickTrue;
4063 cache_info->metacontent=(
void *) NULL;
4064 if (cache_info->metacontent_extent != 0)
4065 cache_info->metacontent=(
void *) (cache_info->pixels+
4066 cache_info->number_channels*number_pixels);
4067 if ((source_info.storage_class != UndefinedClass) &&
4070 status=ClonePixelCacheRepository(cache_info,&source_info,
4072 RelinquishPixelCachePixels(&source_info);
4074 if (cache_info->debug != MagickFalse)
4076 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4077 MagickPathExtent,format);
4078 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4080 (void) FormatLocaleString(message,MagickPathExtent,
4081 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4082 cache_info->filename,cache_info->cache_filename,
4083 cache_info->file,type,(
double) cache_info->columns,
4084 (
double) cache_info->rows,(
double)
4085 cache_info->number_channels,format);
4086 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4091 if ((source_info.storage_class != UndefinedClass) &&
4093 RelinquishPixelCachePixels(&source_info);
4094 cache_info->type=UndefinedCache;
4095 return(MagickFalse);
4102 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4104 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4105 RelinquishPixelCachePixels(&source_info);
4107 if (cache_info->debug != MagickFalse)
4109 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4110 MagickPathExtent,format);
4111 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4113 (void) FormatLocaleString(message,MagickPathExtent,
4114 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4115 cache_info->cache_filename,cache_info->file,type,(
double)
4116 cache_info->columns,(
double) cache_info->rows,(
double)
4117 cache_info->number_channels,format);
4118 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4122 cache_info->type=UndefinedCache;
4123 return(MagickFalse);
4165MagickExport MagickBooleanType PersistPixelCache(Image *image,
4166 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4167 ExceptionInfo *exception)
4170 *magick_restrict cache_info,
4171 *magick_restrict clone_info;
4179 assert(image != (Image *) NULL);
4180 assert(image->signature == MagickCoreSignature);
4181 if (IsEventLogging() != MagickFalse)
4182 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4183 assert(image->cache != (
void *) NULL);
4184 assert(filename != (
const char *) NULL);
4185 assert(offset != (MagickOffsetType *) NULL);
4186 page_size=GetMagickPageSize();
4187 cache_info=(CacheInfo *) image->cache;
4188 assert(cache_info->signature == MagickCoreSignature);
4189#if defined(MAGICKCORE_OPENCL_SUPPORT)
4190 CopyOpenCLBuffer(cache_info);
4192 if (attach != MagickFalse)
4197 if (cache_info->debug != MagickFalse)
4198 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4199 "attach persistent cache");
4200 (void) CopyMagickString(cache_info->cache_filename,filename,
4202 cache_info->type=MapCache;
4203 cache_info->offset=(*offset);
4204 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4205 return(MagickFalse);
4206 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4207 ((MagickOffsetType) cache_info->length % page_size));
4213 status=AcquireMagickResource(DiskResource,cache_info->length);
4214 if (status == MagickFalse)
4216 cache_info->type=UndefinedCache;
4217 (void) memset(image->channel_map,0,MaxPixelChannels*
4218 sizeof(*image->channel_map));
4219 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4220 "CacheResourcesExhausted",
"`%s'",image->filename);
4221 return(MagickFalse);
4223 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4224 clone_info->type=DiskCache;
4225 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4226 clone_info->file=(-1);
4227 clone_info->storage_class=cache_info->storage_class;
4228 clone_info->colorspace=cache_info->colorspace;
4229 clone_info->alpha_trait=cache_info->alpha_trait;
4230 clone_info->channels=cache_info->channels;
4231 clone_info->columns=cache_info->columns;
4232 clone_info->rows=cache_info->rows;
4233 clone_info->number_channels=cache_info->number_channels;
4234 clone_info->metacontent_extent=cache_info->metacontent_extent;
4235 clone_info->mode=PersistMode;
4236 clone_info->length=cache_info->length;
4237 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4238 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4239 clone_info->offset=(*offset);
4240 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4241 if (status != MagickFalse)
4242 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4243 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4244 ((MagickOffsetType) cache_info->length % page_size));
4245 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4287MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4288 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4289 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4292 *magick_restrict cache_info;
4301 *magick_restrict pixels;
4306 assert(image != (
const Image *) NULL);
4307 assert(image->signature == MagickCoreSignature);
4308 assert(image->cache != (Cache) NULL);
4309 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4310 if (cache_info == (Cache) NULL)
4311 return((Quantum *) NULL);
4312 assert(cache_info->signature == MagickCoreSignature);
4313 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4314 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4315 (y >= (ssize_t) cache_info->rows))
4317 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4318 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4319 return((Quantum *) NULL);
4321 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4322 return((Quantum *) NULL);
4323 offset=y*(MagickOffsetType) cache_info->columns+x;
4325 return((Quantum *) NULL);
4326 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4327 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4328 (MagickOffsetType) columns-1;
4329 if ((MagickSizeType) offset >= number_pixels)
4330 return((Quantum *) NULL);
4334 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4335 ((image->channels & WriteMaskChannel) != 0) ||
4336 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4337 nexus_info,exception);
4374static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4375 const ssize_t y,
const size_t columns,
const size_t rows,
4376 ExceptionInfo *exception)
4379 *magick_restrict cache_info;
4382 id = GetOpenMPThreadId();
4385 *magick_restrict pixels;
4387 assert(image != (
const Image *) NULL);
4388 assert(image->signature == MagickCoreSignature);
4389 assert(image->cache != (Cache) NULL);
4390 cache_info=(CacheInfo *) image->cache;
4391 assert(cache_info->signature == MagickCoreSignature);
4392 assert(
id < (
int) cache_info->number_threads);
4393 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4394 cache_info->nexus_info[
id],exception);
4454MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4455 const ssize_t y,
const size_t columns,
const size_t rows,
4456 ExceptionInfo *exception)
4459 *magick_restrict cache_info;
4462 id = GetOpenMPThreadId();
4465 *magick_restrict pixels;
4467 assert(image != (Image *) NULL);
4468 assert(image->signature == MagickCoreSignature);
4469 assert(image->cache != (Cache) NULL);
4470 cache_info=(CacheInfo *) image->cache;
4471 assert(cache_info->signature == MagickCoreSignature);
4472 if (cache_info->methods.queue_authentic_pixels_handler !=
4473 (QueueAuthenticPixelsHandler) NULL)
4475 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4476 columns,rows,exception);
4479 assert(
id < (
int) cache_info->number_threads);
4480 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4481 cache_info->nexus_info[
id],exception);
4514static inline MagickOffsetType ReadPixelCacheRegion(
4515 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4516 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4524#if !defined(MAGICKCORE_HAVE_PREAD)
4525 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4526 return((MagickOffsetType) -1);
4528 for (i=0; i < (MagickOffsetType) length; i+=count)
4530#if !defined(MAGICKCORE_HAVE_PREAD)
4531 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4532 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4534 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4535 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4547static MagickBooleanType ReadPixelCacheMetacontent(
4548 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4549 ExceptionInfo *exception)
4568 if (cache_info->metacontent_extent == 0)
4569 return(MagickFalse);
4570 if (nexus_info->authentic_pixel_cache != MagickFalse)
4572 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4573 return(MagickFalse);
4574 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4575 nexus_info->region.x;
4576 length=(MagickSizeType) nexus_info->region.width*
4577 cache_info->metacontent_extent;
4578 extent=length*nexus_info->region.height;
4579 rows=nexus_info->region.height;
4581 q=(
unsigned char *) nexus_info->metacontent;
4582 switch (cache_info->type)
4593 if ((cache_info->columns == nexus_info->region.width) &&
4594 (extent == (MagickSizeType) ((
size_t) extent)))
4599 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4600 cache_info->metacontent_extent;
4601 for (y=0; y < (ssize_t) rows; y++)
4603 (void) memcpy(q,p,(
size_t) length);
4604 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4605 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4614 LockSemaphoreInfo(cache_info->file_semaphore);
4615 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4617 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4618 cache_info->cache_filename);
4619 UnlockSemaphoreInfo(cache_info->file_semaphore);
4620 return(MagickFalse);
4622 if ((cache_info->columns == nexus_info->region.width) &&
4623 (extent <= MagickMaxBufferExtent))
4628 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4629 for (y=0; y < (ssize_t) rows; y++)
4631 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4632 (MagickOffsetType) extent*(MagickOffsetType)
4633 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4634 (MagickOffsetType) cache_info->metacontent_extent,length,
4635 (
unsigned char *) q);
4636 if (count != (MagickOffsetType) length)
4638 offset+=(MagickOffsetType) cache_info->columns;
4639 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4641 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4642 (void) ClosePixelCacheOnDisk(cache_info);
4643 UnlockSemaphoreInfo(cache_info->file_semaphore);
4646 case DistributedCache:
4654 LockSemaphoreInfo(cache_info->file_semaphore);
4655 region=nexus_info->region;
4656 if ((cache_info->columns != nexus_info->region.width) ||
4657 (extent > MagickMaxBufferExtent))
4664 for (y=0; y < (ssize_t) rows; y++)
4666 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4667 cache_info->server_info,®ion,length,(
unsigned char *) q);
4668 if (count != (MagickOffsetType) length)
4670 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4673 UnlockSemaphoreInfo(cache_info->file_semaphore);
4679 if (y < (ssize_t) rows)
4681 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4682 cache_info->cache_filename);
4683 return(MagickFalse);
4685 if ((cache_info->debug != MagickFalse) &&
4686 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4687 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4688 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4689 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4690 nexus_info->region.x,(
double) nexus_info->region.y);
4722static MagickBooleanType ReadPixelCachePixels(
4723 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4724 ExceptionInfo *exception)
4744 if (nexus_info->authentic_pixel_cache != MagickFalse)
4746 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4747 return(MagickFalse);
4748 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4749 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4750 return(MagickFalse);
4751 offset+=nexus_info->region.x;
4752 number_channels=cache_info->number_channels;
4753 length=(MagickSizeType) number_channels*nexus_info->region.width*
4755 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4756 return(MagickFalse);
4757 rows=nexus_info->region.height;
4759 if ((extent == 0) || ((extent/length) != rows))
4760 return(MagickFalse);
4762 q=nexus_info->pixels;
4763 switch (cache_info->type)
4774 if ((cache_info->columns == nexus_info->region.width) &&
4775 (extent == (MagickSizeType) ((
size_t) extent)))
4780 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4782 for (y=0; y < (ssize_t) rows; y++)
4784 (void) memcpy(q,p,(
size_t) length);
4785 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4786 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4795 LockSemaphoreInfo(cache_info->file_semaphore);
4796 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4798 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4799 cache_info->cache_filename);
4800 UnlockSemaphoreInfo(cache_info->file_semaphore);
4801 return(MagickFalse);
4803 if ((cache_info->columns == nexus_info->region.width) &&
4804 (extent <= MagickMaxBufferExtent))
4809 for (y=0; y < (ssize_t) rows; y++)
4811 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4812 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4813 sizeof(*q),length,(
unsigned char *) q);
4814 if (count != (MagickOffsetType) length)
4816 offset+=(MagickOffsetType) cache_info->columns;
4817 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4819 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4820 (void) ClosePixelCacheOnDisk(cache_info);
4821 UnlockSemaphoreInfo(cache_info->file_semaphore);
4824 case DistributedCache:
4832 LockSemaphoreInfo(cache_info->file_semaphore);
4833 region=nexus_info->region;
4834 if ((cache_info->columns != nexus_info->region.width) ||
4835 (extent > MagickMaxBufferExtent))
4842 for (y=0; y < (ssize_t) rows; y++)
4844 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4845 cache_info->server_info,®ion,length,(
unsigned char *) q);
4846 if (count != (MagickOffsetType) length)
4848 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4851 UnlockSemaphoreInfo(cache_info->file_semaphore);
4857 if (y < (ssize_t) rows)
4859 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4860 cache_info->cache_filename);
4861 return(MagickFalse);
4863 if ((cache_info->debug != MagickFalse) &&
4864 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4865 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4866 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4867 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4868 nexus_info->region.x,(
double) nexus_info->region.y);
4895MagickPrivate Cache ReferencePixelCache(Cache cache)
4898 *magick_restrict cache_info;
4900 assert(cache != (Cache *) NULL);
4901 cache_info=(CacheInfo *) cache;
4902 assert(cache_info->signature == MagickCoreSignature);
4903 LockSemaphoreInfo(cache_info->semaphore);
4904 cache_info->reference_count++;
4905 UnlockSemaphoreInfo(cache_info->semaphore);
4931MagickPrivate
void ResetPixelCacheChannels(Image *image)
4934 *magick_restrict cache_info;
4936 assert(image != (
const Image *) NULL);
4937 assert(image->signature == MagickCoreSignature);
4938 assert(image->cache != (Cache) NULL);
4939 cache_info=(CacheInfo *) image->cache;
4940 assert(cache_info->signature == MagickCoreSignature);
4941 cache_info->number_channels=GetPixelChannels(image);
4962MagickPrivate
void ResetCacheAnonymousMemory(
void)
4964 cache_anonymous_memory=0;
4996MagickExport MagickBooleanType ReshapePixelCache(Image *image,
4997 const size_t columns,
const size_t rows,ExceptionInfo *exception)
5005 assert(image != (Image *) NULL);
5006 assert(image->signature == MagickCoreSignature);
5007 if (IsEventLogging() != MagickFalse)
5008 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5009 assert(image->cache != (
void *) NULL);
5010 extent=(MagickSizeType) columns*rows;
5011 if (extent > ((MagickSizeType) image->columns*image->rows))
5012 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5014 image->columns=columns;
5016 cache_info=(CacheInfo *) image->cache;
5017 cache_info->columns=columns;
5018 cache_info->rows=rows;
5019 return(SyncImagePixelCache(image,exception));
5046MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5049 *magick_restrict cache_info;
5051 GetOneAuthenticPixelFromHandler
5052 get_one_authentic_pixel_from_handler;
5054 GetOneVirtualPixelFromHandler
5055 get_one_virtual_pixel_from_handler;
5060 assert(cache != (Cache) NULL);
5061 assert(cache_methods != (CacheMethods *) NULL);
5062 cache_info=(CacheInfo *) cache;
5063 assert(cache_info->signature == MagickCoreSignature);
5064 if (IsEventLogging() != MagickFalse)
5065 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5066 cache_info->filename);
5067 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5068 cache_info->methods.get_virtual_pixel_handler=
5069 cache_methods->get_virtual_pixel_handler;
5070 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5071 cache_info->methods.destroy_pixel_handler=
5072 cache_methods->destroy_pixel_handler;
5073 if (cache_methods->get_virtual_metacontent_from_handler !=
5074 (GetVirtualMetacontentFromHandler) NULL)
5075 cache_info->methods.get_virtual_metacontent_from_handler=
5076 cache_methods->get_virtual_metacontent_from_handler;
5077 if (cache_methods->get_authentic_pixels_handler !=
5078 (GetAuthenticPixelsHandler) NULL)
5079 cache_info->methods.get_authentic_pixels_handler=
5080 cache_methods->get_authentic_pixels_handler;
5081 if (cache_methods->queue_authentic_pixels_handler !=
5082 (QueueAuthenticPixelsHandler) NULL)
5083 cache_info->methods.queue_authentic_pixels_handler=
5084 cache_methods->queue_authentic_pixels_handler;
5085 if (cache_methods->sync_authentic_pixels_handler !=
5086 (SyncAuthenticPixelsHandler) NULL)
5087 cache_info->methods.sync_authentic_pixels_handler=
5088 cache_methods->sync_authentic_pixels_handler;
5089 if (cache_methods->get_authentic_pixels_from_handler !=
5090 (GetAuthenticPixelsFromHandler) NULL)
5091 cache_info->methods.get_authentic_pixels_from_handler=
5092 cache_methods->get_authentic_pixels_from_handler;
5093 if (cache_methods->get_authentic_metacontent_from_handler !=
5094 (GetAuthenticMetacontentFromHandler) NULL)
5095 cache_info->methods.get_authentic_metacontent_from_handler=
5096 cache_methods->get_authentic_metacontent_from_handler;
5097 get_one_virtual_pixel_from_handler=
5098 cache_info->methods.get_one_virtual_pixel_from_handler;
5099 if (get_one_virtual_pixel_from_handler !=
5100 (GetOneVirtualPixelFromHandler) NULL)
5101 cache_info->methods.get_one_virtual_pixel_from_handler=
5102 cache_methods->get_one_virtual_pixel_from_handler;
5103 get_one_authentic_pixel_from_handler=
5104 cache_methods->get_one_authentic_pixel_from_handler;
5105 if (get_one_authentic_pixel_from_handler !=
5106 (GetOneAuthenticPixelFromHandler) NULL)
5107 cache_info->methods.get_one_authentic_pixel_from_handler=
5108 cache_methods->get_one_authentic_pixel_from_handler;
5149static inline MagickBooleanType AcquireCacheNexusPixels(
5150 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5151 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5153 if (length != (MagickSizeType) ((
size_t) length))
5155 (void) ThrowMagickException(exception,GetMagickModule(),
5156 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5157 cache_info->filename);
5158 return(MagickFalse);
5160 nexus_info->length=0;
5161 nexus_info->mapped=MagickFalse;
5162 if (cache_anonymous_memory <= 0)
5164 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5166 if (nexus_info->cache != (Quantum *) NULL)
5167 (void) memset(nexus_info->cache,0,(
size_t) length);
5171 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5172 if (nexus_info->cache != (Quantum *) NULL)
5173 nexus_info->mapped=MagickTrue;
5175 if (nexus_info->cache == (Quantum *) NULL)
5177 (void) ThrowMagickException(exception,GetMagickModule(),
5178 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5179 cache_info->filename);
5180 return(MagickFalse);
5182 nexus_info->length=length;
5186static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5189 if (nexus_info->length < CACHE_LINE_SIZE)
5191 if (mode == ReadMode)
5193 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5197 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5200static Quantum *SetPixelCacheNexusPixels(
5201 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5202 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5203 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5204 ExceptionInfo *exception)
5213 assert(cache_info != (
const CacheInfo *) NULL);
5214 assert(cache_info->signature == MagickCoreSignature);
5215 if (cache_info->type == UndefinedCache)
5216 return((Quantum *) NULL);
5217 assert(nexus_info->signature == MagickCoreSignature);
5218 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5219 if ((width == 0) || (height == 0))
5221 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5222 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5223 return((Quantum *) NULL);
5225 if (((MagickSizeType) width > cache_info->width_limit) ||
5226 ((MagickSizeType) height > cache_info->height_limit))
5228 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5229 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5230 return((Quantum *) NULL);
5232 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5233 (IsValidPixelOffset(y,height) == MagickFalse))
5235 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5236 "InvalidPixel",
"`%s'",cache_info->filename);
5237 return((Quantum *) NULL);
5239 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5240 (buffered == MagickFalse))
5242 if (((x >= 0) && (y >= 0) &&
5243 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5244 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5245 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5253 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5254 return((Quantum *) NULL);
5255 offset=y*(MagickOffsetType) cache_info->columns+x;
5256 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5257 cache_info->number_channels*offset;
5258 nexus_info->metacontent=(
void *) NULL;
5259 if (cache_info->metacontent_extent != 0)
5260 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5261 offset*(MagickOffsetType) cache_info->metacontent_extent;
5262 nexus_info->region.width=width;
5263 nexus_info->region.height=height;
5264 nexus_info->region.x=x;
5265 nexus_info->region.y=y;
5266 nexus_info->authentic_pixel_cache=MagickTrue;
5267 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5268 return(nexus_info->pixels);
5274 number_pixels=(MagickSizeType) width*height;
5275 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5276 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5277 if (cache_info->metacontent_extent != 0)
5278 length+=number_pixels*cache_info->metacontent_extent;
5280 if (nexus_info->cache == (Quantum *) NULL)
5281 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5283 if (nexus_info->length < length)
5285 RelinquishCacheNexusPixels(nexus_info);
5286 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5288 if (status == MagickFalse)
5289 return((Quantum *) NULL);
5290 nexus_info->pixels=nexus_info->cache;
5291 nexus_info->metacontent=(
void *) NULL;
5292 if (cache_info->metacontent_extent != 0)
5293 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5294 cache_info->number_channels*number_pixels);
5295 nexus_info->region.width=width;
5296 nexus_info->region.height=height;
5297 nexus_info->region.x=x;
5298 nexus_info->region.y=y;
5299 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5300 MagickTrue : MagickFalse;
5301 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5302 return(nexus_info->pixels);
5335static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5336 ExceptionInfo *exception)
5339 *magick_restrict image_view;
5347 assert(image != (Image *) NULL);
5348 assert(image->signature == MagickCoreSignature);
5349 if (IsEventLogging() != MagickFalse)
5350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5351 assert(image->cache != (Cache) NULL);
5352 image->alpha_trait=BlendPixelTrait;
5354 image_view=AcquireVirtualCacheView(image,exception);
5355#if defined(MAGICKCORE_OPENMP_SUPPORT)
5356 #pragma omp parallel for schedule(static) shared(status) \
5357 magick_number_threads(image,image,image->rows,2)
5359 for (y=0; y < (ssize_t) image->rows; y++)
5367 if (status == MagickFalse)
5369 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5370 if (q == (Quantum *) NULL)
5375 for (x=0; x < (ssize_t) image->columns; x++)
5377 SetPixelAlpha(image,alpha,q);
5378 q+=(ptrdiff_t) GetPixelChannels(image);
5380 status=SyncCacheViewAuthenticPixels(image_view,exception);
5382 image_view=DestroyCacheView(image_view);
5386MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5387 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5390 *magick_restrict cache_info;
5395 assert(image != (Image *) NULL);
5396 assert(image->signature == MagickCoreSignature);
5397 if (IsEventLogging() != MagickFalse)
5398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5399 assert(image->cache != (Cache) NULL);
5400 cache_info=(CacheInfo *) image->cache;
5401 assert(cache_info->signature == MagickCoreSignature);
5402 method=cache_info->virtual_pixel_method;
5403 cache_info->virtual_pixel_method=virtual_pixel_method;
5404 if ((image->columns != 0) && (image->rows != 0))
5405 switch (virtual_pixel_method)
5407 case BackgroundVirtualPixelMethod:
5409 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5410 ((image->alpha_trait & BlendPixelTrait) == 0))
5411 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5412 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5413 (IsGrayColorspace(image->colorspace) != MagickFalse))
5414 (void) SetImageColorspace(image,sRGBColorspace,exception);
5417 case TransparentVirtualPixelMethod:
5419 if ((image->alpha_trait & BlendPixelTrait) == 0)
5420 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5429#if defined(MAGICKCORE_OPENCL_SUPPORT)
5454static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5456 assert(cache_info != (CacheInfo *) NULL);
5457 assert(cache_info->signature == MagickCoreSignature);
5458 if ((cache_info->type != MemoryCache) ||
5459 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5464 LockSemaphoreInfo(cache_info->semaphore);
5465 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5466 UnlockSemaphoreInfo(cache_info->semaphore);
5469MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5472 *magick_restrict cache_info;
5474 assert(image != (
const Image *) NULL);
5475 cache_info=(CacheInfo *) image->cache;
5476 CopyOpenCLBuffer(cache_info);
5509MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5510 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5513 *magick_restrict cache_info;
5521 assert(image != (Image *) NULL);
5522 assert(image->signature == MagickCoreSignature);
5523 if (image->cache == (Cache) NULL)
5524 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5525 cache_info=(CacheInfo *) image->cache;
5526 assert(cache_info->signature == MagickCoreSignature);
5527 if (cache_info->type == UndefinedCache)
5528 return(MagickFalse);
5529 if ((image->mask_trait & UpdatePixelTrait) != 0)
5531 if (((image->channels & WriteMaskChannel) != 0) &&
5532 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5533 return(MagickFalse);
5534 if (((image->channels & CompositeMaskChannel) != 0) &&
5535 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5536 return(MagickFalse);
5538 if (nexus_info->authentic_pixel_cache != MagickFalse)
5540 if (image->taint == MagickFalse)
5541 image->taint=MagickTrue;
5544 assert(cache_info->signature == MagickCoreSignature);
5545 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5546 if ((cache_info->metacontent_extent != 0) &&
5547 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5548 return(MagickFalse);
5549 if ((status != MagickFalse) && (image->taint == MagickFalse))
5550 image->taint=MagickTrue;
5581static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5582 ExceptionInfo *exception)
5585 *magick_restrict cache_info;
5588 id = GetOpenMPThreadId();
5593 assert(image != (Image *) NULL);
5594 assert(image->signature == MagickCoreSignature);
5595 assert(image->cache != (Cache) NULL);
5596 cache_info=(CacheInfo *) image->cache;
5597 assert(cache_info->signature == MagickCoreSignature);
5598 assert(
id < (
int) cache_info->number_threads);
5599 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5631MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5632 ExceptionInfo *exception)
5635 *magick_restrict cache_info;
5638 id = GetOpenMPThreadId();
5643 assert(image != (Image *) NULL);
5644 assert(image->signature == MagickCoreSignature);
5645 assert(image->cache != (Cache) NULL);
5646 cache_info=(CacheInfo *) image->cache;
5647 assert(cache_info->signature == MagickCoreSignature);
5648 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5650 status=cache_info->methods.sync_authentic_pixels_handler(image,
5654 assert(
id < (
int) cache_info->number_threads);
5655 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5687MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5688 ExceptionInfo *exception)
5691 *magick_restrict cache_info;
5693 assert(image != (Image *) NULL);
5694 assert(exception != (ExceptionInfo *) NULL);
5695 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5696 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5727static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5728 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5747 if (cache_info->metacontent_extent == 0)
5748 return(MagickFalse);
5749 if (nexus_info->authentic_pixel_cache != MagickFalse)
5751 if (nexus_info->metacontent == (
unsigned char *) NULL)
5752 return(MagickFalse);
5753 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5754 return(MagickFalse);
5755 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5756 nexus_info->region.x;
5757 length=(MagickSizeType) nexus_info->region.width*
5758 cache_info->metacontent_extent;
5759 extent=(MagickSizeType) length*nexus_info->region.height;
5760 rows=nexus_info->region.height;
5762 p=(
unsigned char *) nexus_info->metacontent;
5763 switch (cache_info->type)
5774 if ((cache_info->columns == nexus_info->region.width) &&
5775 (extent == (MagickSizeType) ((
size_t) extent)))
5780 q=(
unsigned char *) cache_info->metacontent+offset*
5781 (MagickOffsetType) cache_info->metacontent_extent;
5782 for (y=0; y < (ssize_t) rows; y++)
5784 (void) memcpy(q,p,(
size_t) length);
5785 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5786 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5795 LockSemaphoreInfo(cache_info->file_semaphore);
5796 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5798 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5799 cache_info->cache_filename);
5800 UnlockSemaphoreInfo(cache_info->file_semaphore);
5801 return(MagickFalse);
5803 if ((cache_info->columns == nexus_info->region.width) &&
5804 (extent <= MagickMaxBufferExtent))
5809 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5810 for (y=0; y < (ssize_t) rows; y++)
5812 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5813 (MagickOffsetType) extent*(MagickOffsetType)
5814 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5815 (MagickOffsetType) cache_info->metacontent_extent,length,
5816 (
const unsigned char *) p);
5817 if (count != (MagickOffsetType) length)
5819 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5820 offset+=(MagickOffsetType) cache_info->columns;
5822 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5823 (void) ClosePixelCacheOnDisk(cache_info);
5824 UnlockSemaphoreInfo(cache_info->file_semaphore);
5827 case DistributedCache:
5835 LockSemaphoreInfo(cache_info->file_semaphore);
5836 region=nexus_info->region;
5837 if ((cache_info->columns != nexus_info->region.width) ||
5838 (extent > MagickMaxBufferExtent))
5845 for (y=0; y < (ssize_t) rows; y++)
5847 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5848 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5849 if (count != (MagickOffsetType) length)
5851 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5854 UnlockSemaphoreInfo(cache_info->file_semaphore);
5860 if (y < (ssize_t) rows)
5862 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5863 cache_info->cache_filename);
5864 return(MagickFalse);
5866 if ((cache_info->debug != MagickFalse) &&
5867 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5868 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5869 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5870 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5871 nexus_info->region.x,(
double) nexus_info->region.y);
5903static MagickBooleanType WritePixelCachePixels(
5904 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5905 ExceptionInfo *exception)
5924 if (nexus_info->authentic_pixel_cache != MagickFalse)
5926 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5927 return(MagickFalse);
5928 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5929 nexus_info->region.x;
5930 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5932 extent=length*nexus_info->region.height;
5933 rows=nexus_info->region.height;
5935 p=nexus_info->pixels;
5936 switch (cache_info->type)
5947 if ((cache_info->columns == nexus_info->region.width) &&
5948 (extent == (MagickSizeType) ((
size_t) extent)))
5953 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5955 for (y=0; y < (ssize_t) rows; y++)
5957 (void) memcpy(q,p,(
size_t) length);
5958 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5959 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5968 LockSemaphoreInfo(cache_info->file_semaphore);
5969 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5971 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5972 cache_info->cache_filename);
5973 UnlockSemaphoreInfo(cache_info->file_semaphore);
5974 return(MagickFalse);
5976 if ((cache_info->columns == nexus_info->region.width) &&
5977 (extent <= MagickMaxBufferExtent))
5982 for (y=0; y < (ssize_t) rows; y++)
5984 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5985 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5986 sizeof(*p),length,(
const unsigned char *) p);
5987 if (count != (MagickOffsetType) length)
5989 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5990 offset+=(MagickOffsetType) cache_info->columns;
5992 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5993 (void) ClosePixelCacheOnDisk(cache_info);
5994 UnlockSemaphoreInfo(cache_info->file_semaphore);
5997 case DistributedCache:
6005 LockSemaphoreInfo(cache_info->file_semaphore);
6006 region=nexus_info->region;
6007 if ((cache_info->columns != nexus_info->region.width) ||
6008 (extent > MagickMaxBufferExtent))
6015 for (y=0; y < (ssize_t) rows; y++)
6017 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6018 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6019 if (count != (MagickOffsetType) length)
6021 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6024 UnlockSemaphoreInfo(cache_info->file_semaphore);
6030 if (y < (ssize_t) rows)
6032 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6033 cache_info->cache_filename);
6034 return(MagickFalse);
6036 if ((cache_info->debug != MagickFalse) &&
6037 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6038 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6039 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6040 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6041 nexus_info->region.x,(
double) nexus_info->region.y);