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_alpha=QuantumScale*(double) GetPixelWriteMask(image,p);
460 if (fabs(mask_alpha) >= MagickEpsilon)
462 for (i=0; i < (ssize_t) image->number_channels; i++)
464 PixelChannel channel = GetPixelChannelChannel(image,i);
465 PixelTrait traits = GetPixelChannelTraits(image,channel);
466 if ((traits & UpdatePixelTrait) == 0)
468 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha*(
double)
469 GetPixelAlpha(image,p),(
double) q[i],(
double)
470 GetPixelAlpha(image,q)));
472 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
474 p+=(ptrdiff_t) GetPixelChannels(image);
475 q+=(ptrdiff_t) GetPixelChannels(image);
503MagickPrivate Cache ClonePixelCache(
const Cache cache)
506 *magick_restrict clone_info;
509 *magick_restrict cache_info;
511 assert(cache != NULL);
512 cache_info=(
const CacheInfo *) cache;
513 assert(cache_info->signature == MagickCoreSignature);
514 if (IsEventLogging() != MagickFalse)
515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
516 cache_info->filename);
517 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
518 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
519 return((Cache ) clone_info);
547MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
550 *magick_restrict cache_info,
551 *magick_restrict source_info;
553 assert(clone != (Cache) NULL);
554 source_info=(CacheInfo *) clone;
555 assert(source_info->signature == MagickCoreSignature);
556 if (IsEventLogging() != MagickFalse)
557 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
558 source_info->filename);
559 assert(cache != (Cache) NULL);
560 cache_info=(CacheInfo *) cache;
561 assert(cache_info->signature == MagickCoreSignature);
562 source_info->methods=cache_info->methods;
594static MagickBooleanType ClonePixelCacheOnDisk(
595 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
615 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
616 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
618 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
619 (lseek(clone_info->file,0,SEEK_SET) < 0))
621 quantum=(size_t) MagickMaxBufferExtent;
622 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
624#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
625 if (cache_info->length < 0x7ffff000)
627 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
628 (
size_t) cache_info->length);
629 if (count == (ssize_t) cache_info->length)
631 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
632 (lseek(clone_info->file,0,SEEK_SET) < 0))
636 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
638 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
639 if (buffer == (
unsigned char *) NULL)
640 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
642 while ((count=read(cache_info->file,buffer,quantum)) > 0)
647 number_bytes=write(clone_info->file,buffer,(
size_t) count);
648 if (number_bytes != count)
650 extent+=(size_t) number_bytes;
652 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
653 if (extent != cache_info->length)
658#if defined(MAGICKCORE_OPENMP_SUPPORT)
659static inline int GetCacheNumberThreads(
const CacheInfo *source,
660 const CacheInfo *destination,
const size_t chunk,
const int factor)
663 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
664 number_threads = 1UL,
665 workload_factor = 64UL << factor;
670 number_threads=(chunk <= workload_factor) ? 1UL :
671 (chunk >= (workload_factor << 6)) ? max_threads :
672 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
676 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
677 ((destination->type != MemoryCache) && (destination->type != MapCache)))
678 number_threads=MagickMin(number_threads,4);
679 return((
int) number_threads);
683static MagickBooleanType ClonePixelCacheRepository(
684 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
685 ExceptionInfo *exception)
687#define cache_number_threads(source,destination,chunk,factor) \
688 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
695 **magick_restrict cache_nexus,
696 **magick_restrict clone_nexus;
704 assert(cache_info != (CacheInfo *) NULL);
705 assert(clone_info != (CacheInfo *) NULL);
706 assert(exception != (ExceptionInfo *) NULL);
707 if (cache_info->type == PingCache)
709 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
710 if ((cache_info->storage_class == clone_info->storage_class) &&
711 (cache_info->colorspace == clone_info->colorspace) &&
712 (cache_info->alpha_trait == clone_info->alpha_trait) &&
713 (cache_info->channels == clone_info->channels) &&
714 (cache_info->columns == clone_info->columns) &&
715 (cache_info->rows == clone_info->rows) &&
716 (cache_info->number_channels == clone_info->number_channels) &&
717 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
718 (cache_info->metacontent_extent == clone_info->metacontent_extent))
723 if (((cache_info->type == MemoryCache) ||
724 (cache_info->type == MapCache)) &&
725 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
727 (void) memcpy(clone_info->pixels,cache_info->pixels,
728 cache_info->number_channels*cache_info->columns*cache_info->rows*
729 sizeof(*cache_info->pixels));
730 if ((cache_info->metacontent_extent != 0) &&
731 (clone_info->metacontent_extent != 0))
732 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
733 cache_info->columns*cache_info->rows*
734 clone_info->metacontent_extent*
sizeof(
unsigned char));
737 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
738 return(ClonePixelCacheOnDisk(cache_info,clone_info));
743 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
744 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
745 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
746 optimize=(cache_info->number_channels == clone_info->number_channels) &&
747 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
748 MagickTrue : MagickFalse;
749 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
750 clone_info->number_channels*clone_info->columns);
752#if defined(MAGICKCORE_OPENMP_SUPPORT)
753 #pragma omp parallel for schedule(static) shared(status) \
754 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
756 for (y=0; y < (ssize_t) cache_info->rows; y++)
759 id = GetOpenMPThreadId();
767 if (status == MagickFalse)
769 if (y >= (ssize_t) clone_info->rows)
771 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
772 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
773 if (pixels == (Quantum *) NULL)
775 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
776 if (status == MagickFalse)
778 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
779 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
780 if (pixels == (Quantum *) NULL)
782 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
783 if (optimize != MagickFalse)
784 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
797 p=cache_nexus[id]->pixels;
798 q=clone_nexus[id]->pixels;
799 for (x=0; x < (ssize_t) cache_info->columns; x++)
804 if (x == (ssize_t) clone_info->columns)
806 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
814 channel=clone_info->channel_map[i].channel;
815 traits=cache_info->channel_map[channel].traits;
816 if (traits != UndefinedPixelTrait)
817 *q=*(p+cache_info->channel_map[channel].offset);
820 p+=(ptrdiff_t) cache_info->number_channels;
823 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
825 if ((cache_info->metacontent_extent != 0) &&
826 (clone_info->metacontent_extent != 0))
831 length=(size_t) MagickMin(cache_info->metacontent_extent,
832 clone_info->metacontent_extent);
833#if defined(MAGICKCORE_OPENMP_SUPPORT)
834 #pragma omp parallel for schedule(static) shared(status) \
835 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
837 for (y=0; y < (ssize_t) cache_info->rows; y++)
840 id = GetOpenMPThreadId();
845 if (status == MagickFalse)
847 if (y >= (ssize_t) clone_info->rows)
849 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
850 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
851 if (pixels == (Quantum *) NULL)
853 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
854 if (status == MagickFalse)
856 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
857 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
858 if (pixels == (Quantum *) NULL)
860 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
861 (cache_nexus[
id]->metacontent != (
void *) NULL))
862 (void) memcpy(clone_nexus[
id]->metacontent,
863 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
864 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
867 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
868 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
869 if (cache_info->debug != MagickFalse)
872 message[MagickPathExtent];
874 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
875 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
876 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
877 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
904static void DestroyImagePixelCache(Image *image)
906 assert(image != (Image *) NULL);
907 assert(image->signature == MagickCoreSignature);
908 if (IsEventLogging() != MagickFalse)
909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
910 if (image->cache != (
void *) NULL)
911 image->cache=DestroyPixelCache(image->cache);
936MagickExport
void DestroyImagePixels(Image *image)
939 *magick_restrict cache_info;
941 assert(image != (
const Image *) NULL);
942 assert(image->signature == MagickCoreSignature);
943 if (IsEventLogging() != MagickFalse)
944 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
945 assert(image->cache != (Cache) NULL);
946 cache_info=(CacheInfo *) image->cache;
947 assert(cache_info->signature == MagickCoreSignature);
948 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
950 cache_info->methods.destroy_pixel_handler(image);
953 image->cache=DestroyPixelCache(image->cache);
979static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
985 if (cache_info->file != -1)
987 status=close_utf8(cache_info->file);
988 cache_info->file=(-1);
989 RelinquishMagickResource(FileResource,1);
991 return(status == -1 ? MagickFalse : MagickTrue);
994static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
996 switch (cache_info->type)
1000 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1001#if defined(MAGICKCORE_OPENCL_SUPPORT)
1002 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1004 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1006 cache_info->pixels=(Quantum *) NULL;
1010 if (cache_info->mapped == MagickFalse)
1011 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1012 cache_info->pixels);
1015 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1016 cache_info->pixels=(Quantum *) NULL;
1018 RelinquishMagickResource(MemoryResource,cache_info->length);
1023 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1024 cache_info->pixels=(Quantum *) NULL;
1025 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1026 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1027 *cache_info->cache_filename=
'\0';
1028 RelinquishMagickResource(MapResource,cache_info->length);
1033 if (cache_info->file != -1)
1034 (void) ClosePixelCacheOnDisk(cache_info);
1035 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1036 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1037 *cache_info->cache_filename=
'\0';
1038 RelinquishMagickResource(DiskResource,cache_info->length);
1041 case DistributedCache:
1043 *cache_info->cache_filename=
'\0';
1044 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1045 cache_info->server_info);
1051 cache_info->type=UndefinedCache;
1052 cache_info->mapped=MagickFalse;
1053 cache_info->metacontent=(
void *) NULL;
1056MagickPrivate Cache DestroyPixelCache(Cache cache)
1059 *magick_restrict cache_info;
1061 assert(cache != (Cache) NULL);
1062 cache_info=(CacheInfo *) cache;
1063 assert(cache_info->signature == MagickCoreSignature);
1064 if (IsEventLogging() != MagickFalse)
1065 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1066 cache_info->filename);
1067 LockSemaphoreInfo(cache_info->semaphore);
1068 cache_info->reference_count--;
1069 if (cache_info->reference_count != 0)
1071 UnlockSemaphoreInfo(cache_info->semaphore);
1072 return((Cache) NULL);
1074 UnlockSemaphoreInfo(cache_info->semaphore);
1075 if (cache_info->debug != MagickFalse)
1078 message[MagickPathExtent];
1080 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1081 cache_info->filename);
1082 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1084 RelinquishPixelCachePixels(cache_info);
1085 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1086 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1087 cache_info->server_info);
1088 if (cache_info->nexus_info != (NexusInfo **) NULL)
1089 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1090 cache_info->number_threads);
1091 if (cache_info->random_info != (RandomInfo *) NULL)
1092 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1094 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1096 RelinquishSemaphoreInfo(&cache_info->semaphore);
1097 cache_info->signature=(~MagickCoreSignature);
1098 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1129static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1131 if (nexus_info->mapped == MagickFalse)
1132 (void) RelinquishAlignedMemory(nexus_info->cache);
1134 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1135 nexus_info->cache=(Quantum *) NULL;
1136 nexus_info->pixels=(Quantum *) NULL;
1137 nexus_info->metacontent=(
void *) NULL;
1138 nexus_info->length=0;
1139 nexus_info->mapped=MagickFalse;
1142MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1143 const size_t number_threads)
1148 assert(nexus_info != (NexusInfo **) NULL);
1149 for (i=0; i < (ssize_t) (2*number_threads); i++)
1151 if (nexus_info[i]->cache != (Quantum *) NULL)
1152 RelinquishCacheNexusPixels(nexus_info[i]);
1153 nexus_info[i]->signature=(~MagickCoreSignature);
1155 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1156 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1185MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1188 *magick_restrict cache_info;
1191 id = GetOpenMPThreadId();
1193 assert(image != (
const Image *) NULL);
1194 assert(image->signature == MagickCoreSignature);
1195 assert(image->cache != (Cache) NULL);
1196 cache_info=(CacheInfo *) image->cache;
1197 assert(cache_info->signature == MagickCoreSignature);
1198 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1199 (GetAuthenticMetacontentFromHandler) NULL)
1204 metacontent=cache_info->methods.
1205 get_authentic_metacontent_from_handler(image);
1206 return(metacontent);
1208 assert(
id < (
int) cache_info->number_threads);
1209 return(cache_info->nexus_info[
id]->metacontent);
1236static void *GetAuthenticMetacontentFromCache(
const Image *image)
1239 *magick_restrict cache_info;
1242 id = GetOpenMPThreadId();
1244 assert(image != (
const Image *) NULL);
1245 assert(image->signature == MagickCoreSignature);
1246 assert(image->cache != (Cache) NULL);
1247 cache_info=(CacheInfo *) image->cache;
1248 assert(cache_info->signature == MagickCoreSignature);
1249 assert(
id < (
int) cache_info->number_threads);
1250 return(cache_info->nexus_info[
id]->metacontent);
1253#if defined(MAGICKCORE_OPENCL_SUPPORT)
1282MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1283 MagickCLDevice device,ExceptionInfo *exception)
1286 *magick_restrict cache_info;
1288 assert(image != (
const Image *) NULL);
1289 assert(device != (
const MagickCLDevice) NULL);
1290 cache_info=(CacheInfo *) image->cache;
1291 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1293 SyncImagePixelCache((Image *) image,exception);
1294 cache_info=(CacheInfo *) image->cache;
1296 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1297 return((cl_mem) NULL);
1298 LockSemaphoreInfo(cache_info->semaphore);
1299 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1300 (cache_info->opencl->device->context != device->context))
1301 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1302 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1304 assert(cache_info->pixels != (Quantum *) NULL);
1305 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1306 cache_info->length);
1308 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1309 RetainOpenCLMemObject(cache_info->opencl->buffer);
1310 UnlockSemaphoreInfo(cache_info->semaphore);
1311 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1312 return((cl_mem) NULL);
1313 assert(cache_info->opencl->pixels == cache_info->pixels);
1314 return(cache_info->opencl->buffer);
1353MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
const ssize_t x,
1354 const ssize_t y,
const size_t columns,
const size_t rows,NexusInfo *nexus_info,
1355 ExceptionInfo *exception)
1358 *magick_restrict cache_info;
1361 *magick_restrict pixels;
1366 assert(image != (Image *) NULL);
1367 assert(image->signature == MagickCoreSignature);
1368 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1369 nexus_info,exception);
1370 if (pixels == (Quantum *) NULL)
1371 return((Quantum *) NULL);
1372 cache_info=(CacheInfo *) image->cache;
1373 assert(cache_info->signature == MagickCoreSignature);
1374 if (nexus_info->authentic_pixel_cache != MagickFalse)
1376 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1377 return((Quantum *) NULL);
1378 if (cache_info->metacontent_extent != 0)
1379 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1380 return((Quantum *) NULL);
1407static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1410 *magick_restrict cache_info;
1413 id = GetOpenMPThreadId();
1415 assert(image != (
const Image *) NULL);
1416 assert(image->signature == MagickCoreSignature);
1417 assert(image->cache != (Cache) NULL);
1418 cache_info=(CacheInfo *) image->cache;
1419 assert(cache_info->signature == MagickCoreSignature);
1420 assert(
id < (
int) cache_info->number_threads);
1421 return(cache_info->nexus_info[
id]->pixels);
1448MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1451 *magick_restrict cache_info;
1454 id = GetOpenMPThreadId();
1456 assert(image != (
const Image *) NULL);
1457 assert(image->signature == MagickCoreSignature);
1458 assert(image->cache != (Cache) NULL);
1459 cache_info=(CacheInfo *) image->cache;
1460 assert(cache_info->signature == MagickCoreSignature);
1461 if (cache_info->methods.get_authentic_pixels_from_handler !=
1462 (GetAuthenticPixelsFromHandler) NULL)
1463 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1464 assert(
id < (
int) cache_info->number_threads);
1465 return(cache_info->nexus_info[
id]->pixels);
1513MagickExport Quantum *GetAuthenticPixels(Image *image,
const ssize_t x,
1514 const ssize_t y,
const size_t columns,
const size_t rows,
1515 ExceptionInfo *exception)
1518 *magick_restrict cache_info;
1521 id = GetOpenMPThreadId();
1526 assert(image != (Image *) NULL);
1527 assert(image->signature == MagickCoreSignature);
1528 assert(image->cache != (Cache) NULL);
1529 cache_info=(CacheInfo *) image->cache;
1530 assert(cache_info->signature == MagickCoreSignature);
1531 if (cache_info->methods.get_authentic_pixels_handler !=
1532 (GetAuthenticPixelsHandler) NULL)
1534 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1538 assert(
id < (
int) cache_info->number_threads);
1539 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1540 cache_info->nexus_info[
id],exception);
1575static Quantum *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1576 const ssize_t y,
const size_t columns,
const size_t rows,
1577 ExceptionInfo *exception)
1580 *magick_restrict cache_info;
1583 id = GetOpenMPThreadId();
1586 *magick_restrict pixels;
1588 assert(image != (
const Image *) NULL);
1589 assert(image->signature == MagickCoreSignature);
1590 assert(image->cache != (Cache) NULL);
1591 cache_info=(CacheInfo *) image->cache;
1592 if (cache_info == (Cache) NULL)
1593 return((Quantum *) NULL);
1594 assert(cache_info->signature == MagickCoreSignature);
1595 assert(
id < (
int) cache_info->number_threads);
1596 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1597 cache_info->nexus_info[
id],exception);
1624MagickExport MagickSizeType GetImageExtent(
const Image *image)
1627 *magick_restrict cache_info;
1630 id = GetOpenMPThreadId();
1632 assert(image != (Image *) NULL);
1633 assert(image->signature == MagickCoreSignature);
1634 if (IsEventLogging() != MagickFalse)
1635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1636 assert(image->cache != (Cache) NULL);
1637 cache_info=(CacheInfo *) image->cache;
1638 assert(cache_info->signature == MagickCoreSignature);
1639 assert(
id < (
int) cache_info->number_threads);
1640 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1673static MagickBooleanType GetDynamicThrottlePolicy(
void)
1675 static MagickBooleanType
1676 check_policy = MagickTrue;
1678 static MagickBooleanType
1679 dynamic_throttle = MagickFalse;
1681 if (check_policy != MagickFalse)
1683 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1684 if (value != (
char *) NULL)
1686 dynamic_throttle=IsStringTrue(value);
1687 value=DestroyString(value);
1689 check_policy=MagickFalse;
1691 return(dynamic_throttle);
1694static inline MagickBooleanType ValidatePixelCacheMorphology(
1695 const Image *magick_restrict image)
1698 *magick_restrict cache_info;
1700 const PixelChannelMap
1707 cache_info=(CacheInfo *) image->cache;
1708 p=image->channel_map;
1709 q=cache_info->channel_map;
1710 if ((image->storage_class != cache_info->storage_class) ||
1711 (image->colorspace != cache_info->colorspace) ||
1712 (image->alpha_trait != cache_info->alpha_trait) ||
1713 (image->channels != cache_info->channels) ||
1714 (image->columns != cache_info->columns) ||
1715 (image->rows != cache_info->rows) ||
1716 (image->number_channels != cache_info->number_channels) ||
1717 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1718 (image->metacontent_extent != cache_info->metacontent_extent) ||
1719 (cache_info->nexus_info == (NexusInfo **) NULL))
1720 return(MagickFalse);
1724static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1725 ExceptionInfo *exception)
1728 *magick_restrict cache_info;
1732 status = MagickTrue;
1734 static MagickSizeType
1735 cpu_throttle = MagickResourceInfinity,
1738 if (IsImageTTLExpired(image) != MagickFalse)
1743 (void) ThrowMagickException(exception,GetMagickModule(),
1744 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1745 return((Cache) NULL);
1747 if (cpu_throttle == MagickResourceInfinity)
1748 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1749 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1762#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1763 if (getloadavg(&load_average,1) != 1)
1766 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1767 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1769 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1770 MagickDelay(cpu_throttle);
1772 LockSemaphoreInfo(image->semaphore);
1773 assert(image->cache != (Cache) NULL);
1774 cache_info=(CacheInfo *) image->cache;
1775#if defined(MAGICKCORE_OPENCL_SUPPORT)
1776 CopyOpenCLBuffer(cache_info);
1778 destroy=MagickFalse;
1779 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1781 LockSemaphoreInfo(cache_info->semaphore);
1782 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1793 clone_image=(*image);
1794 clone_image.semaphore=AcquireSemaphoreInfo();
1795 clone_image.reference_count=1;
1796 clone_image.cache=ClonePixelCache(cache_info);
1797 clone_info=(CacheInfo *) clone_image.cache;
1798 status=OpenPixelCache(&clone_image,IOMode,exception);
1799 if (status == MagickFalse)
1800 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1803 if (clone != MagickFalse)
1804 status=ClonePixelCacheRepository(clone_info,cache_info,
1806 if (status == MagickFalse)
1807 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1811 image->cache=clone_info;
1814 RelinquishSemaphoreInfo(&clone_image.semaphore);
1816 UnlockSemaphoreInfo(cache_info->semaphore);
1818 if (destroy != MagickFalse)
1819 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1820 if (status != MagickFalse)
1825 if (image->type != UndefinedType)
1826 image->type=UndefinedType;
1827 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1829 status=OpenPixelCache(image,IOMode,exception);
1830 cache_info=(CacheInfo *) image->cache;
1831 if (cache_info->file != -1)
1832 (void) ClosePixelCacheOnDisk(cache_info);
1835 UnlockSemaphoreInfo(image->semaphore);
1836 if (status == MagickFalse)
1837 return((Cache) NULL);
1838 return(image->cache);
1864MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1867 *magick_restrict cache_info;
1869 assert(image != (Image *) NULL);
1870 assert(image->signature == MagickCoreSignature);
1871 assert(image->cache != (Cache) NULL);
1872 cache_info=(CacheInfo *) image->cache;
1873 assert(cache_info->signature == MagickCoreSignature);
1874 return(cache_info->type);
1908static inline MagickBooleanType CopyPixel(
const Image *image,
1909 const Quantum *source,Quantum *destination)
1914 if (source == (
const Quantum *) NULL)
1916 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1917 destination[GreenPixelChannel]=ClampToQuantum(
1918 image->background_color.green);
1919 destination[BluePixelChannel]=ClampToQuantum(
1920 image->background_color.blue);
1921 destination[BlackPixelChannel]=ClampToQuantum(
1922 image->background_color.black);
1923 destination[AlphaPixelChannel]=ClampToQuantum(
1924 image->background_color.alpha);
1925 return(MagickFalse);
1927 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1929 PixelChannel channel = GetPixelChannelChannel(image,i);
1930 destination[channel]=source[i];
1935MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1936 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1939 *magick_restrict cache_info;
1944 assert(image != (Image *) NULL);
1945 assert(image->signature == MagickCoreSignature);
1946 assert(image->cache != (Cache) NULL);
1947 cache_info=(CacheInfo *) image->cache;
1948 assert(cache_info->signature == MagickCoreSignature);
1949 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1950 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1951 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1952 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1953 return(CopyPixel(image,q,pixel));
1987static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
1988 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1991 *magick_restrict cache_info;
1994 id = GetOpenMPThreadId();
1999 assert(image != (
const Image *) NULL);
2000 assert(image->signature == MagickCoreSignature);
2001 assert(image->cache != (Cache) NULL);
2002 cache_info=(CacheInfo *) image->cache;
2003 assert(cache_info->signature == MagickCoreSignature);
2004 assert(
id < (
int) cache_info->number_threads);
2005 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2006 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2008 return(CopyPixel(image,q,pixel));
2042MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2043 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2046 *magick_restrict cache_info;
2049 id = GetOpenMPThreadId();
2054 assert(image != (
const Image *) NULL);
2055 assert(image->signature == MagickCoreSignature);
2056 assert(image->cache != (Cache) NULL);
2057 cache_info=(CacheInfo *) image->cache;
2058 assert(cache_info->signature == MagickCoreSignature);
2059 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2060 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2061 (GetOneVirtualPixelFromHandler) NULL)
2062 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2063 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2064 assert(
id < (
int) cache_info->number_threads);
2065 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2066 1UL,1UL,cache_info->nexus_info[
id],exception);
2067 return(CopyPixel(image,p,pixel));
2104static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2105 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2106 Quantum *pixel,ExceptionInfo *exception)
2109 *magick_restrict cache_info;
2112 id = GetOpenMPThreadId();
2117 assert(image != (
const Image *) NULL);
2118 assert(image->signature == MagickCoreSignature);
2119 assert(image->cache != (Cache) NULL);
2120 cache_info=(CacheInfo *) image->cache;
2121 assert(cache_info->signature == MagickCoreSignature);
2122 assert(
id < (
int) cache_info->number_threads);
2123 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2124 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2125 cache_info->nexus_info[
id],exception);
2126 return(CopyPixel(image,p,pixel));
2163MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2164 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2165 PixelInfo *pixel,ExceptionInfo *exception)
2168 *magick_restrict cache_info;
2171 id = GetOpenMPThreadId();
2176 assert(image != (
const Image *) NULL);
2177 assert(image->signature == MagickCoreSignature);
2178 assert(image->cache != (Cache) NULL);
2179 cache_info=(CacheInfo *) image->cache;
2180 assert(cache_info->signature == MagickCoreSignature);
2181 assert(
id < (
int) cache_info->number_threads);
2182 GetPixelInfo(image,pixel);
2183 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2184 cache_info->nexus_info[
id],exception);
2185 if (p == (
const Quantum *) NULL)
2186 return(MagickFalse);
2187 GetPixelInfoPixel(image,p,pixel);
2213MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2216 *magick_restrict cache_info;
2218 assert(cache != (Cache) NULL);
2219 cache_info=(CacheInfo *) cache;
2220 assert(cache_info->signature == MagickCoreSignature);
2221 if (IsEventLogging() != MagickFalse)
2222 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2223 cache_info->filename);
2224 return(cache_info->colorspace);
2250MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2253 *magick_restrict cache_info;
2255 assert(image != (
const Image *) NULL);
2256 assert(image->signature == MagickCoreSignature);
2257 assert(image->cache != (Cache) NULL);
2258 cache_info=(CacheInfo *) image->cache;
2259 assert(cache_info->signature == MagickCoreSignature);
2260 return(cache_info->cache_filename);
2285MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2287 assert(cache_methods != (CacheMethods *) NULL);
2288 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2289 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2290 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2291 cache_methods->get_virtual_metacontent_from_handler=
2292 GetVirtualMetacontentFromCache;
2293 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2294 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2295 cache_methods->get_authentic_metacontent_from_handler=
2296 GetAuthenticMetacontentFromCache;
2297 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2298 cache_methods->get_one_authentic_pixel_from_handler=
2299 GetOneAuthenticPixelFromCache;
2300 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2301 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2302 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2330MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2331 NexusInfo *magick_restrict nexus_info)
2334 *magick_restrict cache_info;
2339 assert(cache != NULL);
2340 cache_info=(CacheInfo *) cache;
2341 assert(cache_info->signature == MagickCoreSignature);
2342 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2344 return((MagickSizeType) cache_info->columns*cache_info->rows);
2375MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2376 ExceptionInfo *magick_unused(exception))
2379 *magick_restrict cache_info;
2381 assert(image != (
const Image *) NULL);
2382 assert(image->signature == MagickCoreSignature);
2383 assert(image->cache != (Cache) NULL);
2384 assert(length != (MagickSizeType *) NULL);
2385 magick_unreferenced(exception);
2386 cache_info=(CacheInfo *) image->cache;
2387 assert(cache_info->signature == MagickCoreSignature);
2388 *length=cache_info->length;
2389 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2390 return((
void *) NULL);
2391 return((
void *) cache_info->pixels);
2418MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2421 *magick_restrict cache_info;
2423 assert(cache != (Cache) NULL);
2424 cache_info=(CacheInfo *) cache;
2425 assert(cache_info->signature == MagickCoreSignature);
2426 if (IsEventLogging() != MagickFalse)
2427 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2428 cache_info->filename);
2429 return(cache_info->storage_class);
2459MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2463 *magick_restrict cache_info;
2465 assert(image != (Image *) NULL);
2466 assert(image->signature == MagickCoreSignature);
2467 if (IsEventLogging() != MagickFalse)
2468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2469 cache_info=(CacheInfo *) image->cache;
2470 assert(cache_info->signature == MagickCoreSignature);
2471 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2472 if (GetImagePixelCacheType(image) == DiskCache)
2473 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2501MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2504 *magick_restrict cache_info;
2506 assert(image != (Image *) NULL);
2507 assert(image->signature == MagickCoreSignature);
2508 assert(image->cache != (Cache) NULL);
2509 cache_info=(CacheInfo *) image->cache;
2510 assert(cache_info->signature == MagickCoreSignature);
2511 return(cache_info->virtual_pixel_method);
2537static const void *GetVirtualMetacontentFromCache(
const Image *image)
2540 *magick_restrict cache_info;
2543 id = GetOpenMPThreadId();
2546 *magick_restrict metacontent;
2548 assert(image != (
const Image *) NULL);
2549 assert(image->signature == MagickCoreSignature);
2550 assert(image->cache != (Cache) NULL);
2551 cache_info=(CacheInfo *) image->cache;
2552 assert(cache_info->signature == MagickCoreSignature);
2553 assert(
id < (
int) cache_info->number_threads);
2554 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2555 cache_info->nexus_info[
id]);
2556 return(metacontent);
2585MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2586 NexusInfo *magick_restrict nexus_info)
2589 *magick_restrict cache_info;
2591 assert(cache != (Cache) NULL);
2592 cache_info=(CacheInfo *) cache;
2593 assert(cache_info->signature == MagickCoreSignature);
2594 if (cache_info->storage_class == UndefinedClass)
2595 return((
void *) NULL);
2596 return(nexus_info->metacontent);
2623MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2626 *magick_restrict cache_info;
2629 id = GetOpenMPThreadId();
2632 *magick_restrict metacontent;
2634 assert(image != (
const Image *) NULL);
2635 assert(image->signature == MagickCoreSignature);
2636 assert(image->cache != (Cache) NULL);
2637 cache_info=(CacheInfo *) image->cache;
2638 assert(cache_info->signature == MagickCoreSignature);
2639 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2641 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2643 if (metacontent != (
const void *) NULL)
2644 return(metacontent);
2646 assert(
id < (
int) cache_info->number_threads);
2647 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2648 cache_info->nexus_info[
id]);
2649 return(metacontent);
2692 0, 48, 12, 60, 3, 51, 15, 63,
2693 32, 16, 44, 28, 35, 19, 47, 31,
2694 8, 56, 4, 52, 11, 59, 7, 55,
2695 40, 24, 36, 20, 43, 27, 39, 23,
2696 2, 50, 14, 62, 1, 49, 13, 61,
2697 34, 18, 46, 30, 33, 17, 45, 29,
2698 10, 58, 6, 54, 9, 57, 5, 53,
2699 42, 26, 38, 22, 41, 25, 37, 21
2702static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2707 index=x+DitherMatrix[x & 0x07]-32L;
2710 if (index >= (ssize_t) columns)
2711 return((ssize_t) columns-1L);
2715static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2720 index=y+DitherMatrix[y & 0x07]-32L;
2723 if (index >= (ssize_t) rows)
2724 return((ssize_t) rows-1L);
2728static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2732 if (x >= (ssize_t) columns)
2733 return((ssize_t) (columns-1));
2737static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2741 if (y >= (ssize_t) rows)
2742 return((ssize_t) (rows-1));
2746static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2747 const MagickOffsetType y)
2749 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2750 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2751 return(MagickFalse);
2755static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2757 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2760static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2762 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2765static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2766 const size_t extent)
2771 modulo.quotient=offset;
2775 modulo.quotient=offset/((ssize_t) extent);
2776 modulo.remainder=offset % ((ssize_t) extent);
2778 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2781 modulo.remainder+=((ssize_t) extent);
2786MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2787 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2788 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2789 ExceptionInfo *exception)
2792 *magick_restrict cache_info;
2808 *magick_restrict virtual_nexus;
2811 *magick_restrict pixels,
2813 virtual_pixel[MaxPixelChannels];
2824 *magick_restrict virtual_metacontent;
2829 assert(image != (
const Image *) NULL);
2830 assert(image->signature == MagickCoreSignature);
2831 assert(image->cache != (Cache) NULL);
2832 cache_info=(CacheInfo *) image->cache;
2833 assert(cache_info->signature == MagickCoreSignature);
2834 if (cache_info->type == UndefinedCache)
2835 return((
const Quantum *) NULL);
2836#if defined(MAGICKCORE_OPENCL_SUPPORT)
2837 CopyOpenCLBuffer(cache_info);
2839 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2840 ((image->channels & WriteMaskChannel) != 0) ||
2841 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2842 nexus_info,exception);
2843 if (pixels == (Quantum *) NULL)
2844 return((
const Quantum *) NULL);
2845 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2846 return((
const Quantum *) NULL);
2847 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2848 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2849 return((
const Quantum *) NULL);
2850 offset+=nexus_info->region.x;
2851 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2852 nexus_info->region.width-1L;
2853 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2854 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2855 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2856 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2864 if (nexus_info->authentic_pixel_cache != MagickFalse)
2866 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2867 if (status == MagickFalse)
2868 return((
const Quantum *) NULL);
2869 if (cache_info->metacontent_extent != 0)
2871 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2872 if (status == MagickFalse)
2873 return((
const Quantum *) NULL);
2880 virtual_nexus=nexus_info->virtual_nexus;
2882 s=(
unsigned char *) nexus_info->metacontent;
2883 (void) memset(virtual_pixel,0,cache_info->number_channels*
2884 sizeof(*virtual_pixel));
2885 virtual_metacontent=(
void *) NULL;
2886 switch (virtual_pixel_method)
2888 case BackgroundVirtualPixelMethod:
2889 case BlackVirtualPixelMethod:
2890 case GrayVirtualPixelMethod:
2891 case TransparentVirtualPixelMethod:
2892 case MaskVirtualPixelMethod:
2893 case WhiteVirtualPixelMethod:
2894 case EdgeVirtualPixelMethod:
2895 case CheckerTileVirtualPixelMethod:
2896 case HorizontalTileVirtualPixelMethod:
2897 case VerticalTileVirtualPixelMethod:
2899 if (cache_info->metacontent_extent != 0)
2904 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2905 cache_info->metacontent_extent);
2906 if (virtual_metacontent == (
void *) NULL)
2908 (void) ThrowMagickException(exception,GetMagickModule(),
2909 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2910 return((
const Quantum *) NULL);
2912 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2914 switch (virtual_pixel_method)
2916 case BlackVirtualPixelMethod:
2918 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2919 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2920 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2923 case GrayVirtualPixelMethod:
2925 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2926 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2928 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2931 case TransparentVirtualPixelMethod:
2933 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2934 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2935 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2938 case MaskVirtualPixelMethod:
2939 case WhiteVirtualPixelMethod:
2941 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2942 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2943 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2948 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2950 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2952 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2954 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2956 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2966 for (v=0; v < (ssize_t) rows; v++)
2972 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2973 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2974 y_offset=EdgeY(y_offset,cache_info->rows);
2975 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2981 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2982 x_offset,(ssize_t) columns-u);
2983 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2984 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2994 length=(MagickSizeType) 1;
2995 switch (virtual_pixel_method)
2997 case EdgeVirtualPixelMethod:
3000 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3001 EdgeX(x_offset,cache_info->columns),
3002 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3004 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3007 case RandomVirtualPixelMethod:
3009 if (cache_info->random_info == (RandomInfo *) NULL)
3010 cache_info->random_info=AcquireRandomInfo();
3011 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3012 RandomX(cache_info->random_info,cache_info->columns),
3013 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3014 virtual_nexus,exception);
3015 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3018 case DitherVirtualPixelMethod:
3020 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3021 DitherX(x_offset,cache_info->columns),
3022 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3024 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3027 case TileVirtualPixelMethod:
3029 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3030 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3031 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3032 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3034 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3037 case MirrorVirtualPixelMethod:
3039 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3040 if ((x_modulo.quotient & 0x01) == 1L)
3041 x_modulo.remainder=(ssize_t) cache_info->columns-
3042 x_modulo.remainder-1L;
3043 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3044 if ((y_modulo.quotient & 0x01) == 1L)
3045 y_modulo.remainder=(ssize_t) cache_info->rows-
3046 y_modulo.remainder-1L;
3047 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3048 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3050 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3053 case HorizontalTileEdgeVirtualPixelMethod:
3055 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3056 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3057 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3058 virtual_nexus,exception);
3059 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3062 case VerticalTileEdgeVirtualPixelMethod:
3064 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3065 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3066 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3067 virtual_nexus,exception);
3068 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3071 case BackgroundVirtualPixelMethod:
3072 case BlackVirtualPixelMethod:
3073 case GrayVirtualPixelMethod:
3074 case TransparentVirtualPixelMethod:
3075 case MaskVirtualPixelMethod:
3076 case WhiteVirtualPixelMethod:
3079 r=virtual_metacontent;
3082 case CheckerTileVirtualPixelMethod:
3084 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3085 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3086 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3089 r=virtual_metacontent;
3092 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3093 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3095 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3098 case HorizontalTileVirtualPixelMethod:
3100 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3103 r=virtual_metacontent;
3106 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3107 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3108 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3109 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3111 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3114 case VerticalTileVirtualPixelMethod:
3116 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3119 r=virtual_metacontent;
3122 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3123 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3124 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3125 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3127 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3131 if (p == (
const Quantum *) NULL)
3133 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3135 q+=(ptrdiff_t) cache_info->number_channels;
3136 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3138 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3139 s+=(ptrdiff_t) cache_info->metacontent_extent;
3146 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3147 (
size_t) length,1UL,virtual_nexus,exception);
3148 if (p == (
const Quantum *) NULL)
3150 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3151 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3153 q+=(ptrdiff_t) cache_info->number_channels*length;
3154 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3156 (void) memcpy(s,r,(
size_t) length);
3157 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3160 if (u < (ssize_t) columns)
3166 if (virtual_metacontent != (
void *) NULL)
3167 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3168 if (v < (ssize_t) rows)
3169 return((
const Quantum *) NULL);
3207static const Quantum *GetVirtualPixelCache(
const Image *image,
3208 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3209 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3212 *magick_restrict cache_info;
3215 id = GetOpenMPThreadId();
3220 assert(image != (
const Image *) NULL);
3221 assert(image->signature == MagickCoreSignature);
3222 assert(image->cache != (Cache) NULL);
3223 cache_info=(CacheInfo *) image->cache;
3224 assert(cache_info->signature == MagickCoreSignature);
3225 assert(
id < (
int) cache_info->number_threads);
3226 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3227 cache_info->nexus_info[
id],exception);
3254MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3257 *magick_restrict cache_info;
3260 id = GetOpenMPThreadId();
3262 assert(image != (
const Image *) NULL);
3263 assert(image->signature == MagickCoreSignature);
3264 assert(image->cache != (Cache) NULL);
3265 cache_info=(CacheInfo *) image->cache;
3266 assert(cache_info->signature == MagickCoreSignature);
3267 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3268 return(cache_info->methods.get_virtual_pixels_handler(image));
3269 assert(
id < (
int) cache_info->number_threads);
3270 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3321MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3322 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3323 ExceptionInfo *exception)
3326 *magick_restrict cache_info;
3329 id = GetOpenMPThreadId();
3334 assert(image != (
const Image *) NULL);
3335 assert(image->signature == MagickCoreSignature);
3336 assert(image->cache != (Cache) NULL);
3337 cache_info=(CacheInfo *) image->cache;
3338 assert(cache_info->signature == MagickCoreSignature);
3339 if (cache_info->methods.get_virtual_pixel_handler !=
3340 (GetVirtualPixelHandler) NULL)
3341 return(cache_info->methods.get_virtual_pixel_handler(image,
3342 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3343 assert(
id < (
int) cache_info->number_threads);
3344 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3345 columns,rows,cache_info->nexus_info[
id],exception);
3372static const Quantum *GetVirtualPixelsCache(
const Image *image)
3375 *magick_restrict cache_info;
3378 id = GetOpenMPThreadId();
3380 assert(image != (
const Image *) NULL);
3381 assert(image->signature == MagickCoreSignature);
3382 assert(image->cache != (Cache) NULL);
3383 cache_info=(CacheInfo *) image->cache;
3384 assert(cache_info->signature == MagickCoreSignature);
3385 assert(
id < (
int) cache_info->number_threads);
3386 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3415MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3416 NexusInfo *magick_restrict nexus_info)
3419 *magick_restrict cache_info;
3421 assert(cache != (Cache) NULL);
3422 cache_info=(CacheInfo *) cache;
3423 assert(cache_info->signature == MagickCoreSignature);
3424 if (cache_info->storage_class == UndefinedClass)
3425 return((Quantum *) NULL);
3426 return((
const Quantum *) nexus_info->pixels);
3459static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3460 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3465 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3467 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3468 gamma=MagickSafeReciprocal(gamma);
3469 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3472static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3473 ExceptionInfo *exception)
3476 *magick_restrict cache_info;
3488 if (IsEventLogging() != MagickFalse)
3489 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3490 if ((image->channels & CompositeMaskChannel) == 0)
3492 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3494 cache_info=(CacheInfo *) image->cache;
3495 if (cache_info == (Cache) NULL)
3496 return(MagickFalse);
3497 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3498 nexus_info->region.width,nexus_info->region.height,
3499 nexus_info->virtual_nexus,exception);
3500 q=nexus_info->pixels;
3501 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3502 return(MagickFalse);
3503 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3508 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3516 alpha=(double) GetPixelCompositeMask(image,p);
3517 for (i=0; i < (ssize_t) image->number_channels; i++)
3519 PixelChannel channel = GetPixelChannelChannel(image,i);
3520 PixelTrait traits = GetPixelChannelTraits(image,channel);
3521 if ((traits & UpdatePixelTrait) == 0)
3523 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3525 p+=(ptrdiff_t) GetPixelChannels(image);
3526 q+=(ptrdiff_t) GetPixelChannels(image);
3563static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3564 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3569 if ((count == 0) || (quantum == 0))
3571 length=count*quantum;
3572 if (quantum != (length/count))
3579 return(MagickFalse);
3582static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3591 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3593 if (*cache_info->cache_filename ==
'\0')
3594 file=AcquireUniqueFileResource(cache_info->cache_filename);
3600 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3605 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3606 O_BINARY | O_EXCL,S_MODE);
3608 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3614 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3617 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3622 return(MagickFalse);
3623 (void) AcquireMagickResource(FileResource,1);
3624 if (cache_info->file != -1)
3625 (void) ClosePixelCacheOnDisk(cache_info);
3626 cache_info->file=file;
3627 cache_info->disk_mode=mode;
3631static inline MagickOffsetType WritePixelCacheRegion(
3632 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3633 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3641#if !defined(MAGICKCORE_HAVE_PWRITE)
3642 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3643 return((MagickOffsetType) -1);
3645 for (i=0; i < (MagickOffsetType) length; i+=count)
3647#if !defined(MAGICKCORE_HAVE_PWRITE)
3648 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3649 (MagickSizeType) i,MagickMaxBufferExtent));
3651 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3652 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3664static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3667 *magick_restrict cache_info;
3672 cache_info=(CacheInfo *) image->cache;
3673 if (cache_info->debug != MagickFalse)
3676 format[MagickPathExtent],
3677 message[MagickPathExtent];
3679 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3680 (void) FormatLocaleString(message,MagickPathExtent,
3681 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3682 cache_info->cache_filename,cache_info->file,format);
3683 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3685 if (length != (MagickSizeType) ((MagickOffsetType) length))
3686 return(MagickFalse);
3687 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3689 return(MagickFalse);
3690 if ((MagickSizeType) offset < length)
3696 extent=(MagickOffsetType) length-1;
3697 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3700 return(MagickFalse);
3701#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3702 if (cache_info->synchronize != MagickFalse)
3703 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3704 return(MagickFalse);
3707 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3709 return(MagickFalse);
3713static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3714 ExceptionInfo *exception)
3717 *magick_restrict cache_info,
3721 format[MagickPathExtent],
3722 message[MagickPathExtent];
3739 assert(image != (
const Image *) NULL);
3740 assert(image->signature == MagickCoreSignature);
3741 assert(image->cache != (Cache) NULL);
3742 if (IsEventLogging() != MagickFalse)
3743 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3744 if (cache_anonymous_memory < 0)
3752 cache_anonymous_memory=0;
3753 value=GetPolicyValue(
"pixel-cache-memory");
3754 if (value == (
char *) NULL)
3755 value=GetPolicyValue(
"cache:memory-map");
3756 if (LocaleCompare(value,
"anonymous") == 0)
3758#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3759 cache_anonymous_memory=1;
3761 (void) ThrowMagickException(exception,GetMagickModule(),
3762 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3763 "`%s' (policy requires anonymous memory mapping)",image->filename);
3766 value=DestroyString(value);
3768 if ((image->columns == 0) || (image->rows == 0))
3769 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3770 cache_info=(CacheInfo *) image->cache;
3771 assert(cache_info->signature == MagickCoreSignature);
3772 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3773 ((MagickSizeType) image->rows > cache_info->height_limit))
3775 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3776 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3777 image->filename, (
double) image->columns, (
double) image->rows,
3778 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3779 return(MagickFalse);
3781 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3783 length=GetImageListLength(image);
3784 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3785 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3788 source_info=(*cache_info);
3789 source_info.file=(-1);
3790 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3791 image->filename,(
double) image->scene);
3792 cache_info->storage_class=image->storage_class;
3793 cache_info->colorspace=image->colorspace;
3794 cache_info->alpha_trait=image->alpha_trait;
3795 cache_info->channels=image->channels;
3796 cache_info->rows=image->rows;
3797 cache_info->columns=image->columns;
3798 status=ResetPixelChannelMap(image,exception);
3799 if (status == MagickFalse)
3800 return(MagickFalse);
3801 cache_info->number_channels=GetPixelChannels(image);
3802 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3803 sizeof(*image->channel_map));
3804 cache_info->metacontent_extent=image->metacontent_extent;
3805 cache_info->mode=mode;
3806 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3807 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3808 if (image->metacontent_extent != 0)
3809 packet_size+=cache_info->metacontent_extent;
3810 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3812 cache_info->storage_class=UndefinedClass;
3813 cache_info->length=0;
3814 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3817 columns=(size_t) (length/cache_info->rows/packet_size);
3818 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3819 ((ssize_t) cache_info->rows < 0))
3821 cache_info->storage_class=UndefinedClass;
3822 cache_info->length=0;
3823 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3826 cache_info->length=length;
3827 if (image->ping != MagickFalse)
3829 cache_info->type=PingCache;
3832 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3833 cache_info->columns*cache_info->rows);
3834 if (cache_info->mode == PersistMode)
3836 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3837 cache_info->metacontent_extent);
3838 if ((status != MagickFalse) &&
3839 (length == (MagickSizeType) ((
size_t) length)) &&
3840 ((cache_info->type == UndefinedCache) ||
3841 (cache_info->type == MemoryCache)))
3843 status=AcquireMagickResource(MemoryResource,cache_info->length);
3844 if (status != MagickFalse)
3847 if (cache_anonymous_memory <= 0)
3849 cache_info->mapped=MagickFalse;
3850 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3851 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3855 cache_info->mapped=MagickTrue;
3856 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3857 cache_info->length);
3859 if (cache_info->pixels == (Quantum *) NULL)
3861 cache_info->mapped=source_info.mapped;
3862 cache_info->pixels=source_info.pixels;
3869 cache_info->type=MemoryCache;
3870 cache_info->metacontent=(
void *) NULL;
3871 if (cache_info->metacontent_extent != 0)
3872 cache_info->metacontent=(
void *) (cache_info->pixels+
3873 cache_info->number_channels*number_pixels);
3874 if ((source_info.storage_class != UndefinedClass) &&
3877 status=ClonePixelCacheRepository(cache_info,&source_info,
3879 RelinquishPixelCachePixels(&source_info);
3881 if (cache_info->debug != MagickFalse)
3883 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3884 MagickPathExtent,format);
3885 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3887 (void) FormatLocaleString(message,MagickPathExtent,
3888 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3889 cache_info->filename,cache_info->mapped != MagickFalse ?
3890 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3891 (
double) cache_info->rows,(
double)
3892 cache_info->number_channels,format);
3893 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3896 cache_info->storage_class=image->storage_class;
3899 if ((source_info.storage_class != UndefinedClass) &&
3901 RelinquishPixelCachePixels(&source_info);
3902 cache_info->type=UndefinedCache;
3903 return(MagickFalse);
3909 status=AcquireMagickResource(DiskResource,cache_info->length);
3910 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3912 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3920 server_info=AcquireDistributeCacheInfo(exception);
3921 if (server_info != (DistributeCacheInfo *) NULL)
3923 status=OpenDistributePixelCache(server_info,image);
3924 if (status == MagickFalse)
3926 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3927 GetDistributeCacheHostname(server_info));
3928 server_info=DestroyDistributeCacheInfo(server_info);
3936 cache_info->type=DistributedCache;
3937 cache_info->server_info=server_info;
3938 (void) FormatLocaleString(cache_info->cache_filename,
3939 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3940 (DistributeCacheInfo *) cache_info->server_info),
3941 GetDistributeCachePort((DistributeCacheInfo *)
3942 cache_info->server_info));
3943 if ((source_info.storage_class != UndefinedClass) &&
3946 status=ClonePixelCacheRepository(cache_info,&source_info,
3948 RelinquishPixelCachePixels(&source_info);
3950 if (cache_info->debug != MagickFalse)
3952 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3953 MagickPathExtent,format);
3954 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3956 (void) FormatLocaleString(message,MagickPathExtent,
3957 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3958 cache_info->filename,cache_info->cache_filename,
3959 GetDistributeCacheFile((DistributeCacheInfo *)
3960 cache_info->server_info),type,(
double) cache_info->columns,
3961 (
double) cache_info->rows,(
double)
3962 cache_info->number_channels,format);
3963 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3968 if ((source_info.storage_class != UndefinedClass) &&
3970 RelinquishPixelCachePixels(&source_info);
3971 cache_info->type=UndefinedCache;
3972 return(MagickFalse);
3977 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3978 RelinquishPixelCachePixels(&source_info);
3979 cache_info->type=UndefinedCache;
3980 (void) memset(image->channel_map,0,MaxPixelChannels*
3981 sizeof(*image->channel_map));
3982 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3983 "CacheResourcesExhausted",
"`%s'",image->filename);
3984 return(MagickFalse);
3989 if (status == MagickFalse)
3991 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3992 RelinquishPixelCachePixels(&source_info);
3993 cache_info->type=UndefinedCache;
3994 (void) memset(image->channel_map,0,MaxPixelChannels*
3995 sizeof(*image->channel_map));
3996 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3997 "CacheResourcesExhausted",
"`%s'",image->filename);
3998 return(MagickFalse);
4000 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4001 (cache_info->mode != PersistMode))
4003 (void) ClosePixelCacheOnDisk(cache_info);
4004 *cache_info->cache_filename=
'\0';
4006 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4008 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4009 RelinquishPixelCachePixels(&source_info);
4010 cache_info->type=UndefinedCache;
4011 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4013 return(MagickFalse);
4015 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4016 cache_info->length);
4017 if (status == MagickFalse)
4019 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4020 RelinquishPixelCachePixels(&source_info);
4021 cache_info->type=UndefinedCache;
4022 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4024 return(MagickFalse);
4026 cache_info->type=DiskCache;
4027 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4028 cache_info->metacontent_extent);
4029 if (length == (MagickSizeType) ((
size_t) length))
4031 status=AcquireMagickResource(MapResource,cache_info->length);
4032 if (status != MagickFalse)
4034 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4035 cache_info->offset,(
size_t) cache_info->length);
4036 if (cache_info->pixels == (Quantum *) NULL)
4038 cache_info->mapped=source_info.mapped;
4039 cache_info->pixels=source_info.pixels;
4040 RelinquishMagickResource(MapResource,cache_info->length);
4047 (void) ClosePixelCacheOnDisk(cache_info);
4048 cache_info->type=MapCache;
4049 cache_info->mapped=MagickTrue;
4050 cache_info->metacontent=(
void *) NULL;
4051 if (cache_info->metacontent_extent != 0)
4052 cache_info->metacontent=(
void *) (cache_info->pixels+
4053 cache_info->number_channels*number_pixels);
4054 if ((source_info.storage_class != UndefinedClass) &&
4057 status=ClonePixelCacheRepository(cache_info,&source_info,
4059 RelinquishPixelCachePixels(&source_info);
4061 if (cache_info->debug != MagickFalse)
4063 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4064 MagickPathExtent,format);
4065 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4067 (void) FormatLocaleString(message,MagickPathExtent,
4068 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4069 cache_info->filename,cache_info->cache_filename,
4070 cache_info->file,type,(
double) cache_info->columns,
4071 (
double) cache_info->rows,(
double)
4072 cache_info->number_channels,format);
4073 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4078 if ((source_info.storage_class != UndefinedClass) &&
4080 RelinquishPixelCachePixels(&source_info);
4081 cache_info->type=UndefinedCache;
4082 return(MagickFalse);
4089 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4091 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4092 RelinquishPixelCachePixels(&source_info);
4094 if (cache_info->debug != MagickFalse)
4096 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4097 MagickPathExtent,format);
4098 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4100 (void) FormatLocaleString(message,MagickPathExtent,
4101 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4102 cache_info->cache_filename,cache_info->file,type,(
double)
4103 cache_info->columns,(
double) cache_info->rows,(
double)
4104 cache_info->number_channels,format);
4105 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4109 cache_info->type=UndefinedCache;
4110 return(MagickFalse);
4152MagickExport MagickBooleanType PersistPixelCache(Image *image,
4153 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4154 ExceptionInfo *exception)
4157 *magick_restrict cache_info,
4158 *magick_restrict clone_info;
4166 assert(image != (Image *) NULL);
4167 assert(image->signature == MagickCoreSignature);
4168 if (IsEventLogging() != MagickFalse)
4169 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4170 assert(image->cache != (
void *) NULL);
4171 assert(filename != (
const char *) NULL);
4172 assert(offset != (MagickOffsetType *) NULL);
4173 page_size=GetMagickPageSize();
4174 cache_info=(CacheInfo *) image->cache;
4175 assert(cache_info->signature == MagickCoreSignature);
4176#if defined(MAGICKCORE_OPENCL_SUPPORT)
4177 CopyOpenCLBuffer(cache_info);
4179 if (attach != MagickFalse)
4184 if (cache_info->debug != MagickFalse)
4185 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4186 "attach persistent cache");
4187 (void) CopyMagickString(cache_info->cache_filename,filename,
4189 cache_info->type=MapCache;
4190 cache_info->offset=(*offset);
4191 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4192 return(MagickFalse);
4193 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4194 ((MagickOffsetType) cache_info->length % page_size));
4200 status=AcquireMagickResource(DiskResource,cache_info->length);
4201 if (status == MagickFalse)
4203 cache_info->type=UndefinedCache;
4204 (void) memset(image->channel_map,0,MaxPixelChannels*
4205 sizeof(*image->channel_map));
4206 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4207 "CacheResourcesExhausted",
"`%s'",image->filename);
4208 return(MagickFalse);
4210 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4211 clone_info->type=DiskCache;
4212 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4213 clone_info->file=(-1);
4214 clone_info->storage_class=cache_info->storage_class;
4215 clone_info->colorspace=cache_info->colorspace;
4216 clone_info->alpha_trait=cache_info->alpha_trait;
4217 clone_info->channels=cache_info->channels;
4218 clone_info->columns=cache_info->columns;
4219 clone_info->rows=cache_info->rows;
4220 clone_info->number_channels=cache_info->number_channels;
4221 clone_info->metacontent_extent=cache_info->metacontent_extent;
4222 clone_info->mode=PersistMode;
4223 clone_info->length=cache_info->length;
4224 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4225 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4226 clone_info->offset=(*offset);
4227 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4228 if (status != MagickFalse)
4229 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4230 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4231 ((MagickOffsetType) cache_info->length % page_size));
4232 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4274MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4275 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4276 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4279 *magick_restrict cache_info;
4288 *magick_restrict pixels;
4293 assert(image != (
const Image *) NULL);
4294 assert(image->signature == MagickCoreSignature);
4295 assert(image->cache != (Cache) NULL);
4296 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4297 if (cache_info == (Cache) NULL)
4298 return((Quantum *) NULL);
4299 assert(cache_info->signature == MagickCoreSignature);
4300 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4301 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4302 (y >= (ssize_t) cache_info->rows))
4304 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4305 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4306 return((Quantum *) NULL);
4308 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4309 return((Quantum *) NULL);
4310 offset=y*(MagickOffsetType) cache_info->columns+x;
4312 return((Quantum *) NULL);
4313 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4314 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4315 (MagickOffsetType) columns-1;
4316 if ((MagickSizeType) offset >= number_pixels)
4317 return((Quantum *) NULL);
4321 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4322 ((image->channels & WriteMaskChannel) != 0) ||
4323 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4324 nexus_info,exception);
4361static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4362 const ssize_t y,
const size_t columns,
const size_t rows,
4363 ExceptionInfo *exception)
4366 *magick_restrict cache_info;
4369 id = GetOpenMPThreadId();
4372 *magick_restrict pixels;
4374 assert(image != (
const Image *) NULL);
4375 assert(image->signature == MagickCoreSignature);
4376 assert(image->cache != (Cache) NULL);
4377 cache_info=(CacheInfo *) image->cache;
4378 assert(cache_info->signature == MagickCoreSignature);
4379 assert(
id < (
int) cache_info->number_threads);
4380 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4381 cache_info->nexus_info[
id],exception);
4441MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4442 const ssize_t y,
const size_t columns,
const size_t rows,
4443 ExceptionInfo *exception)
4446 *magick_restrict cache_info;
4449 id = GetOpenMPThreadId();
4452 *magick_restrict pixels;
4454 assert(image != (Image *) NULL);
4455 assert(image->signature == MagickCoreSignature);
4456 assert(image->cache != (Cache) NULL);
4457 cache_info=(CacheInfo *) image->cache;
4458 assert(cache_info->signature == MagickCoreSignature);
4459 if (cache_info->methods.queue_authentic_pixels_handler !=
4460 (QueueAuthenticPixelsHandler) NULL)
4462 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4463 columns,rows,exception);
4466 assert(
id < (
int) cache_info->number_threads);
4467 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4468 cache_info->nexus_info[
id],exception);
4501static inline MagickOffsetType ReadPixelCacheRegion(
4502 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4503 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4511#if !defined(MAGICKCORE_HAVE_PREAD)
4512 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4513 return((MagickOffsetType) -1);
4515 for (i=0; i < (MagickOffsetType) length; i+=count)
4517#if !defined(MAGICKCORE_HAVE_PREAD)
4518 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4519 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4521 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4522 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4534static MagickBooleanType ReadPixelCacheMetacontent(
4535 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4536 ExceptionInfo *exception)
4555 if (cache_info->metacontent_extent == 0)
4556 return(MagickFalse);
4557 if (nexus_info->authentic_pixel_cache != MagickFalse)
4559 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4560 return(MagickFalse);
4561 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4562 nexus_info->region.x;
4563 length=(MagickSizeType) nexus_info->region.width*
4564 cache_info->metacontent_extent;
4565 extent=length*nexus_info->region.height;
4566 rows=nexus_info->region.height;
4568 q=(
unsigned char *) nexus_info->metacontent;
4569 switch (cache_info->type)
4580 if ((cache_info->columns == nexus_info->region.width) &&
4581 (extent == (MagickSizeType) ((
size_t) extent)))
4586 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4587 cache_info->metacontent_extent;
4588 for (y=0; y < (ssize_t) rows; y++)
4590 (void) memcpy(q,p,(
size_t) length);
4591 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4592 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4601 LockSemaphoreInfo(cache_info->file_semaphore);
4602 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4604 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4605 cache_info->cache_filename);
4606 UnlockSemaphoreInfo(cache_info->file_semaphore);
4607 return(MagickFalse);
4609 if ((cache_info->columns == nexus_info->region.width) &&
4610 (extent <= MagickMaxBufferExtent))
4615 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4616 for (y=0; y < (ssize_t) rows; y++)
4618 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4619 (MagickOffsetType) extent*(MagickOffsetType)
4620 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4621 (MagickOffsetType) cache_info->metacontent_extent,length,
4622 (
unsigned char *) q);
4623 if (count != (MagickOffsetType) length)
4625 offset+=(MagickOffsetType) cache_info->columns;
4626 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4628 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4629 (void) ClosePixelCacheOnDisk(cache_info);
4630 UnlockSemaphoreInfo(cache_info->file_semaphore);
4633 case DistributedCache:
4641 LockSemaphoreInfo(cache_info->file_semaphore);
4642 region=nexus_info->region;
4643 if ((cache_info->columns != nexus_info->region.width) ||
4644 (extent > MagickMaxBufferExtent))
4651 for (y=0; y < (ssize_t) rows; y++)
4653 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4654 cache_info->server_info,®ion,length,(
unsigned char *) q);
4655 if (count != (MagickOffsetType) length)
4657 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4660 UnlockSemaphoreInfo(cache_info->file_semaphore);
4666 if (y < (ssize_t) rows)
4668 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4669 cache_info->cache_filename);
4670 return(MagickFalse);
4672 if ((cache_info->debug != MagickFalse) &&
4673 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4674 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4675 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4676 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4677 nexus_info->region.x,(
double) nexus_info->region.y);
4709static MagickBooleanType ReadPixelCachePixels(
4710 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4711 ExceptionInfo *exception)
4731 if (nexus_info->authentic_pixel_cache != MagickFalse)
4733 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4734 return(MagickFalse);
4735 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4736 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4737 return(MagickFalse);
4738 offset+=nexus_info->region.x;
4739 number_channels=cache_info->number_channels;
4740 length=(MagickSizeType) number_channels*nexus_info->region.width*
4742 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4743 return(MagickFalse);
4744 rows=nexus_info->region.height;
4746 if ((extent == 0) || ((extent/length) != rows))
4747 return(MagickFalse);
4749 q=nexus_info->pixels;
4750 switch (cache_info->type)
4761 if ((cache_info->columns == nexus_info->region.width) &&
4762 (extent == (MagickSizeType) ((
size_t) extent)))
4767 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4769 for (y=0; y < (ssize_t) rows; y++)
4771 (void) memcpy(q,p,(
size_t) length);
4772 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4773 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4782 LockSemaphoreInfo(cache_info->file_semaphore);
4783 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4785 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4786 cache_info->cache_filename);
4787 UnlockSemaphoreInfo(cache_info->file_semaphore);
4788 return(MagickFalse);
4790 if ((cache_info->columns == nexus_info->region.width) &&
4791 (extent <= MagickMaxBufferExtent))
4796 for (y=0; y < (ssize_t) rows; y++)
4798 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4799 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4800 sizeof(*q),length,(
unsigned char *) q);
4801 if (count != (MagickOffsetType) length)
4803 offset+=(MagickOffsetType) cache_info->columns;
4804 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4806 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4807 (void) ClosePixelCacheOnDisk(cache_info);
4808 UnlockSemaphoreInfo(cache_info->file_semaphore);
4811 case DistributedCache:
4819 LockSemaphoreInfo(cache_info->file_semaphore);
4820 region=nexus_info->region;
4821 if ((cache_info->columns != nexus_info->region.width) ||
4822 (extent > MagickMaxBufferExtent))
4829 for (y=0; y < (ssize_t) rows; y++)
4831 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4832 cache_info->server_info,®ion,length,(
unsigned char *) q);
4833 if (count != (MagickOffsetType) length)
4835 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4838 UnlockSemaphoreInfo(cache_info->file_semaphore);
4844 if (y < (ssize_t) rows)
4846 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4847 cache_info->cache_filename);
4848 return(MagickFalse);
4850 if ((cache_info->debug != MagickFalse) &&
4851 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4852 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4853 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4854 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4855 nexus_info->region.x,(
double) nexus_info->region.y);
4882MagickPrivate Cache ReferencePixelCache(Cache cache)
4885 *magick_restrict cache_info;
4887 assert(cache != (Cache *) NULL);
4888 cache_info=(CacheInfo *) cache;
4889 assert(cache_info->signature == MagickCoreSignature);
4890 LockSemaphoreInfo(cache_info->semaphore);
4891 cache_info->reference_count++;
4892 UnlockSemaphoreInfo(cache_info->semaphore);
4918MagickPrivate
void ResetPixelCacheChannels(Image *image)
4921 *magick_restrict cache_info;
4923 assert(image != (
const Image *) NULL);
4924 assert(image->signature == MagickCoreSignature);
4925 assert(image->cache != (Cache) NULL);
4926 cache_info=(CacheInfo *) image->cache;
4927 assert(cache_info->signature == MagickCoreSignature);
4928 cache_info->number_channels=GetPixelChannels(image);
4949MagickPrivate
void ResetCacheAnonymousMemory(
void)
4951 cache_anonymous_memory=0;
4983MagickExport MagickBooleanType ReshapePixelCache(Image *image,
4984 const size_t columns,
const size_t rows,ExceptionInfo *exception)
4992 assert(image != (Image *) NULL);
4993 assert(image->signature == MagickCoreSignature);
4994 if (IsEventLogging() != MagickFalse)
4995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4996 assert(image->cache != (
void *) NULL);
4997 extent=(MagickSizeType) columns*rows;
4998 if (extent > ((MagickSizeType) image->columns*image->rows))
4999 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5001 image->columns=columns;
5003 cache_info=(CacheInfo *) image->cache;
5004 cache_info->columns=columns;
5005 cache_info->rows=rows;
5006 return(SyncImagePixelCache(image,exception));
5033MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5036 *magick_restrict cache_info;
5038 GetOneAuthenticPixelFromHandler
5039 get_one_authentic_pixel_from_handler;
5041 GetOneVirtualPixelFromHandler
5042 get_one_virtual_pixel_from_handler;
5047 assert(cache != (Cache) NULL);
5048 assert(cache_methods != (CacheMethods *) NULL);
5049 cache_info=(CacheInfo *) cache;
5050 assert(cache_info->signature == MagickCoreSignature);
5051 if (IsEventLogging() != MagickFalse)
5052 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5053 cache_info->filename);
5054 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5055 cache_info->methods.get_virtual_pixel_handler=
5056 cache_methods->get_virtual_pixel_handler;
5057 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5058 cache_info->methods.destroy_pixel_handler=
5059 cache_methods->destroy_pixel_handler;
5060 if (cache_methods->get_virtual_metacontent_from_handler !=
5061 (GetVirtualMetacontentFromHandler) NULL)
5062 cache_info->methods.get_virtual_metacontent_from_handler=
5063 cache_methods->get_virtual_metacontent_from_handler;
5064 if (cache_methods->get_authentic_pixels_handler !=
5065 (GetAuthenticPixelsHandler) NULL)
5066 cache_info->methods.get_authentic_pixels_handler=
5067 cache_methods->get_authentic_pixels_handler;
5068 if (cache_methods->queue_authentic_pixels_handler !=
5069 (QueueAuthenticPixelsHandler) NULL)
5070 cache_info->methods.queue_authentic_pixels_handler=
5071 cache_methods->queue_authentic_pixels_handler;
5072 if (cache_methods->sync_authentic_pixels_handler !=
5073 (SyncAuthenticPixelsHandler) NULL)
5074 cache_info->methods.sync_authentic_pixels_handler=
5075 cache_methods->sync_authentic_pixels_handler;
5076 if (cache_methods->get_authentic_pixels_from_handler !=
5077 (GetAuthenticPixelsFromHandler) NULL)
5078 cache_info->methods.get_authentic_pixels_from_handler=
5079 cache_methods->get_authentic_pixels_from_handler;
5080 if (cache_methods->get_authentic_metacontent_from_handler !=
5081 (GetAuthenticMetacontentFromHandler) NULL)
5082 cache_info->methods.get_authentic_metacontent_from_handler=
5083 cache_methods->get_authentic_metacontent_from_handler;
5084 get_one_virtual_pixel_from_handler=
5085 cache_info->methods.get_one_virtual_pixel_from_handler;
5086 if (get_one_virtual_pixel_from_handler !=
5087 (GetOneVirtualPixelFromHandler) NULL)
5088 cache_info->methods.get_one_virtual_pixel_from_handler=
5089 cache_methods->get_one_virtual_pixel_from_handler;
5090 get_one_authentic_pixel_from_handler=
5091 cache_methods->get_one_authentic_pixel_from_handler;
5092 if (get_one_authentic_pixel_from_handler !=
5093 (GetOneAuthenticPixelFromHandler) NULL)
5094 cache_info->methods.get_one_authentic_pixel_from_handler=
5095 cache_methods->get_one_authentic_pixel_from_handler;
5136static inline MagickBooleanType AcquireCacheNexusPixels(
5137 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5138 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5140 if (length != (MagickSizeType) ((
size_t) length))
5142 (void) ThrowMagickException(exception,GetMagickModule(),
5143 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5144 cache_info->filename);
5145 return(MagickFalse);
5147 nexus_info->length=0;
5148 nexus_info->mapped=MagickFalse;
5149 if (cache_anonymous_memory <= 0)
5151 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5153 if (nexus_info->cache != (Quantum *) NULL)
5154 (void) memset(nexus_info->cache,0,(
size_t) length);
5158 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5159 if (nexus_info->cache != (Quantum *) NULL)
5160 nexus_info->mapped=MagickTrue;
5162 if (nexus_info->cache == (Quantum *) NULL)
5164 (void) ThrowMagickException(exception,GetMagickModule(),
5165 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5166 cache_info->filename);
5167 return(MagickFalse);
5169 nexus_info->length=length;
5173static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5176 if (nexus_info->length < CACHE_LINE_SIZE)
5178 if (mode == ReadMode)
5180 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5184 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5187static Quantum *SetPixelCacheNexusPixels(
5188 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5189 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5190 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5191 ExceptionInfo *exception)
5200 assert(cache_info != (
const CacheInfo *) NULL);
5201 assert(cache_info->signature == MagickCoreSignature);
5202 if (cache_info->type == UndefinedCache)
5203 return((Quantum *) NULL);
5204 assert(nexus_info->signature == MagickCoreSignature);
5205 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5206 if ((width == 0) || (height == 0))
5208 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5209 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5210 return((Quantum *) NULL);
5212 if (((MagickSizeType) width > cache_info->width_limit) ||
5213 ((MagickSizeType) height > cache_info->height_limit))
5215 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5216 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5217 return((Quantum *) NULL);
5219 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5220 (IsValidPixelOffset(y,height) == MagickFalse))
5222 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5223 "InvalidPixel",
"`%s'",cache_info->filename);
5224 return((Quantum *) NULL);
5226 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5227 (buffered == MagickFalse))
5229 if (((x >= 0) && (y >= 0) &&
5230 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5231 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5232 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5240 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5241 return((Quantum *) NULL);
5242 offset=y*(MagickOffsetType) cache_info->columns+x;
5243 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5244 cache_info->number_channels*offset;
5245 nexus_info->metacontent=(
void *) NULL;
5246 if (cache_info->metacontent_extent != 0)
5247 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5248 offset*(MagickOffsetType) cache_info->metacontent_extent;
5249 nexus_info->region.width=width;
5250 nexus_info->region.height=height;
5251 nexus_info->region.x=x;
5252 nexus_info->region.y=y;
5253 nexus_info->authentic_pixel_cache=MagickTrue;
5254 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5255 return(nexus_info->pixels);
5261 number_pixels=(MagickSizeType) width*height;
5262 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5263 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5264 if (cache_info->metacontent_extent != 0)
5265 length+=number_pixels*cache_info->metacontent_extent;
5267 if (nexus_info->cache == (Quantum *) NULL)
5268 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5270 if (nexus_info->length < length)
5272 RelinquishCacheNexusPixels(nexus_info);
5273 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5275 if (status == MagickFalse)
5276 return((Quantum *) NULL);
5277 nexus_info->pixels=nexus_info->cache;
5278 nexus_info->metacontent=(
void *) NULL;
5279 if (cache_info->metacontent_extent != 0)
5280 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5281 cache_info->number_channels*number_pixels);
5282 nexus_info->region.width=width;
5283 nexus_info->region.height=height;
5284 nexus_info->region.x=x;
5285 nexus_info->region.y=y;
5286 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5287 MagickTrue : MagickFalse;
5288 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5289 return(nexus_info->pixels);
5322static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5323 ExceptionInfo *exception)
5326 *magick_restrict image_view;
5334 assert(image != (Image *) NULL);
5335 assert(image->signature == MagickCoreSignature);
5336 if (IsEventLogging() != MagickFalse)
5337 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5338 assert(image->cache != (Cache) NULL);
5339 image->alpha_trait=BlendPixelTrait;
5341 image_view=AcquireVirtualCacheView(image,exception);
5342#if defined(MAGICKCORE_OPENMP_SUPPORT)
5343 #pragma omp parallel for schedule(static) shared(status) \
5344 magick_number_threads(image,image,image->rows,2)
5346 for (y=0; y < (ssize_t) image->rows; y++)
5354 if (status == MagickFalse)
5356 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5357 if (q == (Quantum *) NULL)
5362 for (x=0; x < (ssize_t) image->columns; x++)
5364 SetPixelAlpha(image,alpha,q);
5365 q+=(ptrdiff_t) GetPixelChannels(image);
5367 status=SyncCacheViewAuthenticPixels(image_view,exception);
5369 image_view=DestroyCacheView(image_view);
5373MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5374 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5377 *magick_restrict cache_info;
5382 assert(image != (Image *) NULL);
5383 assert(image->signature == MagickCoreSignature);
5384 if (IsEventLogging() != MagickFalse)
5385 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5386 assert(image->cache != (Cache) NULL);
5387 cache_info=(CacheInfo *) image->cache;
5388 assert(cache_info->signature == MagickCoreSignature);
5389 method=cache_info->virtual_pixel_method;
5390 cache_info->virtual_pixel_method=virtual_pixel_method;
5391 if ((image->columns != 0) && (image->rows != 0))
5392 switch (virtual_pixel_method)
5394 case BackgroundVirtualPixelMethod:
5396 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5397 ((image->alpha_trait & BlendPixelTrait) == 0))
5398 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5399 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5400 (IsGrayColorspace(image->colorspace) != MagickFalse))
5401 (void) SetImageColorspace(image,sRGBColorspace,exception);
5404 case TransparentVirtualPixelMethod:
5406 if ((image->alpha_trait & BlendPixelTrait) == 0)
5407 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5416#if defined(MAGICKCORE_OPENCL_SUPPORT)
5441static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5443 assert(cache_info != (CacheInfo *) NULL);
5444 assert(cache_info->signature == MagickCoreSignature);
5445 if ((cache_info->type != MemoryCache) ||
5446 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5451 LockSemaphoreInfo(cache_info->semaphore);
5452 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5453 UnlockSemaphoreInfo(cache_info->semaphore);
5456MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5459 *magick_restrict cache_info;
5461 assert(image != (
const Image *) NULL);
5462 cache_info=(CacheInfo *) image->cache;
5463 CopyOpenCLBuffer(cache_info);
5496MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5497 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5500 *magick_restrict cache_info;
5508 assert(image != (Image *) NULL);
5509 assert(image->signature == MagickCoreSignature);
5510 if (image->cache == (Cache) NULL)
5511 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5512 cache_info=(CacheInfo *) image->cache;
5513 assert(cache_info->signature == MagickCoreSignature);
5514 if (cache_info->type == UndefinedCache)
5515 return(MagickFalse);
5516 if (image->mask_trait != UpdatePixelTrait)
5518 if (((image->channels & WriteMaskChannel) != 0) &&
5519 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5520 return(MagickFalse);
5521 if (((image->channels & CompositeMaskChannel) != 0) &&
5522 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5523 return(MagickFalse);
5525 if (nexus_info->authentic_pixel_cache != MagickFalse)
5527 if (image->taint == MagickFalse)
5528 image->taint=MagickTrue;
5531 assert(cache_info->signature == MagickCoreSignature);
5532 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5533 if ((cache_info->metacontent_extent != 0) &&
5534 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5535 return(MagickFalse);
5536 if ((status != MagickFalse) && (image->taint == MagickFalse))
5537 image->taint=MagickTrue;
5568static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5569 ExceptionInfo *exception)
5572 *magick_restrict cache_info;
5575 id = GetOpenMPThreadId();
5580 assert(image != (Image *) NULL);
5581 assert(image->signature == MagickCoreSignature);
5582 assert(image->cache != (Cache) NULL);
5583 cache_info=(CacheInfo *) image->cache;
5584 assert(cache_info->signature == MagickCoreSignature);
5585 assert(
id < (
int) cache_info->number_threads);
5586 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5618MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5619 ExceptionInfo *exception)
5622 *magick_restrict cache_info;
5625 id = GetOpenMPThreadId();
5630 assert(image != (Image *) NULL);
5631 assert(image->signature == MagickCoreSignature);
5632 assert(image->cache != (Cache) NULL);
5633 cache_info=(CacheInfo *) image->cache;
5634 assert(cache_info->signature == MagickCoreSignature);
5635 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5637 status=cache_info->methods.sync_authentic_pixels_handler(image,
5641 assert(
id < (
int) cache_info->number_threads);
5642 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5674MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5675 ExceptionInfo *exception)
5678 *magick_restrict cache_info;
5680 assert(image != (Image *) NULL);
5681 assert(exception != (ExceptionInfo *) NULL);
5682 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5683 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5714static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5715 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5734 if (cache_info->metacontent_extent == 0)
5735 return(MagickFalse);
5736 if (nexus_info->authentic_pixel_cache != MagickFalse)
5738 if (nexus_info->metacontent == (
unsigned char *) NULL)
5739 return(MagickFalse);
5740 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5741 return(MagickFalse);
5742 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5743 nexus_info->region.x;
5744 length=(MagickSizeType) nexus_info->region.width*
5745 cache_info->metacontent_extent;
5746 extent=(MagickSizeType) length*nexus_info->region.height;
5747 rows=nexus_info->region.height;
5749 p=(
unsigned char *) nexus_info->metacontent;
5750 switch (cache_info->type)
5761 if ((cache_info->columns == nexus_info->region.width) &&
5762 (extent == (MagickSizeType) ((
size_t) extent)))
5767 q=(
unsigned char *) cache_info->metacontent+offset*
5768 (MagickOffsetType) cache_info->metacontent_extent;
5769 for (y=0; y < (ssize_t) rows; y++)
5771 (void) memcpy(q,p,(
size_t) length);
5772 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5773 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5782 LockSemaphoreInfo(cache_info->file_semaphore);
5783 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5785 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5786 cache_info->cache_filename);
5787 UnlockSemaphoreInfo(cache_info->file_semaphore);
5788 return(MagickFalse);
5790 if ((cache_info->columns == nexus_info->region.width) &&
5791 (extent <= MagickMaxBufferExtent))
5796 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5797 for (y=0; y < (ssize_t) rows; y++)
5799 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5800 (MagickOffsetType) extent*(MagickOffsetType)
5801 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5802 (MagickOffsetType) cache_info->metacontent_extent,length,
5803 (
const unsigned char *) p);
5804 if (count != (MagickOffsetType) length)
5806 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5807 offset+=(MagickOffsetType) cache_info->columns;
5809 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5810 (void) ClosePixelCacheOnDisk(cache_info);
5811 UnlockSemaphoreInfo(cache_info->file_semaphore);
5814 case DistributedCache:
5822 LockSemaphoreInfo(cache_info->file_semaphore);
5823 region=nexus_info->region;
5824 if ((cache_info->columns != nexus_info->region.width) ||
5825 (extent > MagickMaxBufferExtent))
5832 for (y=0; y < (ssize_t) rows; y++)
5834 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5835 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5836 if (count != (MagickOffsetType) length)
5838 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5841 UnlockSemaphoreInfo(cache_info->file_semaphore);
5847 if (y < (ssize_t) rows)
5849 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5850 cache_info->cache_filename);
5851 return(MagickFalse);
5853 if ((cache_info->debug != MagickFalse) &&
5854 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5855 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5856 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5857 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5858 nexus_info->region.x,(
double) nexus_info->region.y);
5890static MagickBooleanType WritePixelCachePixels(
5891 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5892 ExceptionInfo *exception)
5911 if (nexus_info->authentic_pixel_cache != MagickFalse)
5913 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5914 return(MagickFalse);
5915 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5916 nexus_info->region.x;
5917 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5919 extent=length*nexus_info->region.height;
5920 rows=nexus_info->region.height;
5922 p=nexus_info->pixels;
5923 switch (cache_info->type)
5934 if ((cache_info->columns == nexus_info->region.width) &&
5935 (extent == (MagickSizeType) ((
size_t) extent)))
5940 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5942 for (y=0; y < (ssize_t) rows; y++)
5944 (void) memcpy(q,p,(
size_t) length);
5945 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5946 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5955 LockSemaphoreInfo(cache_info->file_semaphore);
5956 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5958 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5959 cache_info->cache_filename);
5960 UnlockSemaphoreInfo(cache_info->file_semaphore);
5961 return(MagickFalse);
5963 if ((cache_info->columns == nexus_info->region.width) &&
5964 (extent <= MagickMaxBufferExtent))
5969 for (y=0; y < (ssize_t) rows; y++)
5971 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5972 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5973 sizeof(*p),length,(
const unsigned char *) p);
5974 if (count != (MagickOffsetType) length)
5976 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5977 offset+=(MagickOffsetType) cache_info->columns;
5979 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5980 (void) ClosePixelCacheOnDisk(cache_info);
5981 UnlockSemaphoreInfo(cache_info->file_semaphore);
5984 case DistributedCache:
5992 LockSemaphoreInfo(cache_info->file_semaphore);
5993 region=nexus_info->region;
5994 if ((cache_info->columns != nexus_info->region.width) ||
5995 (extent > MagickMaxBufferExtent))
6002 for (y=0; y < (ssize_t) rows; y++)
6004 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6005 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6006 if (count != (MagickOffsetType) length)
6008 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6011 UnlockSemaphoreInfo(cache_info->file_semaphore);
6017 if (y < (ssize_t) rows)
6019 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6020 cache_info->cache_filename);
6021 return(MagickFalse);
6023 if ((cache_info->debug != MagickFalse) &&
6024 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6025 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6026 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6027 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6028 nexus_info->region.x,(
double) nexus_info->region.y);