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 (void) 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 (ValidatePixelCacheMorphology(image) == MagickFalse)
1827 image->type=UndefinedType;
1828 status=OpenPixelCache(image,IOMode,exception);
1829 cache_info=(CacheInfo *) image->cache;
1830 if (cache_info->file != -1)
1831 (void) ClosePixelCacheOnDisk(cache_info);
1834 UnlockSemaphoreInfo(image->semaphore);
1835 if (status == MagickFalse)
1836 return((Cache) NULL);
1837 return(image->cache);
1863MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1866 *magick_restrict cache_info;
1868 assert(image != (Image *) NULL);
1869 assert(image->signature == MagickCoreSignature);
1870 assert(image->cache != (Cache) NULL);
1871 cache_info=(CacheInfo *) image->cache;
1872 assert(cache_info->signature == MagickCoreSignature);
1873 return(cache_info->type);
1907static inline MagickBooleanType CopyPixel(
const Image *image,
1908 const Quantum *source,Quantum *destination)
1913 if (source == (
const Quantum *) NULL)
1915 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1916 destination[GreenPixelChannel]=ClampToQuantum(
1917 image->background_color.green);
1918 destination[BluePixelChannel]=ClampToQuantum(
1919 image->background_color.blue);
1920 destination[BlackPixelChannel]=ClampToQuantum(
1921 image->background_color.black);
1922 destination[AlphaPixelChannel]=ClampToQuantum(
1923 image->background_color.alpha);
1924 return(MagickFalse);
1926 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1928 PixelChannel channel = GetPixelChannelChannel(image,i);
1929 destination[channel]=source[i];
1934MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1935 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1938 *magick_restrict cache_info;
1943 assert(image != (Image *) NULL);
1944 assert(image->signature == MagickCoreSignature);
1945 assert(image->cache != (Cache) NULL);
1946 cache_info=(CacheInfo *) image->cache;
1947 assert(cache_info->signature == MagickCoreSignature);
1948 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1949 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1950 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1951 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1952 return(CopyPixel(image,q,pixel));
1986static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
1987 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1990 *magick_restrict cache_info;
1993 id = GetOpenMPThreadId();
1998 assert(image != (
const Image *) NULL);
1999 assert(image->signature == MagickCoreSignature);
2000 assert(image->cache != (Cache) NULL);
2001 cache_info=(CacheInfo *) image->cache;
2002 assert(cache_info->signature == MagickCoreSignature);
2003 assert(
id < (
int) cache_info->number_threads);
2004 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2005 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2007 return(CopyPixel(image,q,pixel));
2041MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2042 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2045 *magick_restrict cache_info;
2048 id = GetOpenMPThreadId();
2053 assert(image != (
const Image *) NULL);
2054 assert(image->signature == MagickCoreSignature);
2055 assert(image->cache != (Cache) NULL);
2056 cache_info=(CacheInfo *) image->cache;
2057 assert(cache_info->signature == MagickCoreSignature);
2058 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2059 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2060 (GetOneVirtualPixelFromHandler) NULL)
2061 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2062 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2063 assert(
id < (
int) cache_info->number_threads);
2064 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2065 1UL,1UL,cache_info->nexus_info[
id],exception);
2066 return(CopyPixel(image,p,pixel));
2103static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2104 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2105 Quantum *pixel,ExceptionInfo *exception)
2108 *magick_restrict cache_info;
2111 id = GetOpenMPThreadId();
2116 assert(image != (
const Image *) NULL);
2117 assert(image->signature == MagickCoreSignature);
2118 assert(image->cache != (Cache) NULL);
2119 cache_info=(CacheInfo *) image->cache;
2120 assert(cache_info->signature == MagickCoreSignature);
2121 assert(
id < (
int) cache_info->number_threads);
2122 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2123 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2124 cache_info->nexus_info[
id],exception);
2125 return(CopyPixel(image,p,pixel));
2162MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2163 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2164 PixelInfo *pixel,ExceptionInfo *exception)
2167 *magick_restrict cache_info;
2170 id = GetOpenMPThreadId();
2175 assert(image != (
const Image *) NULL);
2176 assert(image->signature == MagickCoreSignature);
2177 assert(image->cache != (Cache) NULL);
2178 cache_info=(CacheInfo *) image->cache;
2179 assert(cache_info->signature == MagickCoreSignature);
2180 assert(
id < (
int) cache_info->number_threads);
2181 GetPixelInfo(image,pixel);
2182 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2183 cache_info->nexus_info[
id],exception);
2184 if (p == (
const Quantum *) NULL)
2185 return(MagickFalse);
2186 GetPixelInfoPixel(image,p,pixel);
2212MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2215 *magick_restrict cache_info;
2217 assert(cache != (Cache) NULL);
2218 cache_info=(CacheInfo *) cache;
2219 assert(cache_info->signature == MagickCoreSignature);
2220 if (IsEventLogging() != MagickFalse)
2221 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2222 cache_info->filename);
2223 return(cache_info->colorspace);
2249MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2252 *magick_restrict cache_info;
2254 assert(image != (
const Image *) NULL);
2255 assert(image->signature == MagickCoreSignature);
2256 assert(image->cache != (Cache) NULL);
2257 cache_info=(CacheInfo *) image->cache;
2258 assert(cache_info->signature == MagickCoreSignature);
2259 return(cache_info->cache_filename);
2284MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2286 assert(cache_methods != (CacheMethods *) NULL);
2287 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2288 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2289 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2290 cache_methods->get_virtual_metacontent_from_handler=
2291 GetVirtualMetacontentFromCache;
2292 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2293 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2294 cache_methods->get_authentic_metacontent_from_handler=
2295 GetAuthenticMetacontentFromCache;
2296 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2297 cache_methods->get_one_authentic_pixel_from_handler=
2298 GetOneAuthenticPixelFromCache;
2299 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2300 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2301 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2329MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2330 NexusInfo *magick_restrict nexus_info)
2333 *magick_restrict cache_info;
2338 assert(cache != NULL);
2339 cache_info=(CacheInfo *) cache;
2340 assert(cache_info->signature == MagickCoreSignature);
2341 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2343 return((MagickSizeType) cache_info->columns*cache_info->rows);
2374MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2375 ExceptionInfo *magick_unused(exception))
2378 *magick_restrict cache_info;
2380 assert(image != (
const Image *) NULL);
2381 assert(image->signature == MagickCoreSignature);
2382 assert(image->cache != (Cache) NULL);
2383 assert(length != (MagickSizeType *) NULL);
2384 magick_unreferenced(exception);
2385 cache_info=(CacheInfo *) image->cache;
2386 assert(cache_info->signature == MagickCoreSignature);
2387 *length=cache_info->length;
2388 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2389 return((
void *) NULL);
2390 return((
void *) cache_info->pixels);
2417MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2420 *magick_restrict cache_info;
2422 assert(cache != (Cache) NULL);
2423 cache_info=(CacheInfo *) cache;
2424 assert(cache_info->signature == MagickCoreSignature);
2425 if (IsEventLogging() != MagickFalse)
2426 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2427 cache_info->filename);
2428 return(cache_info->storage_class);
2458MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2462 *magick_restrict cache_info;
2464 assert(image != (Image *) NULL);
2465 assert(image->signature == MagickCoreSignature);
2466 if (IsEventLogging() != MagickFalse)
2467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2468 cache_info=(CacheInfo *) image->cache;
2469 assert(cache_info->signature == MagickCoreSignature);
2470 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2471 if (GetImagePixelCacheType(image) == DiskCache)
2472 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2500MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2503 *magick_restrict cache_info;
2505 assert(image != (Image *) NULL);
2506 assert(image->signature == MagickCoreSignature);
2507 assert(image->cache != (Cache) NULL);
2508 cache_info=(CacheInfo *) image->cache;
2509 assert(cache_info->signature == MagickCoreSignature);
2510 return(cache_info->virtual_pixel_method);
2536static const void *GetVirtualMetacontentFromCache(
const Image *image)
2539 *magick_restrict cache_info;
2542 id = GetOpenMPThreadId();
2545 *magick_restrict metacontent;
2547 assert(image != (
const Image *) NULL);
2548 assert(image->signature == MagickCoreSignature);
2549 assert(image->cache != (Cache) NULL);
2550 cache_info=(CacheInfo *) image->cache;
2551 assert(cache_info->signature == MagickCoreSignature);
2552 assert(
id < (
int) cache_info->number_threads);
2553 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2554 cache_info->nexus_info[
id]);
2555 return(metacontent);
2584MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2585 NexusInfo *magick_restrict nexus_info)
2588 *magick_restrict cache_info;
2590 assert(cache != (Cache) NULL);
2591 cache_info=(CacheInfo *) cache;
2592 assert(cache_info->signature == MagickCoreSignature);
2593 if (cache_info->storage_class == UndefinedClass)
2594 return((
void *) NULL);
2595 return(nexus_info->metacontent);
2622MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2625 *magick_restrict cache_info;
2628 id = GetOpenMPThreadId();
2631 *magick_restrict metacontent;
2633 assert(image != (
const Image *) NULL);
2634 assert(image->signature == MagickCoreSignature);
2635 assert(image->cache != (Cache) NULL);
2636 cache_info=(CacheInfo *) image->cache;
2637 assert(cache_info->signature == MagickCoreSignature);
2638 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2640 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2642 if (metacontent != (
const void *) NULL)
2643 return(metacontent);
2645 assert(
id < (
int) cache_info->number_threads);
2646 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2647 cache_info->nexus_info[
id]);
2648 return(metacontent);
2691 0, 48, 12, 60, 3, 51, 15, 63,
2692 32, 16, 44, 28, 35, 19, 47, 31,
2693 8, 56, 4, 52, 11, 59, 7, 55,
2694 40, 24, 36, 20, 43, 27, 39, 23,
2695 2, 50, 14, 62, 1, 49, 13, 61,
2696 34, 18, 46, 30, 33, 17, 45, 29,
2697 10, 58, 6, 54, 9, 57, 5, 53,
2698 42, 26, 38, 22, 41, 25, 37, 21
2701static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2706 index=x+DitherMatrix[x & 0x07]-32L;
2709 if (index >= (ssize_t) columns)
2710 return((ssize_t) columns-1L);
2714static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2719 index=y+DitherMatrix[y & 0x07]-32L;
2722 if (index >= (ssize_t) rows)
2723 return((ssize_t) rows-1L);
2727static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2731 if (x >= (ssize_t) columns)
2732 return((ssize_t) (columns-1));
2736static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2740 if (y >= (ssize_t) rows)
2741 return((ssize_t) (rows-1));
2745static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2746 const MagickOffsetType y)
2748 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2749 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2750 return(MagickFalse);
2754static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2756 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2759static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2761 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2764static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2765 const size_t extent)
2770 modulo.quotient=offset;
2774 modulo.quotient=offset/((ssize_t) extent);
2775 modulo.remainder=offset % ((ssize_t) extent);
2777 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2780 modulo.remainder+=((ssize_t) extent);
2785MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2786 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2787 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2788 ExceptionInfo *exception)
2791 *magick_restrict cache_info;
2807 *magick_restrict virtual_nexus;
2810 *magick_restrict pixels,
2812 virtual_pixel[MaxPixelChannels];
2823 *magick_restrict virtual_metacontent;
2828 assert(image != (
const Image *) NULL);
2829 assert(image->signature == MagickCoreSignature);
2830 assert(image->cache != (Cache) NULL);
2831 cache_info=(CacheInfo *) image->cache;
2832 assert(cache_info->signature == MagickCoreSignature);
2833 if (cache_info->type == UndefinedCache)
2834 return((
const Quantum *) NULL);
2835#if defined(MAGICKCORE_OPENCL_SUPPORT)
2836 CopyOpenCLBuffer(cache_info);
2838 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2839 ((image->channels & WriteMaskChannel) != 0) ||
2840 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2841 nexus_info,exception);
2842 if (pixels == (Quantum *) NULL)
2843 return((
const Quantum *) NULL);
2844 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2845 return((
const Quantum *) NULL);
2846 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2847 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2848 return((
const Quantum *) NULL);
2849 offset+=nexus_info->region.x;
2850 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2851 nexus_info->region.width-1L;
2852 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2853 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2854 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2855 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2863 if (nexus_info->authentic_pixel_cache != MagickFalse)
2865 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2866 if (status == MagickFalse)
2867 return((
const Quantum *) NULL);
2868 if (cache_info->metacontent_extent != 0)
2870 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2871 if (status == MagickFalse)
2872 return((
const Quantum *) NULL);
2879 virtual_nexus=nexus_info->virtual_nexus;
2881 s=(
unsigned char *) nexus_info->metacontent;
2882 (void) memset(virtual_pixel,0,cache_info->number_channels*
2883 sizeof(*virtual_pixel));
2884 virtual_metacontent=(
void *) NULL;
2885 switch (virtual_pixel_method)
2887 case BackgroundVirtualPixelMethod:
2888 case BlackVirtualPixelMethod:
2889 case GrayVirtualPixelMethod:
2890 case TransparentVirtualPixelMethod:
2891 case MaskVirtualPixelMethod:
2892 case WhiteVirtualPixelMethod:
2893 case EdgeVirtualPixelMethod:
2894 case CheckerTileVirtualPixelMethod:
2895 case HorizontalTileVirtualPixelMethod:
2896 case VerticalTileVirtualPixelMethod:
2898 if (cache_info->metacontent_extent != 0)
2903 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2904 cache_info->metacontent_extent);
2905 if (virtual_metacontent == (
void *) NULL)
2907 (void) ThrowMagickException(exception,GetMagickModule(),
2908 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2909 return((
const Quantum *) NULL);
2911 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2913 switch (virtual_pixel_method)
2915 case BlackVirtualPixelMethod:
2917 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2918 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2919 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2922 case GrayVirtualPixelMethod:
2924 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2925 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2927 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2930 case TransparentVirtualPixelMethod:
2932 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2933 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2934 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2937 case MaskVirtualPixelMethod:
2938 case WhiteVirtualPixelMethod:
2940 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2941 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2942 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2947 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2949 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2951 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2953 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2955 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2965 for (v=0; v < (ssize_t) rows; v++)
2971 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2972 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2973 y_offset=EdgeY(y_offset,cache_info->rows);
2974 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2980 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2981 x_offset,(ssize_t) columns-u);
2982 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2983 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2993 length=(MagickSizeType) 1;
2994 switch (virtual_pixel_method)
2996 case EdgeVirtualPixelMethod:
2999 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3000 EdgeX(x_offset,cache_info->columns),
3001 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3003 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3006 case RandomVirtualPixelMethod:
3008 if (cache_info->random_info == (RandomInfo *) NULL)
3009 cache_info->random_info=AcquireRandomInfo();
3010 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3011 RandomX(cache_info->random_info,cache_info->columns),
3012 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3013 virtual_nexus,exception);
3014 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3017 case DitherVirtualPixelMethod:
3019 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3020 DitherX(x_offset,cache_info->columns),
3021 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3023 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3026 case TileVirtualPixelMethod:
3028 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3029 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3030 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3031 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3033 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3036 case MirrorVirtualPixelMethod:
3038 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3039 if ((x_modulo.quotient & 0x01) == 1L)
3040 x_modulo.remainder=(ssize_t) cache_info->columns-
3041 x_modulo.remainder-1L;
3042 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3043 if ((y_modulo.quotient & 0x01) == 1L)
3044 y_modulo.remainder=(ssize_t) cache_info->rows-
3045 y_modulo.remainder-1L;
3046 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3047 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3049 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3052 case HorizontalTileEdgeVirtualPixelMethod:
3054 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3055 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3056 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3057 virtual_nexus,exception);
3058 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3061 case VerticalTileEdgeVirtualPixelMethod:
3063 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3064 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3065 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3066 virtual_nexus,exception);
3067 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3070 case BackgroundVirtualPixelMethod:
3071 case BlackVirtualPixelMethod:
3072 case GrayVirtualPixelMethod:
3073 case TransparentVirtualPixelMethod:
3074 case MaskVirtualPixelMethod:
3075 case WhiteVirtualPixelMethod:
3078 r=virtual_metacontent;
3081 case CheckerTileVirtualPixelMethod:
3083 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3084 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3085 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3088 r=virtual_metacontent;
3091 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3092 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3094 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3097 case HorizontalTileVirtualPixelMethod:
3099 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3102 r=virtual_metacontent;
3105 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3106 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3107 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3108 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3110 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3113 case VerticalTileVirtualPixelMethod:
3115 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3118 r=virtual_metacontent;
3121 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3122 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3123 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3124 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3126 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3130 if (p == (
const Quantum *) NULL)
3132 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3134 q+=(ptrdiff_t) cache_info->number_channels;
3135 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3137 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3138 s+=(ptrdiff_t) cache_info->metacontent_extent;
3145 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3146 (
size_t) length,1UL,virtual_nexus,exception);
3147 if (p == (
const Quantum *) NULL)
3149 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3150 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3152 q+=(ptrdiff_t) cache_info->number_channels*length;
3153 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3155 (void) memcpy(s,r,(
size_t) length);
3156 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3159 if (u < (ssize_t) columns)
3165 if (virtual_metacontent != (
void *) NULL)
3166 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3167 if (v < (ssize_t) rows)
3168 return((
const Quantum *) NULL);
3206static const Quantum *GetVirtualPixelCache(
const Image *image,
3207 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3208 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3211 *magick_restrict cache_info;
3214 id = GetOpenMPThreadId();
3219 assert(image != (
const Image *) NULL);
3220 assert(image->signature == MagickCoreSignature);
3221 assert(image->cache != (Cache) NULL);
3222 cache_info=(CacheInfo *) image->cache;
3223 assert(cache_info->signature == MagickCoreSignature);
3224 assert(
id < (
int) cache_info->number_threads);
3225 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3226 cache_info->nexus_info[
id],exception);
3253MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3256 *magick_restrict cache_info;
3259 id = GetOpenMPThreadId();
3261 assert(image != (
const Image *) NULL);
3262 assert(image->signature == MagickCoreSignature);
3263 assert(image->cache != (Cache) NULL);
3264 cache_info=(CacheInfo *) image->cache;
3265 assert(cache_info->signature == MagickCoreSignature);
3266 if (cache_info->methods.get_virtual_pixels_handler != (GetVirtualPixelsHandler) NULL)
3267 return(cache_info->methods.get_virtual_pixels_handler(image));
3268 assert(
id < (
int) cache_info->number_threads);
3269 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3320MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3321 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3322 ExceptionInfo *exception)
3325 *magick_restrict cache_info;
3328 id = GetOpenMPThreadId();
3333 assert(image != (
const Image *) NULL);
3334 assert(image->signature == MagickCoreSignature);
3335 assert(image->cache != (Cache) NULL);
3336 cache_info=(CacheInfo *) image->cache;
3337 assert(cache_info->signature == MagickCoreSignature);
3338 if (cache_info->methods.get_virtual_pixel_handler !=
3339 (GetVirtualPixelHandler) NULL)
3340 return(cache_info->methods.get_virtual_pixel_handler(image,
3341 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3342 assert(
id < (
int) cache_info->number_threads);
3343 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3344 columns,rows,cache_info->nexus_info[
id],exception);
3371static const Quantum *GetVirtualPixelsCache(
const Image *image)
3374 *magick_restrict cache_info;
3377 id = GetOpenMPThreadId();
3379 assert(image != (
const Image *) NULL);
3380 assert(image->signature == MagickCoreSignature);
3381 assert(image->cache != (Cache) NULL);
3382 cache_info=(CacheInfo *) image->cache;
3383 assert(cache_info->signature == MagickCoreSignature);
3384 assert(
id < (
int) cache_info->number_threads);
3385 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3414MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3415 NexusInfo *magick_restrict nexus_info)
3418 *magick_restrict cache_info;
3420 assert(cache != (Cache) NULL);
3421 cache_info=(CacheInfo *) cache;
3422 assert(cache_info->signature == MagickCoreSignature);
3423 if (cache_info->storage_class == UndefinedClass)
3424 return((Quantum *) NULL);
3425 return((
const Quantum *) nexus_info->pixels);
3458static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3459 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3464 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3466 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3467 gamma=MagickSafeReciprocal(gamma);
3468 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3471static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3472 ExceptionInfo *exception)
3475 *magick_restrict cache_info;
3487 if (IsEventLogging() != MagickFalse)
3488 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3489 if ((image->channels & CompositeMaskChannel) == 0)
3491 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3493 cache_info=(CacheInfo *) image->cache;
3494 if (cache_info == (Cache) NULL)
3495 return(MagickFalse);
3496 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3497 nexus_info->region.width,nexus_info->region.height,
3498 nexus_info->virtual_nexus,exception);
3499 q=nexus_info->pixels;
3500 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3501 return(MagickFalse);
3502 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3507 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3515 alpha=(double) GetPixelCompositeMask(image,p);
3516 for (i=0; i < (ssize_t) image->number_channels; i++)
3518 PixelChannel channel = GetPixelChannelChannel(image,i);
3519 PixelTrait traits = GetPixelChannelTraits(image,channel);
3520 if ((traits & UpdatePixelTrait) == 0)
3522 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3524 p+=(ptrdiff_t) GetPixelChannels(image);
3525 q+=(ptrdiff_t) GetPixelChannels(image);
3562static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3563 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3568 if ((count == 0) || (quantum == 0))
3570 length=count*quantum;
3571 if (quantum != (length/count))
3578 return(MagickFalse);
3581static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3590 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3592 if (*cache_info->cache_filename ==
'\0')
3593 file=AcquireUniqueFileResource(cache_info->cache_filename);
3599 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3604 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3605 O_BINARY | O_EXCL,S_MODE);
3607 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3613 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3616 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3621 return(MagickFalse);
3622 (void) AcquireMagickResource(FileResource,1);
3623 if (cache_info->file != -1)
3624 (void) ClosePixelCacheOnDisk(cache_info);
3625 cache_info->file=file;
3626 cache_info->disk_mode=mode;
3630static inline MagickOffsetType WritePixelCacheRegion(
3631 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3632 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3640#if !defined(MAGICKCORE_HAVE_PWRITE)
3641 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3642 return((MagickOffsetType) -1);
3644 for (i=0; i < (MagickOffsetType) length; i+=count)
3646#if !defined(MAGICKCORE_HAVE_PWRITE)
3647 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3648 (MagickSizeType) i,MagickMaxBufferExtent));
3650 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3651 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3663static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3666 *magick_restrict cache_info;
3671 cache_info=(CacheInfo *) image->cache;
3672 if (cache_info->debug != MagickFalse)
3675 format[MagickPathExtent],
3676 message[MagickPathExtent];
3678 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3679 (void) FormatLocaleString(message,MagickPathExtent,
3680 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3681 cache_info->cache_filename,cache_info->file,format);
3682 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3684 if (length != (MagickSizeType) ((MagickOffsetType) length))
3685 return(MagickFalse);
3686 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3688 return(MagickFalse);
3689 if ((MagickSizeType) offset < length)
3695 extent=(MagickOffsetType) length-1;
3696 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3699 return(MagickFalse);
3700#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3701 if (cache_info->synchronize != MagickFalse)
3702 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3703 return(MagickFalse);
3706 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3708 return(MagickFalse);
3712static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3713 ExceptionInfo *exception)
3716 *magick_restrict cache_info,
3720 format[MagickPathExtent],
3721 message[MagickPathExtent];
3738 assert(image != (
const Image *) NULL);
3739 assert(image->signature == MagickCoreSignature);
3740 assert(image->cache != (Cache) NULL);
3741 if (IsEventLogging() != MagickFalse)
3742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3743 if (cache_anonymous_memory < 0)
3751 cache_anonymous_memory=0;
3752 value=GetPolicyValue(
"pixel-cache-memory");
3753 if (value == (
char *) NULL)
3754 value=GetPolicyValue(
"cache:memory-map");
3755 if (LocaleCompare(value,
"anonymous") == 0)
3757#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3758 cache_anonymous_memory=1;
3760 (void) ThrowMagickException(exception,GetMagickModule(),
3761 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3762 "`%s' (policy requires anonymous memory mapping)",image->filename);
3765 value=DestroyString(value);
3767 if ((image->columns == 0) || (image->rows == 0))
3768 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3769 cache_info=(CacheInfo *) image->cache;
3770 assert(cache_info->signature == MagickCoreSignature);
3771 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3772 ((MagickSizeType) image->rows > cache_info->height_limit))
3774 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3775 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3776 image->filename, (
double) image->columns, (
double) image->rows,
3777 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3778 return(MagickFalse);
3780 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3782 length=GetImageListLength(image);
3783 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3784 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3787 source_info=(*cache_info);
3788 source_info.file=(-1);
3789 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3790 image->filename,(
double) image->scene);
3791 cache_info->storage_class=image->storage_class;
3792 cache_info->colorspace=image->colorspace;
3793 cache_info->alpha_trait=image->alpha_trait;
3794 cache_info->channels=image->channels;
3795 cache_info->rows=image->rows;
3796 cache_info->columns=image->columns;
3797 status=ResetPixelChannelMap(image,exception);
3798 if (status == MagickFalse)
3799 return(MagickFalse);
3800 cache_info->number_channels=GetPixelChannels(image);
3801 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3802 sizeof(*image->channel_map));
3803 cache_info->metacontent_extent=image->metacontent_extent;
3804 cache_info->mode=mode;
3805 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3806 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3807 if (image->metacontent_extent != 0)
3808 packet_size+=cache_info->metacontent_extent;
3809 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3811 cache_info->storage_class=UndefinedClass;
3812 cache_info->length=0;
3813 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3816 columns=(size_t) (length/cache_info->rows/packet_size);
3817 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3818 ((ssize_t) cache_info->rows < 0))
3820 cache_info->storage_class=UndefinedClass;
3821 cache_info->length=0;
3822 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3825 cache_info->length=length;
3826 if (image->ping != MagickFalse)
3828 cache_info->type=PingCache;
3831 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3832 cache_info->columns*cache_info->rows);
3833 if (cache_info->mode == PersistMode)
3835 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3836 cache_info->metacontent_extent);
3837 if ((status != MagickFalse) &&
3838 (length == (MagickSizeType) ((
size_t) length)) &&
3839 ((cache_info->type == UndefinedCache) ||
3840 (cache_info->type == MemoryCache)))
3842 status=AcquireMagickResource(MemoryResource,cache_info->length);
3843 if (status != MagickFalse)
3846 if (cache_anonymous_memory <= 0)
3848 cache_info->mapped=MagickFalse;
3849 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3850 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3854 cache_info->mapped=MagickTrue;
3855 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3856 cache_info->length);
3858 if (cache_info->pixels == (Quantum *) NULL)
3860 cache_info->mapped=source_info.mapped;
3861 cache_info->pixels=source_info.pixels;
3868 cache_info->type=MemoryCache;
3869 cache_info->metacontent=(
void *) NULL;
3870 if (cache_info->metacontent_extent != 0)
3871 cache_info->metacontent=(
void *) (cache_info->pixels+
3872 cache_info->number_channels*number_pixels);
3873 if ((source_info.storage_class != UndefinedClass) &&
3876 status=ClonePixelCacheRepository(cache_info,&source_info,
3878 RelinquishPixelCachePixels(&source_info);
3880 if (cache_info->debug != MagickFalse)
3882 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3883 MagickPathExtent,format);
3884 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3886 (void) FormatLocaleString(message,MagickPathExtent,
3887 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3888 cache_info->filename,cache_info->mapped != MagickFalse ?
3889 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3890 (
double) cache_info->rows,(
double)
3891 cache_info->number_channels,format);
3892 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3895 cache_info->storage_class=image->storage_class;
3898 if ((source_info.storage_class != UndefinedClass) &&
3900 RelinquishPixelCachePixels(&source_info);
3901 cache_info->type=UndefinedCache;
3902 return(MagickFalse);
3908 status=AcquireMagickResource(DiskResource,cache_info->length);
3909 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3911 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3919 server_info=AcquireDistributeCacheInfo(exception);
3920 if (server_info != (DistributeCacheInfo *) NULL)
3922 status=OpenDistributePixelCache(server_info,image);
3923 if (status == MagickFalse)
3925 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3926 GetDistributeCacheHostname(server_info));
3927 server_info=DestroyDistributeCacheInfo(server_info);
3935 cache_info->type=DistributedCache;
3936 cache_info->server_info=server_info;
3937 (void) FormatLocaleString(cache_info->cache_filename,
3938 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3939 (DistributeCacheInfo *) cache_info->server_info),
3940 GetDistributeCachePort((DistributeCacheInfo *)
3941 cache_info->server_info));
3942 if ((source_info.storage_class != UndefinedClass) &&
3945 status=ClonePixelCacheRepository(cache_info,&source_info,
3947 RelinquishPixelCachePixels(&source_info);
3949 if (cache_info->debug != MagickFalse)
3951 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3952 MagickPathExtent,format);
3953 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3955 (void) FormatLocaleString(message,MagickPathExtent,
3956 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3957 cache_info->filename,cache_info->cache_filename,
3958 GetDistributeCacheFile((DistributeCacheInfo *)
3959 cache_info->server_info),type,(
double) cache_info->columns,
3960 (
double) cache_info->rows,(
double)
3961 cache_info->number_channels,format);
3962 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3967 if ((source_info.storage_class != UndefinedClass) &&
3969 RelinquishPixelCachePixels(&source_info);
3970 cache_info->type=UndefinedCache;
3971 return(MagickFalse);
3976 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3977 RelinquishPixelCachePixels(&source_info);
3978 cache_info->type=UndefinedCache;
3979 (void) memset(image->channel_map,0,MaxPixelChannels*
3980 sizeof(*image->channel_map));
3981 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3982 "CacheResourcesExhausted",
"`%s'",image->filename);
3983 return(MagickFalse);
3988 if (status == MagickFalse)
3990 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3991 RelinquishPixelCachePixels(&source_info);
3992 cache_info->type=UndefinedCache;
3993 (void) memset(image->channel_map,0,MaxPixelChannels*
3994 sizeof(*image->channel_map));
3995 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3996 "CacheResourcesExhausted",
"`%s'",image->filename);
3997 return(MagickFalse);
3999 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
4000 (cache_info->mode != PersistMode))
4002 (void) ClosePixelCacheOnDisk(cache_info);
4003 *cache_info->cache_filename=
'\0';
4005 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4007 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4008 RelinquishPixelCachePixels(&source_info);
4009 cache_info->type=UndefinedCache;
4010 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4012 return(MagickFalse);
4014 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4015 cache_info->length);
4016 if (status == MagickFalse)
4018 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4019 RelinquishPixelCachePixels(&source_info);
4020 cache_info->type=UndefinedCache;
4021 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4023 return(MagickFalse);
4025 cache_info->type=DiskCache;
4026 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4027 cache_info->metacontent_extent);
4028 if (length == (MagickSizeType) ((
size_t) length))
4030 status=AcquireMagickResource(MapResource,cache_info->length);
4031 if (status != MagickFalse)
4033 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4034 cache_info->offset,(
size_t) cache_info->length);
4035 if (cache_info->pixels == (Quantum *) NULL)
4037 cache_info->mapped=source_info.mapped;
4038 cache_info->pixels=source_info.pixels;
4039 RelinquishMagickResource(MapResource,cache_info->length);
4046 (void) ClosePixelCacheOnDisk(cache_info);
4047 cache_info->type=MapCache;
4048 cache_info->mapped=MagickTrue;
4049 cache_info->metacontent=(
void *) NULL;
4050 if (cache_info->metacontent_extent != 0)
4051 cache_info->metacontent=(
void *) (cache_info->pixels+
4052 cache_info->number_channels*number_pixels);
4053 if ((source_info.storage_class != UndefinedClass) &&
4056 status=ClonePixelCacheRepository(cache_info,&source_info,
4058 RelinquishPixelCachePixels(&source_info);
4060 if (cache_info->debug != MagickFalse)
4062 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4063 MagickPathExtent,format);
4064 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4066 (void) FormatLocaleString(message,MagickPathExtent,
4067 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4068 cache_info->filename,cache_info->cache_filename,
4069 cache_info->file,type,(
double) cache_info->columns,
4070 (
double) cache_info->rows,(
double)
4071 cache_info->number_channels,format);
4072 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4077 if ((source_info.storage_class != UndefinedClass) &&
4079 RelinquishPixelCachePixels(&source_info);
4080 cache_info->type=UndefinedCache;
4081 return(MagickFalse);
4088 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4090 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4091 RelinquishPixelCachePixels(&source_info);
4093 if (cache_info->debug != MagickFalse)
4095 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4096 MagickPathExtent,format);
4097 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4099 (void) FormatLocaleString(message,MagickPathExtent,
4100 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4101 cache_info->cache_filename,cache_info->file,type,(
double)
4102 cache_info->columns,(
double) cache_info->rows,(
double)
4103 cache_info->number_channels,format);
4104 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4108 cache_info->type=UndefinedCache;
4109 return(MagickFalse);
4151MagickExport MagickBooleanType PersistPixelCache(Image *image,
4152 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4153 ExceptionInfo *exception)
4156 *magick_restrict cache_info,
4157 *magick_restrict clone_info;
4165 assert(image != (Image *) NULL);
4166 assert(image->signature == MagickCoreSignature);
4167 if (IsEventLogging() != MagickFalse)
4168 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4169 assert(image->cache != (
void *) NULL);
4170 assert(filename != (
const char *) NULL);
4171 assert(offset != (MagickOffsetType *) NULL);
4172 page_size=GetMagickPageSize();
4173 cache_info=(CacheInfo *) image->cache;
4174 assert(cache_info->signature == MagickCoreSignature);
4175#if defined(MAGICKCORE_OPENCL_SUPPORT)
4176 CopyOpenCLBuffer(cache_info);
4178 if (attach != MagickFalse)
4183 if (cache_info->debug != MagickFalse)
4184 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4185 "attach persistent cache");
4186 (void) CopyMagickString(cache_info->cache_filename,filename,
4188 cache_info->type=MapCache;
4189 cache_info->offset=(*offset);
4190 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4191 return(MagickFalse);
4192 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4193 ((MagickOffsetType) cache_info->length % page_size));
4199 status=AcquireMagickResource(DiskResource,cache_info->length);
4200 if (status == MagickFalse)
4202 cache_info->type=UndefinedCache;
4203 (void) memset(image->channel_map,0,MaxPixelChannels*
4204 sizeof(*image->channel_map));
4205 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4206 "CacheResourcesExhausted",
"`%s'",image->filename);
4207 return(MagickFalse);
4209 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4210 clone_info->type=DiskCache;
4211 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4212 clone_info->file=(-1);
4213 clone_info->storage_class=cache_info->storage_class;
4214 clone_info->colorspace=cache_info->colorspace;
4215 clone_info->alpha_trait=cache_info->alpha_trait;
4216 clone_info->channels=cache_info->channels;
4217 clone_info->columns=cache_info->columns;
4218 clone_info->rows=cache_info->rows;
4219 clone_info->number_channels=cache_info->number_channels;
4220 clone_info->metacontent_extent=cache_info->metacontent_extent;
4221 clone_info->mode=PersistMode;
4222 clone_info->length=cache_info->length;
4223 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4224 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4225 clone_info->offset=(*offset);
4226 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4227 if (status != MagickFalse)
4228 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4229 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4230 ((MagickOffsetType) cache_info->length % page_size));
4231 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4273MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4274 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4275 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4278 *magick_restrict cache_info;
4287 *magick_restrict pixels;
4292 assert(image != (
const Image *) NULL);
4293 assert(image->signature == MagickCoreSignature);
4294 assert(image->cache != (Cache) NULL);
4295 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4296 if (cache_info == (Cache) NULL)
4297 return((Quantum *) NULL);
4298 assert(cache_info->signature == MagickCoreSignature);
4299 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4300 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4301 (y >= (ssize_t) cache_info->rows))
4303 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4304 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4305 return((Quantum *) NULL);
4307 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4308 return((Quantum *) NULL);
4309 offset=y*(MagickOffsetType) cache_info->columns+x;
4311 return((Quantum *) NULL);
4312 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4313 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4314 (MagickOffsetType) columns-1;
4315 if ((MagickSizeType) offset >= number_pixels)
4316 return((Quantum *) NULL);
4320 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4321 ((image->channels & WriteMaskChannel) != 0) ||
4322 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4323 nexus_info,exception);
4360static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4361 const ssize_t y,
const size_t columns,
const size_t rows,
4362 ExceptionInfo *exception)
4365 *magick_restrict cache_info;
4368 id = GetOpenMPThreadId();
4371 *magick_restrict pixels;
4373 assert(image != (
const Image *) NULL);
4374 assert(image->signature == MagickCoreSignature);
4375 assert(image->cache != (Cache) NULL);
4376 cache_info=(CacheInfo *) image->cache;
4377 assert(cache_info->signature == MagickCoreSignature);
4378 assert(
id < (
int) cache_info->number_threads);
4379 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4380 cache_info->nexus_info[
id],exception);
4440MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4441 const ssize_t y,
const size_t columns,
const size_t rows,
4442 ExceptionInfo *exception)
4445 *magick_restrict cache_info;
4448 id = GetOpenMPThreadId();
4451 *magick_restrict pixels;
4453 assert(image != (Image *) NULL);
4454 assert(image->signature == MagickCoreSignature);
4455 assert(image->cache != (Cache) NULL);
4456 cache_info=(CacheInfo *) image->cache;
4457 assert(cache_info->signature == MagickCoreSignature);
4458 if (cache_info->methods.queue_authentic_pixels_handler !=
4459 (QueueAuthenticPixelsHandler) NULL)
4461 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4462 columns,rows,exception);
4465 assert(
id < (
int) cache_info->number_threads);
4466 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4467 cache_info->nexus_info[
id],exception);
4500static inline MagickOffsetType ReadPixelCacheRegion(
4501 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4502 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4510#if !defined(MAGICKCORE_HAVE_PREAD)
4511 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4512 return((MagickOffsetType) -1);
4514 for (i=0; i < (MagickOffsetType) length; i+=count)
4516#if !defined(MAGICKCORE_HAVE_PREAD)
4517 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4518 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4520 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4521 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4533static MagickBooleanType ReadPixelCacheMetacontent(
4534 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4535 ExceptionInfo *exception)
4554 if (cache_info->metacontent_extent == 0)
4555 return(MagickFalse);
4556 if (nexus_info->authentic_pixel_cache != MagickFalse)
4558 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4559 return(MagickFalse);
4560 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4561 nexus_info->region.x;
4562 length=(MagickSizeType) nexus_info->region.width*
4563 cache_info->metacontent_extent;
4564 extent=length*nexus_info->region.height;
4565 rows=nexus_info->region.height;
4567 q=(
unsigned char *) nexus_info->metacontent;
4568 switch (cache_info->type)
4579 if ((cache_info->columns == nexus_info->region.width) &&
4580 (extent == (MagickSizeType) ((
size_t) extent)))
4585 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4586 cache_info->metacontent_extent;
4587 for (y=0; y < (ssize_t) rows; y++)
4589 (void) memcpy(q,p,(
size_t) length);
4590 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4591 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4600 LockSemaphoreInfo(cache_info->file_semaphore);
4601 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4603 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4604 cache_info->cache_filename);
4605 UnlockSemaphoreInfo(cache_info->file_semaphore);
4606 return(MagickFalse);
4608 if ((cache_info->columns == nexus_info->region.width) &&
4609 (extent <= MagickMaxBufferExtent))
4614 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4615 for (y=0; y < (ssize_t) rows; y++)
4617 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4618 (MagickOffsetType) extent*(MagickOffsetType)
4619 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4620 (MagickOffsetType) cache_info->metacontent_extent,length,
4621 (
unsigned char *) q);
4622 if (count != (MagickOffsetType) length)
4624 offset+=(MagickOffsetType) cache_info->columns;
4625 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4627 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4628 (void) ClosePixelCacheOnDisk(cache_info);
4629 UnlockSemaphoreInfo(cache_info->file_semaphore);
4632 case DistributedCache:
4640 LockSemaphoreInfo(cache_info->file_semaphore);
4641 region=nexus_info->region;
4642 if ((cache_info->columns != nexus_info->region.width) ||
4643 (extent > MagickMaxBufferExtent))
4650 for (y=0; y < (ssize_t) rows; y++)
4652 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4653 cache_info->server_info,®ion,length,(
unsigned char *) q);
4654 if (count != (MagickOffsetType) length)
4656 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4659 UnlockSemaphoreInfo(cache_info->file_semaphore);
4665 if (y < (ssize_t) rows)
4667 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4668 cache_info->cache_filename);
4669 return(MagickFalse);
4671 if ((cache_info->debug != MagickFalse) &&
4672 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4673 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4674 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4675 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4676 nexus_info->region.x,(
double) nexus_info->region.y);
4708static MagickBooleanType ReadPixelCachePixels(
4709 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4710 ExceptionInfo *exception)
4730 if (nexus_info->authentic_pixel_cache != MagickFalse)
4732 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4733 return(MagickFalse);
4734 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4735 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4736 return(MagickFalse);
4737 offset+=nexus_info->region.x;
4738 number_channels=cache_info->number_channels;
4739 length=(MagickSizeType) number_channels*nexus_info->region.width*
4741 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4742 return(MagickFalse);
4743 rows=nexus_info->region.height;
4745 if ((extent == 0) || ((extent/length) != rows))
4746 return(MagickFalse);
4748 q=nexus_info->pixels;
4749 switch (cache_info->type)
4760 if ((cache_info->columns == nexus_info->region.width) &&
4761 (extent == (MagickSizeType) ((
size_t) extent)))
4766 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4768 for (y=0; y < (ssize_t) rows; y++)
4770 (void) memcpy(q,p,(
size_t) length);
4771 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4772 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4781 LockSemaphoreInfo(cache_info->file_semaphore);
4782 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4784 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4785 cache_info->cache_filename);
4786 UnlockSemaphoreInfo(cache_info->file_semaphore);
4787 return(MagickFalse);
4789 if ((cache_info->columns == nexus_info->region.width) &&
4790 (extent <= MagickMaxBufferExtent))
4795 for (y=0; y < (ssize_t) rows; y++)
4797 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4798 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4799 sizeof(*q),length,(
unsigned char *) q);
4800 if (count != (MagickOffsetType) length)
4802 offset+=(MagickOffsetType) cache_info->columns;
4803 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4805 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4806 (void) ClosePixelCacheOnDisk(cache_info);
4807 UnlockSemaphoreInfo(cache_info->file_semaphore);
4810 case DistributedCache:
4818 LockSemaphoreInfo(cache_info->file_semaphore);
4819 region=nexus_info->region;
4820 if ((cache_info->columns != nexus_info->region.width) ||
4821 (extent > MagickMaxBufferExtent))
4828 for (y=0; y < (ssize_t) rows; y++)
4830 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4831 cache_info->server_info,®ion,length,(
unsigned char *) q);
4832 if (count != (MagickOffsetType) length)
4834 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4837 UnlockSemaphoreInfo(cache_info->file_semaphore);
4843 if (y < (ssize_t) rows)
4845 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4846 cache_info->cache_filename);
4847 return(MagickFalse);
4849 if ((cache_info->debug != MagickFalse) &&
4850 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4851 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4852 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4853 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4854 nexus_info->region.x,(
double) nexus_info->region.y);
4881MagickPrivate Cache ReferencePixelCache(Cache cache)
4884 *magick_restrict cache_info;
4886 assert(cache != (Cache *) NULL);
4887 cache_info=(CacheInfo *) cache;
4888 assert(cache_info->signature == MagickCoreSignature);
4889 LockSemaphoreInfo(cache_info->semaphore);
4890 cache_info->reference_count++;
4891 UnlockSemaphoreInfo(cache_info->semaphore);
4917MagickPrivate
void ResetPixelCacheChannels(Image *image)
4920 *magick_restrict cache_info;
4922 assert(image != (
const Image *) NULL);
4923 assert(image->signature == MagickCoreSignature);
4924 assert(image->cache != (Cache) NULL);
4925 cache_info=(CacheInfo *) image->cache;
4926 assert(cache_info->signature == MagickCoreSignature);
4927 cache_info->number_channels=GetPixelChannels(image);
4948MagickPrivate
void ResetCacheAnonymousMemory(
void)
4950 cache_anonymous_memory=0;
4982MagickExport MagickBooleanType ReshapePixelCache(Image *image,
4983 const size_t columns,
const size_t rows,ExceptionInfo *exception)
4991 assert(image != (Image *) NULL);
4992 assert(image->signature == MagickCoreSignature);
4993 if (IsEventLogging() != MagickFalse)
4994 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4995 assert(image->cache != (
void *) NULL);
4996 extent=(MagickSizeType) columns*rows;
4997 if (extent > ((MagickSizeType) image->columns*image->rows))
4998 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
5000 image->columns=columns;
5002 cache_info=(CacheInfo *) image->cache;
5003 cache_info->columns=columns;
5004 cache_info->rows=rows;
5005 return(SyncImagePixelCache(image,exception));
5032MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5035 *magick_restrict cache_info;
5037 GetOneAuthenticPixelFromHandler
5038 get_one_authentic_pixel_from_handler;
5040 GetOneVirtualPixelFromHandler
5041 get_one_virtual_pixel_from_handler;
5046 assert(cache != (Cache) NULL);
5047 assert(cache_methods != (CacheMethods *) NULL);
5048 cache_info=(CacheInfo *) cache;
5049 assert(cache_info->signature == MagickCoreSignature);
5050 if (IsEventLogging() != MagickFalse)
5051 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5052 cache_info->filename);
5053 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5054 cache_info->methods.get_virtual_pixel_handler=
5055 cache_methods->get_virtual_pixel_handler;
5056 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5057 cache_info->methods.destroy_pixel_handler=
5058 cache_methods->destroy_pixel_handler;
5059 if (cache_methods->get_virtual_metacontent_from_handler !=
5060 (GetVirtualMetacontentFromHandler) NULL)
5061 cache_info->methods.get_virtual_metacontent_from_handler=
5062 cache_methods->get_virtual_metacontent_from_handler;
5063 if (cache_methods->get_authentic_pixels_handler !=
5064 (GetAuthenticPixelsHandler) NULL)
5065 cache_info->methods.get_authentic_pixels_handler=
5066 cache_methods->get_authentic_pixels_handler;
5067 if (cache_methods->queue_authentic_pixels_handler !=
5068 (QueueAuthenticPixelsHandler) NULL)
5069 cache_info->methods.queue_authentic_pixels_handler=
5070 cache_methods->queue_authentic_pixels_handler;
5071 if (cache_methods->sync_authentic_pixels_handler !=
5072 (SyncAuthenticPixelsHandler) NULL)
5073 cache_info->methods.sync_authentic_pixels_handler=
5074 cache_methods->sync_authentic_pixels_handler;
5075 if (cache_methods->get_authentic_pixels_from_handler !=
5076 (GetAuthenticPixelsFromHandler) NULL)
5077 cache_info->methods.get_authentic_pixels_from_handler=
5078 cache_methods->get_authentic_pixels_from_handler;
5079 if (cache_methods->get_authentic_metacontent_from_handler !=
5080 (GetAuthenticMetacontentFromHandler) NULL)
5081 cache_info->methods.get_authentic_metacontent_from_handler=
5082 cache_methods->get_authentic_metacontent_from_handler;
5083 get_one_virtual_pixel_from_handler=
5084 cache_info->methods.get_one_virtual_pixel_from_handler;
5085 if (get_one_virtual_pixel_from_handler !=
5086 (GetOneVirtualPixelFromHandler) NULL)
5087 cache_info->methods.get_one_virtual_pixel_from_handler=
5088 cache_methods->get_one_virtual_pixel_from_handler;
5089 get_one_authentic_pixel_from_handler=
5090 cache_methods->get_one_authentic_pixel_from_handler;
5091 if (get_one_authentic_pixel_from_handler !=
5092 (GetOneAuthenticPixelFromHandler) NULL)
5093 cache_info->methods.get_one_authentic_pixel_from_handler=
5094 cache_methods->get_one_authentic_pixel_from_handler;
5135static inline MagickBooleanType AcquireCacheNexusPixels(
5136 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5137 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5139 if (length != (MagickSizeType) ((
size_t) length))
5141 (void) ThrowMagickException(exception,GetMagickModule(),
5142 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5143 cache_info->filename);
5144 return(MagickFalse);
5146 nexus_info->length=0;
5147 nexus_info->mapped=MagickFalse;
5148 if (cache_anonymous_memory <= 0)
5150 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5152 if (nexus_info->cache != (Quantum *) NULL)
5153 (void) memset(nexus_info->cache,0,(
size_t) length);
5157 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5158 if (nexus_info->cache != (Quantum *) NULL)
5159 nexus_info->mapped=MagickTrue;
5161 if (nexus_info->cache == (Quantum *) NULL)
5163 (void) ThrowMagickException(exception,GetMagickModule(),
5164 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5165 cache_info->filename);
5166 return(MagickFalse);
5168 nexus_info->length=length;
5172static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5175 if (nexus_info->length < CACHE_LINE_SIZE)
5177 if (mode == ReadMode)
5179 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5183 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5186static Quantum *SetPixelCacheNexusPixels(
5187 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5188 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5189 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5190 ExceptionInfo *exception)
5199 assert(cache_info != (
const CacheInfo *) NULL);
5200 assert(cache_info->signature == MagickCoreSignature);
5201 if (cache_info->type == UndefinedCache)
5202 return((Quantum *) NULL);
5203 assert(nexus_info->signature == MagickCoreSignature);
5204 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5205 if ((width == 0) || (height == 0))
5207 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5208 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5209 return((Quantum *) NULL);
5211 if (((MagickSizeType) width > cache_info->width_limit) ||
5212 ((MagickSizeType) height > cache_info->height_limit))
5214 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5215 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5216 return((Quantum *) NULL);
5218 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5219 (IsValidPixelOffset(y,height) == MagickFalse))
5221 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5222 "InvalidPixel",
"`%s'",cache_info->filename);
5223 return((Quantum *) NULL);
5225 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5226 (buffered == MagickFalse))
5228 if (((x >= 0) && (y >= 0) &&
5229 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5230 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5231 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5239 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5240 return((Quantum *) NULL);
5241 offset=y*(MagickOffsetType) cache_info->columns+x;
5242 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5243 cache_info->number_channels*offset;
5244 nexus_info->metacontent=(
void *) NULL;
5245 if (cache_info->metacontent_extent != 0)
5246 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5247 offset*(MagickOffsetType) cache_info->metacontent_extent;
5248 nexus_info->region.width=width;
5249 nexus_info->region.height=height;
5250 nexus_info->region.x=x;
5251 nexus_info->region.y=y;
5252 nexus_info->authentic_pixel_cache=MagickTrue;
5253 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5254 return(nexus_info->pixels);
5260 number_pixels=(MagickSizeType) width*height;
5261 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5262 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5263 if (cache_info->metacontent_extent != 0)
5264 length+=number_pixels*cache_info->metacontent_extent;
5266 if (nexus_info->cache == (Quantum *) NULL)
5267 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5269 if (nexus_info->length < length)
5271 RelinquishCacheNexusPixels(nexus_info);
5272 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5274 if (status == MagickFalse)
5275 return((Quantum *) NULL);
5276 nexus_info->pixels=nexus_info->cache;
5277 nexus_info->metacontent=(
void *) NULL;
5278 if (cache_info->metacontent_extent != 0)
5279 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5280 cache_info->number_channels*number_pixels);
5281 nexus_info->region.width=width;
5282 nexus_info->region.height=height;
5283 nexus_info->region.x=x;
5284 nexus_info->region.y=y;
5285 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5286 MagickTrue : MagickFalse;
5287 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5288 return(nexus_info->pixels);
5321static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5322 ExceptionInfo *exception)
5325 *magick_restrict image_view;
5333 assert(image != (Image *) NULL);
5334 assert(image->signature == MagickCoreSignature);
5335 if (IsEventLogging() != MagickFalse)
5336 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5337 assert(image->cache != (Cache) NULL);
5338 image->alpha_trait=BlendPixelTrait;
5340 image_view=AcquireVirtualCacheView(image,exception);
5341#if defined(MAGICKCORE_OPENMP_SUPPORT)
5342 #pragma omp parallel for schedule(static) shared(status) \
5343 magick_number_threads(image,image,image->rows,2)
5345 for (y=0; y < (ssize_t) image->rows; y++)
5353 if (status == MagickFalse)
5355 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5356 if (q == (Quantum *) NULL)
5361 for (x=0; x < (ssize_t) image->columns; x++)
5363 SetPixelAlpha(image,alpha,q);
5364 q+=(ptrdiff_t) GetPixelChannels(image);
5366 status=SyncCacheViewAuthenticPixels(image_view,exception);
5368 image_view=DestroyCacheView(image_view);
5372MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5373 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5376 *magick_restrict cache_info;
5381 assert(image != (Image *) NULL);
5382 assert(image->signature == MagickCoreSignature);
5383 if (IsEventLogging() != MagickFalse)
5384 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5385 assert(image->cache != (Cache) NULL);
5386 cache_info=(CacheInfo *) image->cache;
5387 assert(cache_info->signature == MagickCoreSignature);
5388 method=cache_info->virtual_pixel_method;
5389 cache_info->virtual_pixel_method=virtual_pixel_method;
5390 if ((image->columns != 0) && (image->rows != 0))
5391 switch (virtual_pixel_method)
5393 case BackgroundVirtualPixelMethod:
5395 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5396 ((image->alpha_trait & BlendPixelTrait) == 0))
5397 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5398 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5399 (IsGrayColorspace(image->colorspace) != MagickFalse))
5400 (void) SetImageColorspace(image,sRGBColorspace,exception);
5403 case TransparentVirtualPixelMethod:
5405 if ((image->alpha_trait & BlendPixelTrait) == 0)
5406 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5415#if defined(MAGICKCORE_OPENCL_SUPPORT)
5440static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5442 assert(cache_info != (CacheInfo *) NULL);
5443 assert(cache_info->signature == MagickCoreSignature);
5444 if ((cache_info->type != MemoryCache) ||
5445 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5450 LockSemaphoreInfo(cache_info->semaphore);
5451 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5452 UnlockSemaphoreInfo(cache_info->semaphore);
5455MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5458 *magick_restrict cache_info;
5460 assert(image != (
const Image *) NULL);
5461 cache_info=(CacheInfo *) image->cache;
5462 CopyOpenCLBuffer(cache_info);
5495MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5496 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5499 *magick_restrict cache_info;
5507 assert(image != (Image *) NULL);
5508 assert(image->signature == MagickCoreSignature);
5509 if (image->cache == (Cache) NULL)
5510 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5511 cache_info=(CacheInfo *) image->cache;
5512 assert(cache_info->signature == MagickCoreSignature);
5513 if (cache_info->type == UndefinedCache)
5514 return(MagickFalse);
5515 if ((image->mask_trait & UpdatePixelTrait) != 0)
5517 if (((image->channels & WriteMaskChannel) != 0) &&
5518 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5519 return(MagickFalse);
5520 if (((image->channels & CompositeMaskChannel) != 0) &&
5521 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5522 return(MagickFalse);
5524 if (nexus_info->authentic_pixel_cache != MagickFalse)
5526 if (image->taint == MagickFalse)
5527 image->taint=MagickTrue;
5530 assert(cache_info->signature == MagickCoreSignature);
5531 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5532 if ((cache_info->metacontent_extent != 0) &&
5533 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5534 return(MagickFalse);
5535 if ((status != MagickFalse) && (image->taint == MagickFalse))
5536 image->taint=MagickTrue;
5567static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5568 ExceptionInfo *exception)
5571 *magick_restrict cache_info;
5574 id = GetOpenMPThreadId();
5579 assert(image != (Image *) NULL);
5580 assert(image->signature == MagickCoreSignature);
5581 assert(image->cache != (Cache) NULL);
5582 cache_info=(CacheInfo *) image->cache;
5583 assert(cache_info->signature == MagickCoreSignature);
5584 assert(
id < (
int) cache_info->number_threads);
5585 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5617MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5618 ExceptionInfo *exception)
5621 *magick_restrict cache_info;
5624 id = GetOpenMPThreadId();
5629 assert(image != (Image *) NULL);
5630 assert(image->signature == MagickCoreSignature);
5631 assert(image->cache != (Cache) NULL);
5632 cache_info=(CacheInfo *) image->cache;
5633 assert(cache_info->signature == MagickCoreSignature);
5634 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5636 status=cache_info->methods.sync_authentic_pixels_handler(image,
5640 assert(
id < (
int) cache_info->number_threads);
5641 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5673MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5674 ExceptionInfo *exception)
5677 *magick_restrict cache_info;
5679 assert(image != (Image *) NULL);
5680 assert(exception != (ExceptionInfo *) NULL);
5681 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5682 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5713static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5714 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5733 if (cache_info->metacontent_extent == 0)
5734 return(MagickFalse);
5735 if (nexus_info->authentic_pixel_cache != MagickFalse)
5737 if (nexus_info->metacontent == (
unsigned char *) NULL)
5738 return(MagickFalse);
5739 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5740 return(MagickFalse);
5741 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5742 nexus_info->region.x;
5743 length=(MagickSizeType) nexus_info->region.width*
5744 cache_info->metacontent_extent;
5745 extent=(MagickSizeType) length*nexus_info->region.height;
5746 rows=nexus_info->region.height;
5748 p=(
unsigned char *) nexus_info->metacontent;
5749 switch (cache_info->type)
5760 if ((cache_info->columns == nexus_info->region.width) &&
5761 (extent == (MagickSizeType) ((
size_t) extent)))
5766 q=(
unsigned char *) cache_info->metacontent+offset*
5767 (MagickOffsetType) cache_info->metacontent_extent;
5768 for (y=0; y < (ssize_t) rows; y++)
5770 (void) memcpy(q,p,(
size_t) length);
5771 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5772 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5781 LockSemaphoreInfo(cache_info->file_semaphore);
5782 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5784 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5785 cache_info->cache_filename);
5786 UnlockSemaphoreInfo(cache_info->file_semaphore);
5787 return(MagickFalse);
5789 if ((cache_info->columns == nexus_info->region.width) &&
5790 (extent <= MagickMaxBufferExtent))
5795 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5796 for (y=0; y < (ssize_t) rows; y++)
5798 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5799 (MagickOffsetType) extent*(MagickOffsetType)
5800 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5801 (MagickOffsetType) cache_info->metacontent_extent,length,
5802 (
const unsigned char *) p);
5803 if (count != (MagickOffsetType) length)
5805 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5806 offset+=(MagickOffsetType) cache_info->columns;
5808 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5809 (void) ClosePixelCacheOnDisk(cache_info);
5810 UnlockSemaphoreInfo(cache_info->file_semaphore);
5813 case DistributedCache:
5821 LockSemaphoreInfo(cache_info->file_semaphore);
5822 region=nexus_info->region;
5823 if ((cache_info->columns != nexus_info->region.width) ||
5824 (extent > MagickMaxBufferExtent))
5831 for (y=0; y < (ssize_t) rows; y++)
5833 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5834 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5835 if (count != (MagickOffsetType) length)
5837 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5840 UnlockSemaphoreInfo(cache_info->file_semaphore);
5846 if (y < (ssize_t) rows)
5848 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5849 cache_info->cache_filename);
5850 return(MagickFalse);
5852 if ((cache_info->debug != MagickFalse) &&
5853 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5854 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5855 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5856 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5857 nexus_info->region.x,(
double) nexus_info->region.y);
5889static MagickBooleanType WritePixelCachePixels(
5890 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5891 ExceptionInfo *exception)
5910 if (nexus_info->authentic_pixel_cache != MagickFalse)
5912 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5913 return(MagickFalse);
5914 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5915 nexus_info->region.x;
5916 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5918 extent=length*nexus_info->region.height;
5919 rows=nexus_info->region.height;
5921 p=nexus_info->pixels;
5922 switch (cache_info->type)
5933 if ((cache_info->columns == nexus_info->region.width) &&
5934 (extent == (MagickSizeType) ((
size_t) extent)))
5939 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5941 for (y=0; y < (ssize_t) rows; y++)
5943 (void) memcpy(q,p,(
size_t) length);
5944 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5945 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5954 LockSemaphoreInfo(cache_info->file_semaphore);
5955 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5957 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5958 cache_info->cache_filename);
5959 UnlockSemaphoreInfo(cache_info->file_semaphore);
5960 return(MagickFalse);
5962 if ((cache_info->columns == nexus_info->region.width) &&
5963 (extent <= MagickMaxBufferExtent))
5968 for (y=0; y < (ssize_t) rows; y++)
5970 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5971 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5972 sizeof(*p),length,(
const unsigned char *) p);
5973 if (count != (MagickOffsetType) length)
5975 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5976 offset+=(MagickOffsetType) cache_info->columns;
5978 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5979 (void) ClosePixelCacheOnDisk(cache_info);
5980 UnlockSemaphoreInfo(cache_info->file_semaphore);
5983 case DistributedCache:
5991 LockSemaphoreInfo(cache_info->file_semaphore);
5992 region=nexus_info->region;
5993 if ((cache_info->columns != nexus_info->region.width) ||
5994 (extent > MagickMaxBufferExtent))
6001 for (y=0; y < (ssize_t) rows; y++)
6003 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
6004 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6005 if (count != (MagickOffsetType) length)
6007 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6010 UnlockSemaphoreInfo(cache_info->file_semaphore);
6016 if (y < (ssize_t) rows)
6018 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6019 cache_info->cache_filename);
6020 return(MagickFalse);
6022 if ((cache_info->debug != MagickFalse) &&
6023 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6024 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6025 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
6026 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
6027 nexus_info->region.x,(
double) nexus_info->region.y);