43#include "MagickCore/studio.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/cache-private.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colorspace-private.h"
50#include "MagickCore/composite-private.h"
51#include "MagickCore/distribute-cache-private.h"
52#include "MagickCore/exception.h"
53#include "MagickCore/exception-private.h"
54#include "MagickCore/geometry.h"
55#include "MagickCore/list.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#include "MagickCore/memory-private.h"
60#include "MagickCore/nt-base-private.h"
61#include "MagickCore/option.h"
62#include "MagickCore/pixel.h"
63#include "MagickCore/pixel-accessor.h"
64#include "MagickCore/pixel-private.h"
65#include "MagickCore/policy.h"
66#include "MagickCore/quantum.h"
67#include "MagickCore/random_.h"
68#include "MagickCore/registry.h"
69#include "MagickCore/resource_.h"
70#include "MagickCore/semaphore.h"
71#include "MagickCore/splay-tree.h"
72#include "MagickCore/string_.h"
73#include "MagickCore/string-private.h"
74#include "MagickCore/timer-private.h"
75#include "MagickCore/thread-private.h"
76#include "MagickCore/utility.h"
77#include "MagickCore/utility-private.h"
78#if defined(MAGICKCORE_HAVE_SYS_LOADAVG_H)
79# include <sys/loadavg.h>
81#if defined(MAGICKCORE_ZLIB_DELEGATE)
88#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
89#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
90 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
105#if defined(__cplusplus) || defined(c_plusplus)
110 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
114 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
115 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
116 *GetVirtualPixelsCache(
const Image *);
119 *GetVirtualMetacontentFromCache(
const Image *);
121static MagickBooleanType
122 GetOneAuthenticPixelFromCache(Image *,
const ssize_t,
const ssize_t,Quantum *,
124 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
125 const ssize_t,
const ssize_t,Quantum *,ExceptionInfo *),
126 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
127 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
128 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
130 ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
131 NexusInfo *magick_restrict,ExceptionInfo *),
132 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
133 WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
135 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
139 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
140 const size_t,ExceptionInfo *),
141 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
142 const size_t,ExceptionInfo *),
143 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
144 const ssize_t,
const ssize_t,
const size_t,
const size_t,
145 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
148#if defined(MAGICKCORE_OPENCL_SUPPORT)
150 CopyOpenCLBuffer(CacheInfo *magick_restrict);
153#if defined(__cplusplus) || defined(c_plusplus)
164 cache_anonymous_memory = (-1);
188MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
191 *magick_restrict cache_info;
196 cache_info=(CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
197 if (cache_info == (CacheInfo *) NULL)
198 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
199 (void) memset(cache_info,0,
sizeof(*cache_info));
200 cache_info->type=UndefinedCache;
201 cache_info->mode=IOMode;
202 cache_info->disk_mode=IOMode;
203 cache_info->colorspace=sRGBColorspace;
204 cache_info->file=(-1);
205 cache_info->id=GetMagickThreadId();
206 cache_info->number_threads=number_threads;
207 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
208 cache_info->number_threads=GetOpenMPMaximumThreads();
209 if (cache_info->number_threads == 0)
210 cache_info->number_threads=1;
211 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
212 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
213 if (value != (
const char *) NULL)
215 cache_info->synchronize=IsStringTrue(value);
216 value=DestroyString(value);
218 value=GetPolicyValue(
"cache:synchronize");
219 if (value != (
const char *) NULL)
221 cache_info->synchronize=IsStringTrue(value);
222 value=DestroyString(value);
224 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
225 (MagickSizeType) MAGICK_SSIZE_MAX);
226 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
227 (MagickSizeType) MAGICK_SSIZE_MAX);
228 cache_info->semaphore=AcquireSemaphoreInfo();
229 cache_info->reference_count=1;
230 cache_info->file_semaphore=AcquireSemaphoreInfo();
231 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
233 cache_info->signature=MagickCoreSignature;
234 return((Cache ) cache_info);
259MagickPrivate NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
262 **magick_restrict nexus_info;
267 nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
268 number_threads,
sizeof(*nexus_info)));
269 if (nexus_info == (NexusInfo **) NULL)
270 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
271 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
272 2*
sizeof(**nexus_info));
273 if (*nexus_info == (NexusInfo *) NULL)
274 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
275 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
276 for (i=0; i < (ssize_t) (2*number_threads); i++)
278 nexus_info[i]=(*nexus_info+i);
279 if (i < (ssize_t) number_threads)
280 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
281 nexus_info[i]->signature=MagickCoreSignature;
314MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
315 ExceptionInfo *exception)
318 *magick_restrict cache_info;
320 assert(image != (
const Image *) NULL);
321 assert(image->signature == MagickCoreSignature);
322 assert(exception != (ExceptionInfo *) NULL);
323 assert(exception->signature == MagickCoreSignature);
324 assert(image->cache != (Cache) NULL);
326 cache_info=(CacheInfo *) image->cache;
327 assert(cache_info->signature == MagickCoreSignature);
329 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
330 return((
void *) NULL);
331 *length=(size_t) cache_info->length;
332 return(cache_info->pixels);
353MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
356 cache_semaphore=AcquireSemaphoreInfo();
378MagickPrivate
void CacheComponentTerminus(
void)
381 ActivateSemaphoreInfo(&cache_semaphore);
383 RelinquishSemaphoreInfo(&cache_semaphore);
415static MagickBooleanType ClipPixelCacheNexus(Image *image,
416 NexusInfo *nexus_info,ExceptionInfo *exception)
419 *magick_restrict cache_info;
431 if (IsEventLogging() != MagickFalse)
432 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
433 if ((image->channels & WriteMaskChannel) == 0)
435 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
437 cache_info=(CacheInfo *) image->cache;
438 if (cache_info == (CacheInfo *) NULL)
440 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
441 nexus_info->region.width,nexus_info->region.height,
442 nexus_info->virtual_nexus,exception);
443 q=nexus_info->pixels;
444 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
446 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
451 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
459 mask_alpha=QuantumScale*(double) GetPixelWriteMask(image,p);
460 if (fabs(mask_alpha) >= MagickEpsilon)
462 for (i=0; i < (ssize_t) image->number_channels; i++)
464 PixelChannel channel = GetPixelChannelChannel(image,i);
465 PixelTrait traits = GetPixelChannelTraits(image,channel);
466 if ((traits & UpdatePixelTrait) == 0)
468 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha*(
double)
469 GetPixelAlpha(image,p),(
double) q[i],(
double)
470 GetPixelAlpha(image,q)));
472 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
474 p+=(ptrdiff_t) GetPixelChannels(image);
475 q+=(ptrdiff_t) GetPixelChannels(image);
503MagickPrivate Cache ClonePixelCache(
const Cache cache)
506 *magick_restrict clone_info;
509 *magick_restrict cache_info;
511 assert(cache != NULL);
512 cache_info=(
const CacheInfo *) cache;
513 assert(cache_info->signature == MagickCoreSignature);
514 if (IsEventLogging() != MagickFalse)
515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
516 cache_info->filename);
517 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
518 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
519 return((Cache ) clone_info);
547MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
550 *magick_restrict cache_info,
551 *magick_restrict source_info;
553 assert(clone != (Cache) NULL);
554 source_info=(CacheInfo *) clone;
555 assert(source_info->signature == MagickCoreSignature);
556 if (IsEventLogging() != MagickFalse)
557 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
558 source_info->filename);
559 assert(cache != (Cache) NULL);
560 cache_info=(CacheInfo *) cache;
561 assert(cache_info->signature == MagickCoreSignature);
562 source_info->methods=cache_info->methods;
594static MagickBooleanType ClonePixelCacheOnDisk(
595 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
615 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
616 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
618 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
619 (lseek(clone_info->file,0,SEEK_SET) < 0))
621 quantum=(size_t) MagickMaxBufferExtent;
622 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
624#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
625 if (cache_info->length < 0x7ffff000)
627 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
628 (
size_t) cache_info->length);
629 if (count == (ssize_t) cache_info->length)
631 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
632 (lseek(clone_info->file,0,SEEK_SET) < 0))
636 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
638 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
639 if (buffer == (
unsigned char *) NULL)
640 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
642 while ((count=read(cache_info->file,buffer,quantum)) > 0)
647 number_bytes=write(clone_info->file,buffer,(
size_t) count);
648 if (number_bytes != count)
650 extent+=(size_t) number_bytes;
652 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
653 if (extent != cache_info->length)
658#if defined(MAGICKCORE_OPENMP_SUPPORT)
659static inline int GetCacheNumberThreads(
const CacheInfo *source,
660 const CacheInfo *destination,
const size_t chunk,
const int factor)
663 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
664 number_threads = 1UL,
665 workload_factor = 64UL << factor;
670 number_threads=(chunk <= workload_factor) ? 1UL :
671 (chunk >= (workload_factor << 6)) ? max_threads :
672 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
676 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
677 ((destination->type != MemoryCache) && (destination->type != MapCache)))
678 number_threads=MagickMin(number_threads,4);
679 return((
int) number_threads);
683static MagickBooleanType ClonePixelCacheRepository(
684 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
685 ExceptionInfo *exception)
687#define cache_number_threads(source,destination,chunk,factor) \
688 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
695 **magick_restrict cache_nexus,
696 **magick_restrict clone_nexus;
704 assert(cache_info != (CacheInfo *) NULL);
705 assert(clone_info != (CacheInfo *) NULL);
706 assert(exception != (ExceptionInfo *) NULL);
707 if (cache_info->type == PingCache)
709 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
710 if ((cache_info->storage_class == clone_info->storage_class) &&
711 (cache_info->colorspace == clone_info->colorspace) &&
712 (cache_info->alpha_trait == clone_info->alpha_trait) &&
713 (cache_info->channels == clone_info->channels) &&
714 (cache_info->columns == clone_info->columns) &&
715 (cache_info->rows == clone_info->rows) &&
716 (cache_info->number_channels == clone_info->number_channels) &&
717 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
718 (cache_info->metacontent_extent == clone_info->metacontent_extent))
723 if (((cache_info->type == MemoryCache) ||
724 (cache_info->type == MapCache)) &&
725 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
727 (void) memcpy(clone_info->pixels,cache_info->pixels,
728 cache_info->number_channels*cache_info->columns*cache_info->rows*
729 sizeof(*cache_info->pixels));
730 if ((cache_info->metacontent_extent != 0) &&
731 (clone_info->metacontent_extent != 0))
732 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
733 cache_info->columns*cache_info->rows*
734 clone_info->metacontent_extent*
sizeof(
unsigned char));
737 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
738 return(ClonePixelCacheOnDisk(cache_info,clone_info));
743 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
744 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
745 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
746 optimize=(cache_info->number_channels == clone_info->number_channels) &&
747 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
748 MagickTrue : MagickFalse;
749 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
750 clone_info->number_channels*clone_info->columns);
752#if defined(MAGICKCORE_OPENMP_SUPPORT)
753 #pragma omp parallel for schedule(static) shared(status) \
754 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
756 for (y=0; y < (ssize_t) cache_info->rows; y++)
759 id = GetOpenMPThreadId();
767 if (status == MagickFalse)
769 if (y >= (ssize_t) clone_info->rows)
771 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
772 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
773 if (pixels == (Quantum *) NULL)
775 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
776 if (status == MagickFalse)
778 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
779 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
780 if (pixels == (Quantum *) NULL)
782 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
783 if (optimize != MagickFalse)
784 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
797 p=cache_nexus[id]->pixels;
798 q=clone_nexus[id]->pixels;
799 for (x=0; x < (ssize_t) cache_info->columns; x++)
804 if (x == (ssize_t) clone_info->columns)
806 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
814 channel=clone_info->channel_map[i].channel;
815 traits=cache_info->channel_map[channel].traits;
816 if (traits != UndefinedPixelTrait)
817 *q=*(p+cache_info->channel_map[channel].offset);
820 p+=(ptrdiff_t) cache_info->number_channels;
823 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
825 if ((cache_info->metacontent_extent != 0) &&
826 (clone_info->metacontent_extent != 0))
831 length=(size_t) MagickMin(cache_info->metacontent_extent,
832 clone_info->metacontent_extent);
833#if defined(MAGICKCORE_OPENMP_SUPPORT)
834 #pragma omp parallel for schedule(static) shared(status) \
835 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
837 for (y=0; y < (ssize_t) cache_info->rows; y++)
840 id = GetOpenMPThreadId();
845 if (status == MagickFalse)
847 if (y >= (ssize_t) clone_info->rows)
849 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
850 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
851 if (pixels == (Quantum *) NULL)
853 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
854 if (status == MagickFalse)
856 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
857 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
858 if (pixels == (Quantum *) NULL)
860 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
861 (cache_nexus[
id]->metacontent != (
void *) NULL))
862 (void) memcpy(clone_nexus[
id]->metacontent,
863 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
864 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
867 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
868 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
869 if (cache_info->debug != MagickFalse)
872 message[MagickPathExtent];
874 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
875 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
876 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
877 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
904static void DestroyImagePixelCache(Image *image)
906 assert(image != (Image *) NULL);
907 assert(image->signature == MagickCoreSignature);
908 if (IsEventLogging() != MagickFalse)
909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
910 if (image->cache != (
void *) NULL)
911 image->cache=DestroyPixelCache(image->cache);
936MagickExport
void DestroyImagePixels(Image *image)
939 *magick_restrict cache_info;
941 assert(image != (
const Image *) NULL);
942 assert(image->signature == MagickCoreSignature);
943 if (IsEventLogging() != MagickFalse)
944 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
945 assert(image->cache != (Cache) NULL);
946 cache_info=(CacheInfo *) image->cache;
947 assert(cache_info->signature == MagickCoreSignature);
948 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
950 cache_info->methods.destroy_pixel_handler(image);
953 image->cache=DestroyPixelCache(image->cache);
979static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
985 if (cache_info->file != -1)
987 status=close_utf8(cache_info->file);
988 cache_info->file=(-1);
989 RelinquishMagickResource(FileResource,1);
991 return(status == -1 ? MagickFalse : MagickTrue);
994static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
996 switch (cache_info->type)
1000 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
1001#if defined(MAGICKCORE_OPENCL_SUPPORT)
1002 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1004 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1006 cache_info->pixels=(Quantum *) NULL;
1010 if (cache_info->mapped == MagickFalse)
1011 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1012 cache_info->pixels);
1015 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1016 cache_info->pixels=(Quantum *) NULL;
1018 RelinquishMagickResource(MemoryResource,cache_info->length);
1023 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1024 cache_info->pixels=(Quantum *) NULL;
1025 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1026 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1027 *cache_info->cache_filename=
'\0';
1028 RelinquishMagickResource(MapResource,cache_info->length);
1033 if (cache_info->file != -1)
1034 (void) ClosePixelCacheOnDisk(cache_info);
1035 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1036 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1037 *cache_info->cache_filename=
'\0';
1038 RelinquishMagickResource(DiskResource,cache_info->length);
1041 case DistributedCache:
1043 *cache_info->cache_filename=
'\0';
1044 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1045 cache_info->server_info);
1051 cache_info->type=UndefinedCache;
1052 cache_info->mapped=MagickFalse;
1053 cache_info->metacontent=(
void *) NULL;
1056MagickPrivate Cache DestroyPixelCache(Cache cache)
1059 *magick_restrict cache_info;
1061 assert(cache != (Cache) NULL);
1062 cache_info=(CacheInfo *) cache;
1063 assert(cache_info->signature == MagickCoreSignature);
1064 if (IsEventLogging() != MagickFalse)
1065 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1066 cache_info->filename);
1067 LockSemaphoreInfo(cache_info->semaphore);
1068 cache_info->reference_count--;
1069 if (cache_info->reference_count != 0)
1071 UnlockSemaphoreInfo(cache_info->semaphore);
1072 return((Cache) NULL);
1074 UnlockSemaphoreInfo(cache_info->semaphore);
1075 if (cache_info->debug != MagickFalse)
1078 message[MagickPathExtent];
1080 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1081 cache_info->filename);
1082 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1084 RelinquishPixelCachePixels(cache_info);
1085 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1086 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1087 cache_info->server_info);
1088 if (cache_info->nexus_info != (NexusInfo **) NULL)
1089 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1090 cache_info->number_threads);
1091 if (cache_info->random_info != (RandomInfo *) NULL)
1092 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1094 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1096 RelinquishSemaphoreInfo(&cache_info->semaphore);
1097 cache_info->signature=(~MagickCoreSignature);
1098 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1129static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1131 if (nexus_info->mapped == MagickFalse)
1132 (void) RelinquishAlignedMemory(nexus_info->cache);
1134 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1135 nexus_info->cache=(Quantum *) NULL;
1136 nexus_info->pixels=(Quantum *) NULL;
1137 nexus_info->metacontent=(
void *) NULL;
1138 nexus_info->length=0;
1139 nexus_info->mapped=MagickFalse;
1142MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1143 const size_t number_threads)
1148 assert(nexus_info != (NexusInfo **) NULL);
1149 for (i=0; i < (ssize_t) (2*number_threads); i++)
1151 if (nexus_info[i]->cache != (Quantum *) NULL)
1152 RelinquishCacheNexusPixels(nexus_info[i]);
1153 nexus_info[i]->signature=(~MagickCoreSignature);
1155 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1156 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1185MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1188 *magick_restrict cache_info;
1191 id = GetOpenMPThreadId();
1193 assert(image != (
const Image *) NULL);
1194 assert(image->signature == MagickCoreSignature);
1195 assert(image->cache != (Cache) NULL);
1196 cache_info=(CacheInfo *) image->cache;
1197 assert(cache_info->signature == MagickCoreSignature);
1198 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1199 (GetAuthenticMetacontentFromHandler) NULL)
1204 metacontent=cache_info->methods.
1205 get_authentic_metacontent_from_handler(image);
1206 return(metacontent);
1208 assert(
id < (
int) cache_info->number_threads);
1209 return(cache_info->nexus_info[
id]->metacontent);
1236static void *GetAuthenticMetacontentFromCache(
const Image *image)
1239 *magick_restrict cache_info;
1242 id = GetOpenMPThreadId();
1244 assert(image != (
const Image *) NULL);
1245 assert(image->signature == MagickCoreSignature);
1246 assert(image->cache != (Cache) NULL);
1247 cache_info=(CacheInfo *) image->cache;
1248 assert(cache_info->signature == MagickCoreSignature);
1249 assert(
id < (
int) cache_info->number_threads);
1250 return(cache_info->nexus_info[
id]->metacontent);
1253#if defined(MAGICKCORE_OPENCL_SUPPORT)
1282MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1283 MagickCLDevice device,ExceptionInfo *exception)
1286 *magick_restrict cache_info;
1288 assert(image != (
const Image *) NULL);
1289 assert(device != (
const MagickCLDevice) NULL);
1290 cache_info=(CacheInfo *) image->cache;
1291 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1293 SyncImagePixelCache((Image *) image,exception);
1294 cache_info=(CacheInfo *) image->cache;
1296 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1297 return((cl_mem) NULL);
1298 LockSemaphoreInfo(cache_info->semaphore);
1299 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1300 (cache_info->opencl->device->context != device->context))
1301 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1302 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1304 assert(cache_info->pixels != (Quantum *) NULL);
1305 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1306 cache_info->length);
1308 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1309 RetainOpenCLMemObject(cache_info->opencl->buffer);
1310 UnlockSemaphoreInfo(cache_info->semaphore);
1311 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1312 return((cl_mem) NULL);
1313 assert(cache_info->opencl->pixels == cache_info->pixels);
1314 return(cache_info->opencl->buffer);
1353MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
const ssize_t x,
1354 const ssize_t y,
const size_t columns,
const size_t rows,NexusInfo *nexus_info,
1355 ExceptionInfo *exception)
1358 *magick_restrict cache_info;
1361 *magick_restrict pixels;
1366 assert(image != (Image *) NULL);
1367 assert(image->signature == MagickCoreSignature);
1368 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1369 nexus_info,exception);
1370 if (pixels == (Quantum *) NULL)
1371 return((Quantum *) NULL);
1372 cache_info=(CacheInfo *) image->cache;
1373 assert(cache_info->signature == MagickCoreSignature);
1374 if (nexus_info->authentic_pixel_cache != MagickFalse)
1376 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1377 return((Quantum *) NULL);
1378 if (cache_info->metacontent_extent != 0)
1379 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1380 return((Quantum *) NULL);
1407static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1410 *magick_restrict cache_info;
1413 id = GetOpenMPThreadId();
1415 assert(image != (
const Image *) NULL);
1416 assert(image->signature == MagickCoreSignature);
1417 assert(image->cache != (Cache) NULL);
1418 cache_info=(CacheInfo *) image->cache;
1419 assert(cache_info->signature == MagickCoreSignature);
1420 assert(
id < (
int) cache_info->number_threads);
1421 return(cache_info->nexus_info[
id]->pixels);
1448MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1451 *magick_restrict cache_info;
1454 id = GetOpenMPThreadId();
1456 assert(image != (
const Image *) NULL);
1457 assert(image->signature == MagickCoreSignature);
1458 assert(image->cache != (Cache) NULL);
1459 cache_info=(CacheInfo *) image->cache;
1460 assert(cache_info->signature == MagickCoreSignature);
1461 if (cache_info->methods.get_authentic_pixels_from_handler !=
1462 (GetAuthenticPixelsFromHandler) NULL)
1463 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1464 assert(
id < (
int) cache_info->number_threads);
1465 return(cache_info->nexus_info[
id]->pixels);
1513MagickExport Quantum *GetAuthenticPixels(Image *image,
const ssize_t x,
1514 const ssize_t y,
const size_t columns,
const size_t rows,
1515 ExceptionInfo *exception)
1518 *magick_restrict cache_info;
1521 id = GetOpenMPThreadId();
1526 assert(image != (Image *) NULL);
1527 assert(image->signature == MagickCoreSignature);
1528 assert(image->cache != (Cache) NULL);
1529 cache_info=(CacheInfo *) image->cache;
1530 assert(cache_info->signature == MagickCoreSignature);
1531 if (cache_info->methods.get_authentic_pixels_handler !=
1532 (GetAuthenticPixelsHandler) NULL)
1534 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1538 assert(
id < (
int) cache_info->number_threads);
1539 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1540 cache_info->nexus_info[
id],exception);
1575static Quantum *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1576 const ssize_t y,
const size_t columns,
const size_t rows,
1577 ExceptionInfo *exception)
1580 *magick_restrict cache_info;
1583 id = GetOpenMPThreadId();
1586 *magick_restrict pixels;
1588 assert(image != (
const Image *) NULL);
1589 assert(image->signature == MagickCoreSignature);
1590 assert(image->cache != (Cache) NULL);
1591 cache_info=(CacheInfo *) image->cache;
1592 if (cache_info == (Cache) NULL)
1593 return((Quantum *) NULL);
1594 assert(cache_info->signature == MagickCoreSignature);
1595 assert(
id < (
int) cache_info->number_threads);
1596 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1597 cache_info->nexus_info[
id],exception);
1624MagickExport MagickSizeType GetImageExtent(
const Image *image)
1627 *magick_restrict cache_info;
1630 id = GetOpenMPThreadId();
1632 assert(image != (Image *) NULL);
1633 assert(image->signature == MagickCoreSignature);
1634 if (IsEventLogging() != MagickFalse)
1635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1636 assert(image->cache != (Cache) NULL);
1637 cache_info=(CacheInfo *) image->cache;
1638 assert(cache_info->signature == MagickCoreSignature);
1639 assert(
id < (
int) cache_info->number_threads);
1640 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1673static MagickBooleanType GetDynamicThrottlePolicy(
void)
1675 static MagickBooleanType
1676 check_policy = MagickTrue;
1678 static MagickBooleanType
1679 dynamic_throttle = MagickFalse;
1681 if (check_policy != MagickFalse)
1683 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1684 if (value != (
char *) NULL)
1686 dynamic_throttle=IsStringTrue(value);
1687 value=DestroyString(value);
1689 check_policy=MagickFalse;
1691 return(dynamic_throttle);
1694static inline MagickBooleanType ValidatePixelCacheMorphology(
1695 const Image *magick_restrict image)
1698 *magick_restrict cache_info;
1700 const PixelChannelMap
1707 cache_info=(CacheInfo *) image->cache;
1708 p=image->channel_map;
1709 q=cache_info->channel_map;
1710 if ((image->storage_class != cache_info->storage_class) ||
1711 (image->colorspace != cache_info->colorspace) ||
1712 (image->alpha_trait != cache_info->alpha_trait) ||
1713 (image->channels != cache_info->channels) ||
1714 (image->columns != cache_info->columns) ||
1715 (image->rows != cache_info->rows) ||
1716 (image->number_channels != cache_info->number_channels) ||
1717 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1718 (image->metacontent_extent != cache_info->metacontent_extent) ||
1719 (cache_info->nexus_info == (NexusInfo **) NULL))
1720 return(MagickFalse);
1724static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1725 ExceptionInfo *exception)
1728 *magick_restrict cache_info;
1732 status = MagickTrue;
1734 static MagickSizeType
1735 cpu_throttle = MagickResourceInfinity,
1738 if (IsImageTTLExpired(image) != MagickFalse)
1743 (void) ThrowMagickException(exception,GetMagickModule(),
1744 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1745 return((Cache) NULL);
1747 if (cpu_throttle == MagickResourceInfinity)
1748 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1749 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1762#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1763 if (getloadavg(&load_average,1) != 1)
1766 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1767 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1769 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1770 MagickDelay(cpu_throttle);
1772 LockSemaphoreInfo(image->semaphore);
1773 assert(image->cache != (Cache) NULL);
1774 cache_info=(CacheInfo *) image->cache;
1775#if defined(MAGICKCORE_OPENCL_SUPPORT)
1776 CopyOpenCLBuffer(cache_info);
1778 destroy=MagickFalse;
1779 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1781 LockSemaphoreInfo(cache_info->semaphore);
1782 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1793 clone_image=(*image);
1794 clone_image.semaphore=AcquireSemaphoreInfo();
1795 clone_image.reference_count=1;
1796 clone_image.cache=ClonePixelCache(cache_info);
1797 clone_info=(CacheInfo *) clone_image.cache;
1798 status=OpenPixelCache(&clone_image,IOMode,exception);
1799 if (status == MagickFalse)
1800 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1803 if (clone != MagickFalse)
1804 status=ClonePixelCacheRepository(clone_info,cache_info,
1806 if (status == MagickFalse)
1807 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1811 image->cache=clone_info;
1814 RelinquishSemaphoreInfo(&clone_image.semaphore);
1816 UnlockSemaphoreInfo(cache_info->semaphore);
1818 if (destroy != MagickFalse)
1819 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1820 if (status != MagickFalse)
1825 if (image->type != UndefinedType)
1826 image->type=UndefinedType;
1827 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1829 status=OpenPixelCache(image,IOMode,exception);
1830 cache_info=(CacheInfo *) image->cache;
1831 if (cache_info->file != -1)
1832 (void) ClosePixelCacheOnDisk(cache_info);
1835 UnlockSemaphoreInfo(image->semaphore);
1836 if (status == MagickFalse)
1837 return((Cache) NULL);
1838 return(image->cache);
1864MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1867 *magick_restrict cache_info;
1869 assert(image != (Image *) NULL);
1870 assert(image->signature == MagickCoreSignature);
1871 assert(image->cache != (Cache) NULL);
1872 cache_info=(CacheInfo *) image->cache;
1873 assert(cache_info->signature == MagickCoreSignature);
1874 return(cache_info->type);
1908static inline MagickBooleanType CopyPixel(
const Image *image,
1909 const Quantum *source,Quantum *destination)
1914 if (source == (
const Quantum *) NULL)
1916 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1917 destination[GreenPixelChannel]=ClampToQuantum(
1918 image->background_color.green);
1919 destination[BluePixelChannel]=ClampToQuantum(
1920 image->background_color.blue);
1921 destination[BlackPixelChannel]=ClampToQuantum(
1922 image->background_color.black);
1923 destination[AlphaPixelChannel]=ClampToQuantum(
1924 image->background_color.alpha);
1925 return(MagickFalse);
1927 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1929 PixelChannel channel = GetPixelChannelChannel(image,i);
1930 destination[channel]=source[i];
1935MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1936 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1939 *magick_restrict cache_info;
1944 assert(image != (Image *) NULL);
1945 assert(image->signature == MagickCoreSignature);
1946 assert(image->cache != (Cache) NULL);
1947 cache_info=(CacheInfo *) image->cache;
1948 assert(cache_info->signature == MagickCoreSignature);
1949 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1950 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1951 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1952 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1953 return(CopyPixel(image,q,pixel));
1987static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
1988 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1991 *magick_restrict cache_info;
1994 id = GetOpenMPThreadId();
1999 assert(image != (
const Image *) NULL);
2000 assert(image->signature == MagickCoreSignature);
2001 assert(image->cache != (Cache) NULL);
2002 cache_info=(CacheInfo *) image->cache;
2003 assert(cache_info->signature == MagickCoreSignature);
2004 assert(
id < (
int) cache_info->number_threads);
2005 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2006 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2008 return(CopyPixel(image,q,pixel));
2042MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2043 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
2046 *magick_restrict cache_info;
2049 id = GetOpenMPThreadId();
2054 assert(image != (
const Image *) NULL);
2055 assert(image->signature == MagickCoreSignature);
2056 assert(image->cache != (Cache) NULL);
2057 cache_info=(CacheInfo *) image->cache;
2058 assert(cache_info->signature == MagickCoreSignature);
2059 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2060 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2061 (GetOneVirtualPixelFromHandler) NULL)
2062 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2063 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2064 assert(
id < (
int) cache_info->number_threads);
2065 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2066 1UL,1UL,cache_info->nexus_info[
id],exception);
2067 return(CopyPixel(image,p,pixel));
2104static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2105 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2106 Quantum *pixel,ExceptionInfo *exception)
2109 *magick_restrict cache_info;
2112 id = GetOpenMPThreadId();
2117 assert(image != (
const Image *) NULL);
2118 assert(image->signature == MagickCoreSignature);
2119 assert(image->cache != (Cache) NULL);
2120 cache_info=(CacheInfo *) image->cache;
2121 assert(cache_info->signature == MagickCoreSignature);
2122 assert(
id < (
int) cache_info->number_threads);
2123 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2124 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2125 cache_info->nexus_info[
id],exception);
2126 return(CopyPixel(image,p,pixel));
2163MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2164 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2165 PixelInfo *pixel,ExceptionInfo *exception)
2168 *magick_restrict cache_info;
2171 id = GetOpenMPThreadId();
2176 assert(image != (
const Image *) NULL);
2177 assert(image->signature == MagickCoreSignature);
2178 assert(image->cache != (Cache) NULL);
2179 cache_info=(CacheInfo *) image->cache;
2180 assert(cache_info->signature == MagickCoreSignature);
2181 assert(
id < (
int) cache_info->number_threads);
2182 GetPixelInfo(image,pixel);
2183 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2184 cache_info->nexus_info[
id],exception);
2185 if (p == (
const Quantum *) NULL)
2186 return(MagickFalse);
2187 GetPixelInfoPixel(image,p,pixel);
2213MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2216 *magick_restrict cache_info;
2218 assert(cache != (Cache) NULL);
2219 cache_info=(CacheInfo *) cache;
2220 assert(cache_info->signature == MagickCoreSignature);
2221 if (IsEventLogging() != MagickFalse)
2222 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2223 cache_info->filename);
2224 return(cache_info->colorspace);
2250MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2253 *magick_restrict cache_info;
2255 assert(image != (
const Image *) NULL);
2256 assert(image->signature == MagickCoreSignature);
2257 assert(image->cache != (Cache) NULL);
2258 cache_info=(CacheInfo *) image->cache;
2259 assert(cache_info->signature == MagickCoreSignature);
2260 return(cache_info->cache_filename);
2285MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2287 assert(cache_methods != (CacheMethods *) NULL);
2288 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2289 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2290 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2291 cache_methods->get_virtual_metacontent_from_handler=
2292 GetVirtualMetacontentFromCache;
2293 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2294 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2295 cache_methods->get_authentic_metacontent_from_handler=
2296 GetAuthenticMetacontentFromCache;
2297 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2298 cache_methods->get_one_authentic_pixel_from_handler=
2299 GetOneAuthenticPixelFromCache;
2300 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2301 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2302 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2330MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2331 NexusInfo *magick_restrict nexus_info)
2334 *magick_restrict cache_info;
2339 assert(cache != NULL);
2340 cache_info=(CacheInfo *) cache;
2341 assert(cache_info->signature == MagickCoreSignature);
2342 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2344 return((MagickSizeType) cache_info->columns*cache_info->rows);
2375MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2376 ExceptionInfo *magick_unused(exception))
2379 *magick_restrict cache_info;
2381 assert(image != (
const Image *) NULL);
2382 assert(image->signature == MagickCoreSignature);
2383 assert(image->cache != (Cache) NULL);
2384 assert(length != (MagickSizeType *) NULL);
2385 magick_unreferenced(exception);
2386 cache_info=(CacheInfo *) image->cache;
2387 assert(cache_info->signature == MagickCoreSignature);
2388 *length=cache_info->length;
2389 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2390 return((
void *) NULL);
2391 return((
void *) cache_info->pixels);
2418MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2421 *magick_restrict cache_info;
2423 assert(cache != (Cache) NULL);
2424 cache_info=(CacheInfo *) cache;
2425 assert(cache_info->signature == MagickCoreSignature);
2426 if (IsEventLogging() != MagickFalse)
2427 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2428 cache_info->filename);
2429 return(cache_info->storage_class);
2459MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2463 *magick_restrict cache_info;
2465 assert(image != (Image *) NULL);
2466 assert(image->signature == MagickCoreSignature);
2467 if (IsEventLogging() != MagickFalse)
2468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2469 cache_info=(CacheInfo *) image->cache;
2470 assert(cache_info->signature == MagickCoreSignature);
2471 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2472 if (GetImagePixelCacheType(image) == DiskCache)
2473 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2501MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2504 *magick_restrict cache_info;
2506 assert(image != (Image *) NULL);
2507 assert(image->signature == MagickCoreSignature);
2508 assert(image->cache != (Cache) NULL);
2509 cache_info=(CacheInfo *) image->cache;
2510 assert(cache_info->signature == MagickCoreSignature);
2511 return(cache_info->virtual_pixel_method);
2537static const void *GetVirtualMetacontentFromCache(
const Image *image)
2540 *magick_restrict cache_info;
2543 id = GetOpenMPThreadId();
2546 *magick_restrict metacontent;
2548 assert(image != (
const Image *) NULL);
2549 assert(image->signature == MagickCoreSignature);
2550 assert(image->cache != (Cache) NULL);
2551 cache_info=(CacheInfo *) image->cache;
2552 assert(cache_info->signature == MagickCoreSignature);
2553 assert(
id < (
int) cache_info->number_threads);
2554 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2555 cache_info->nexus_info[
id]);
2556 return(metacontent);
2585MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2586 NexusInfo *magick_restrict nexus_info)
2589 *magick_restrict cache_info;
2591 assert(cache != (Cache) NULL);
2592 cache_info=(CacheInfo *) cache;
2593 assert(cache_info->signature == MagickCoreSignature);
2594 if (cache_info->storage_class == UndefinedClass)
2595 return((
void *) NULL);
2596 return(nexus_info->metacontent);
2623MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2626 *magick_restrict cache_info;
2629 id = GetOpenMPThreadId();
2632 *magick_restrict metacontent;
2634 assert(image != (
const Image *) NULL);
2635 assert(image->signature == MagickCoreSignature);
2636 assert(image->cache != (Cache) NULL);
2637 cache_info=(CacheInfo *) image->cache;
2638 assert(cache_info->signature == MagickCoreSignature);
2639 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2641 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2643 if (metacontent != (
const void *) NULL)
2644 return(metacontent);
2646 assert(
id < (
int) cache_info->number_threads);
2647 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2648 cache_info->nexus_info[
id]);
2649 return(metacontent);
2692 0, 48, 12, 60, 3, 51, 15, 63,
2693 32, 16, 44, 28, 35, 19, 47, 31,
2694 8, 56, 4, 52, 11, 59, 7, 55,
2695 40, 24, 36, 20, 43, 27, 39, 23,
2696 2, 50, 14, 62, 1, 49, 13, 61,
2697 34, 18, 46, 30, 33, 17, 45, 29,
2698 10, 58, 6, 54, 9, 57, 5, 53,
2699 42, 26, 38, 22, 41, 25, 37, 21
2702static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2707 index=x+DitherMatrix[x & 0x07]-32L;
2710 if (index >= (ssize_t) columns)
2711 return((ssize_t) columns-1L);
2715static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2720 index=y+DitherMatrix[y & 0x07]-32L;
2723 if (index >= (ssize_t) rows)
2724 return((ssize_t) rows-1L);
2728static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2732 if (x >= (ssize_t) columns)
2733 return((ssize_t) (columns-1));
2737static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2741 if (y >= (ssize_t) rows)
2742 return((ssize_t) (rows-1));
2746static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2747 const MagickOffsetType y)
2749 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2750 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2751 return(MagickFalse);
2755static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2757 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2760static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2762 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2765static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2766 const size_t extent)
2771 modulo.quotient=offset;
2775 modulo.quotient=offset/((ssize_t) extent);
2776 modulo.remainder=offset % ((ssize_t) extent);
2778 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2781 modulo.remainder+=((ssize_t) extent);
2786MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2787 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2788 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2789 ExceptionInfo *exception)
2792 *magick_restrict cache_info;
2808 *magick_restrict virtual_nexus;
2811 *magick_restrict pixels,
2813 virtual_pixel[MaxPixelChannels];
2824 *magick_restrict virtual_metacontent;
2829 assert(image != (
const Image *) NULL);
2830 assert(image->signature == MagickCoreSignature);
2831 assert(image->cache != (Cache) NULL);
2832 cache_info=(CacheInfo *) image->cache;
2833 assert(cache_info->signature == MagickCoreSignature);
2834 if (cache_info->type == UndefinedCache)
2835 return((
const Quantum *) NULL);
2836#if defined(MAGICKCORE_OPENCL_SUPPORT)
2837 CopyOpenCLBuffer(cache_info);
2839 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2840 ((image->channels & WriteMaskChannel) != 0) ||
2841 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2842 nexus_info,exception);
2843 if (pixels == (Quantum *) NULL)
2844 return((
const Quantum *) NULL);
2845 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2846 return((
const Quantum *) NULL);
2847 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2848 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2849 return((
const Quantum *) NULL);
2850 offset+=nexus_info->region.x;
2851 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2852 nexus_info->region.width-1L;
2853 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2854 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2855 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2856 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2864 if (nexus_info->authentic_pixel_cache != MagickFalse)
2866 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2867 if (status == MagickFalse)
2868 return((
const Quantum *) NULL);
2869 if (cache_info->metacontent_extent != 0)
2871 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2872 if (status == MagickFalse)
2873 return((
const Quantum *) NULL);
2880 virtual_nexus=nexus_info->virtual_nexus;
2882 s=(
unsigned char *) nexus_info->metacontent;
2883 (void) memset(virtual_pixel,0,cache_info->number_channels*
2884 sizeof(*virtual_pixel));
2885 virtual_metacontent=(
void *) NULL;
2886 switch (virtual_pixel_method)
2888 case BackgroundVirtualPixelMethod:
2889 case BlackVirtualPixelMethod:
2890 case GrayVirtualPixelMethod:
2891 case TransparentVirtualPixelMethod:
2892 case MaskVirtualPixelMethod:
2893 case WhiteVirtualPixelMethod:
2894 case EdgeVirtualPixelMethod:
2895 case CheckerTileVirtualPixelMethod:
2896 case HorizontalTileVirtualPixelMethod:
2897 case VerticalTileVirtualPixelMethod:
2899 if (cache_info->metacontent_extent != 0)
2904 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2905 cache_info->metacontent_extent);
2906 if (virtual_metacontent == (
void *) NULL)
2908 (void) ThrowMagickException(exception,GetMagickModule(),
2909 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2910 return((
const Quantum *) NULL);
2912 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2914 switch (virtual_pixel_method)
2916 case BlackVirtualPixelMethod:
2918 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2919 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2920 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2923 case GrayVirtualPixelMethod:
2925 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2926 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2928 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2931 case TransparentVirtualPixelMethod:
2933 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2934 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2935 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2938 case MaskVirtualPixelMethod:
2939 case WhiteVirtualPixelMethod:
2941 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2942 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2943 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2948 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2950 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2952 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2954 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2956 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2966 for (v=0; v < (ssize_t) rows; v++)
2972 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2973 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2974 y_offset=EdgeY(y_offset,cache_info->rows);
2975 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2981 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2982 x_offset,(ssize_t) columns-u);
2983 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2984 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2994 length=(MagickSizeType) 1;
2995 switch (virtual_pixel_method)
2997 case EdgeVirtualPixelMethod:
3000 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3001 EdgeX(x_offset,cache_info->columns),
3002 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3004 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3007 case RandomVirtualPixelMethod:
3009 if (cache_info->random_info == (RandomInfo *) NULL)
3010 cache_info->random_info=AcquireRandomInfo();
3011 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3012 RandomX(cache_info->random_info,cache_info->columns),
3013 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3014 virtual_nexus,exception);
3015 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3018 case DitherVirtualPixelMethod:
3020 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3021 DitherX(x_offset,cache_info->columns),
3022 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3024 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3027 case TileVirtualPixelMethod:
3029 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3030 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3031 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3032 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3034 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3037 case MirrorVirtualPixelMethod:
3039 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3040 if ((x_modulo.quotient & 0x01) == 1L)
3041 x_modulo.remainder=(ssize_t) cache_info->columns-
3042 x_modulo.remainder-1L;
3043 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3044 if ((y_modulo.quotient & 0x01) == 1L)
3045 y_modulo.remainder=(ssize_t) cache_info->rows-
3046 y_modulo.remainder-1L;
3047 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3048 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3050 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3053 case HorizontalTileEdgeVirtualPixelMethod:
3055 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3056 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3057 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3058 virtual_nexus,exception);
3059 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3062 case VerticalTileEdgeVirtualPixelMethod:
3064 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3065 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3066 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3067 virtual_nexus,exception);
3068 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3071 case BackgroundVirtualPixelMethod:
3072 case BlackVirtualPixelMethod:
3073 case GrayVirtualPixelMethod:
3074 case TransparentVirtualPixelMethod:
3075 case MaskVirtualPixelMethod:
3076 case WhiteVirtualPixelMethod:
3079 r=virtual_metacontent;
3082 case CheckerTileVirtualPixelMethod:
3084 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3085 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3086 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3089 r=virtual_metacontent;
3092 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3093 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3095 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3098 case HorizontalTileVirtualPixelMethod:
3100 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3103 r=virtual_metacontent;
3106 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3107 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3108 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3109 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3111 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3114 case VerticalTileVirtualPixelMethod:
3116 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3119 r=virtual_metacontent;
3122 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3123 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3124 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3125 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3127 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3131 if (p == (
const Quantum *) NULL)
3133 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3135 q+=(ptrdiff_t) cache_info->number_channels;
3136 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3138 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3139 s+=(ptrdiff_t) cache_info->metacontent_extent;
3146 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3147 (
size_t) length,1UL,virtual_nexus,exception);
3148 if (p == (
const Quantum *) NULL)
3150 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3151 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3153 q+=(ptrdiff_t) cache_info->number_channels*length;
3154 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3156 (void) memcpy(s,r,(
size_t) length);
3157 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3160 if (u < (ssize_t) columns)
3166 if (virtual_metacontent != (
void *) NULL)
3167 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3168 if (v < (ssize_t) rows)
3169 return((
const Quantum *) NULL);
3207static const Quantum *GetVirtualPixelCache(
const Image *image,
3208 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3209 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3212 *magick_restrict cache_info;
3215 id = GetOpenMPThreadId();
3220 assert(image != (
const Image *) NULL);
3221 assert(image->signature == MagickCoreSignature);
3222 assert(image->cache != (Cache) NULL);
3223 cache_info=(CacheInfo *) image->cache;
3224 assert(cache_info->signature == MagickCoreSignature);
3225 assert(
id < (
int) cache_info->number_threads);
3226 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3227 cache_info->nexus_info[
id],exception);
3254MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3257 *magick_restrict cache_info;
3260 id = GetOpenMPThreadId();
3262 assert(image != (
const Image *) NULL);
3263 assert(image->signature == MagickCoreSignature);
3264 assert(image->cache != (Cache) NULL);
3265 cache_info=(CacheInfo *) image->cache;
3266 assert(cache_info->signature == MagickCoreSignature);
3267 if (cache_info->methods.get_virtual_pixels_handler !=
3268 (GetVirtualPixelsHandler) NULL)
3269 return(cache_info->methods.get_virtual_pixels_handler(image));
3270 assert(
id < (
int) cache_info->number_threads);
3271 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3322MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3323 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3324 ExceptionInfo *exception)
3327 *magick_restrict cache_info;
3330 id = GetOpenMPThreadId();
3335 assert(image != (
const Image *) NULL);
3336 assert(image->signature == MagickCoreSignature);
3337 assert(image->cache != (Cache) NULL);
3338 cache_info=(CacheInfo *) image->cache;
3339 assert(cache_info->signature == MagickCoreSignature);
3340 if (cache_info->methods.get_virtual_pixel_handler !=
3341 (GetVirtualPixelHandler) NULL)
3342 return(cache_info->methods.get_virtual_pixel_handler(image,
3343 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3344 assert(
id < (
int) cache_info->number_threads);
3345 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3346 columns,rows,cache_info->nexus_info[
id],exception);
3373static const Quantum *GetVirtualPixelsCache(
const Image *image)
3376 *magick_restrict cache_info;
3379 id = GetOpenMPThreadId();
3381 assert(image != (
const Image *) NULL);
3382 assert(image->signature == MagickCoreSignature);
3383 assert(image->cache != (Cache) NULL);
3384 cache_info=(CacheInfo *) image->cache;
3385 assert(cache_info->signature == MagickCoreSignature);
3386 assert(
id < (
int) cache_info->number_threads);
3387 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3416MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3417 NexusInfo *magick_restrict nexus_info)
3420 *magick_restrict cache_info;
3422 assert(cache != (Cache) NULL);
3423 cache_info=(CacheInfo *) cache;
3424 assert(cache_info->signature == MagickCoreSignature);
3425 if (cache_info->storage_class == UndefinedClass)
3426 return((Quantum *) NULL);
3427 return((
const Quantum *) nexus_info->pixels);
3460static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3461 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3466 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3468 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3469 gamma=MagickSafeReciprocal(gamma);
3470 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3473static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3474 ExceptionInfo *exception)
3477 *magick_restrict cache_info;
3489 if (IsEventLogging() != MagickFalse)
3490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3491 if ((image->channels & CompositeMaskChannel) == 0)
3493 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3495 cache_info=(CacheInfo *) image->cache;
3496 if (cache_info == (Cache) NULL)
3497 return(MagickFalse);
3498 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3499 nexus_info->region.width,nexus_info->region.height,
3500 nexus_info->virtual_nexus,exception);
3501 q=nexus_info->pixels;
3502 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3503 return(MagickFalse);
3504 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3509 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3517 alpha=(double) GetPixelCompositeMask(image,p);
3518 for (i=0; i < (ssize_t) image->number_channels; i++)
3520 PixelChannel channel = GetPixelChannelChannel(image,i);
3521 PixelTrait traits = GetPixelChannelTraits(image,channel);
3522 if ((traits & UpdatePixelTrait) == 0)
3524 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3526 p+=(ptrdiff_t) GetPixelChannels(image);
3527 q+=(ptrdiff_t) GetPixelChannels(image);
3564static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3573 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3575 if (*cache_info->cache_filename ==
'\0')
3576 file=AcquireUniqueFileResource(cache_info->cache_filename);
3582 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3587 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3588 O_BINARY | O_EXCL,S_MODE);
3590 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3596 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3599 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3604 return(MagickFalse);
3605 (void) AcquireMagickResource(FileResource,1);
3606 if (cache_info->file != -1)
3607 (void) ClosePixelCacheOnDisk(cache_info);
3608 cache_info->file=file;
3609 cache_info->disk_mode=mode;
3613static inline MagickOffsetType WritePixelCacheRegion(
3614 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3615 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3623#if !defined(MAGICKCORE_HAVE_PWRITE)
3624 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3625 return((MagickOffsetType) -1);
3627 for (i=0; i < (MagickOffsetType) length; i+=count)
3629#if !defined(MAGICKCORE_HAVE_PWRITE)
3630 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3631 (MagickSizeType) i,MagickMaxBufferExtent));
3633 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3634 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3646static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3649 *magick_restrict cache_info;
3654 cache_info=(CacheInfo *) image->cache;
3655 if (cache_info->debug != MagickFalse)
3658 format[MagickPathExtent],
3659 message[MagickPathExtent];
3661 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3662 (void) FormatLocaleString(message,MagickPathExtent,
3663 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3664 cache_info->cache_filename,cache_info->file,format);
3665 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3667 if (length != (MagickSizeType) ((MagickOffsetType) length))
3668 return(MagickFalse);
3669 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3671 return(MagickFalse);
3672 if ((MagickSizeType) offset < length)
3678 extent=(MagickOffsetType) length-1;
3679 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3682 return(MagickFalse);
3683#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3684 if (cache_info->synchronize != MagickFalse)
3685 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3686 return(MagickFalse);
3689 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3691 return(MagickFalse);
3695static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3696 ExceptionInfo *exception)
3699 *magick_restrict cache_info,
3703 format[MagickPathExtent],
3704 message[MagickPathExtent];
3721 assert(image != (
const Image *) NULL);
3722 assert(image->signature == MagickCoreSignature);
3723 assert(image->cache != (Cache) NULL);
3724 if (IsEventLogging() != MagickFalse)
3725 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3726 if (cache_anonymous_memory < 0)
3734 cache_anonymous_memory=0;
3735 value=GetPolicyValue(
"pixel-cache-memory");
3736 if (value == (
char *) NULL)
3737 value=GetPolicyValue(
"cache:memory-map");
3738 if (LocaleCompare(value,
"anonymous") == 0)
3740#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3741 cache_anonymous_memory=1;
3743 (void) ThrowMagickException(exception,GetMagickModule(),
3744 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3745 "`%s' (policy requires anonymous memory mapping)",image->filename);
3748 value=DestroyString(value);
3750 if ((image->columns == 0) || (image->rows == 0))
3751 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3752 cache_info=(CacheInfo *) image->cache;
3753 assert(cache_info->signature == MagickCoreSignature);
3754 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3755 ((MagickSizeType) image->rows > cache_info->height_limit))
3757 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3758 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3759 image->filename, (
double) image->columns, (
double) image->rows,
3760 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3761 return(MagickFalse);
3763 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3765 length=GetImageListLength(image);
3766 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3767 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3770 source_info=(*cache_info);
3771 source_info.file=(-1);
3772 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3773 image->filename,(
double) image->scene);
3774 cache_info->storage_class=image->storage_class;
3775 cache_info->colorspace=image->colorspace;
3776 cache_info->alpha_trait=image->alpha_trait;
3777 cache_info->channels=image->channels;
3778 cache_info->rows=image->rows;
3779 cache_info->columns=image->columns;
3780 status=ResetPixelChannelMap(image,exception);
3781 if (status == MagickFalse)
3782 return(MagickFalse);
3783 cache_info->number_channels=GetPixelChannels(image);
3784 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3785 sizeof(*image->channel_map));
3786 cache_info->metacontent_extent=image->metacontent_extent;
3787 cache_info->mode=mode;
3788 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3789 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3790 if (image->metacontent_extent != 0)
3791 packet_size+=cache_info->metacontent_extent;
3792 length=number_pixels*packet_size;
3793 columns=(size_t) (length/cache_info->rows/packet_size);
3794 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3795 ((ssize_t) cache_info->rows < 0))
3796 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3798 cache_info->length=length;
3799 if (image->ping != MagickFalse)
3801 cache_info->type=PingCache;
3804 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3805 cache_info->columns*cache_info->rows);
3806 if (cache_info->mode == PersistMode)
3808 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3809 cache_info->metacontent_extent);
3810 if ((status != MagickFalse) &&
3811 (length == (MagickSizeType) ((
size_t) length)) &&
3812 ((cache_info->type == UndefinedCache) ||
3813 (cache_info->type == MemoryCache)))
3815 status=AcquireMagickResource(MemoryResource,cache_info->length);
3816 if (status != MagickFalse)
3819 if (cache_anonymous_memory <= 0)
3821 cache_info->mapped=MagickFalse;
3822 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3823 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3827 cache_info->mapped=MagickTrue;
3828 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3829 cache_info->length);
3831 if (cache_info->pixels == (Quantum *) NULL)
3833 cache_info->mapped=source_info.mapped;
3834 cache_info->pixels=source_info.pixels;
3841 cache_info->type=MemoryCache;
3842 cache_info->metacontent=(
void *) NULL;
3843 if (cache_info->metacontent_extent != 0)
3844 cache_info->metacontent=(
void *) (cache_info->pixels+
3845 cache_info->number_channels*number_pixels);
3846 if ((source_info.storage_class != UndefinedClass) &&
3849 status=ClonePixelCacheRepository(cache_info,&source_info,
3851 RelinquishPixelCachePixels(&source_info);
3853 if (cache_info->debug != MagickFalse)
3855 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3856 MagickPathExtent,format);
3857 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3859 (void) FormatLocaleString(message,MagickPathExtent,
3860 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3861 cache_info->filename,cache_info->mapped != MagickFalse ?
3862 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3863 (
double) cache_info->rows,(
double)
3864 cache_info->number_channels,format);
3865 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3868 cache_info->storage_class=image->storage_class;
3871 if ((source_info.storage_class != UndefinedClass) &&
3873 RelinquishPixelCachePixels(&source_info);
3874 cache_info->type=UndefinedCache;
3875 return(MagickFalse);
3881 status=AcquireMagickResource(DiskResource,cache_info->length);
3882 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3884 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3892 server_info=AcquireDistributeCacheInfo(exception);
3893 if (server_info != (DistributeCacheInfo *) NULL)
3895 status=OpenDistributePixelCache(server_info,image);
3896 if (status == MagickFalse)
3898 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3899 GetDistributeCacheHostname(server_info));
3900 server_info=DestroyDistributeCacheInfo(server_info);
3908 cache_info->type=DistributedCache;
3909 cache_info->server_info=server_info;
3910 (void) FormatLocaleString(cache_info->cache_filename,
3911 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3912 (DistributeCacheInfo *) cache_info->server_info),
3913 GetDistributeCachePort((DistributeCacheInfo *)
3914 cache_info->server_info));
3915 if ((source_info.storage_class != UndefinedClass) &&
3918 status=ClonePixelCacheRepository(cache_info,&source_info,
3920 RelinquishPixelCachePixels(&source_info);
3922 if (cache_info->debug != MagickFalse)
3924 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3925 MagickPathExtent,format);
3926 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3928 (void) FormatLocaleString(message,MagickPathExtent,
3929 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3930 cache_info->filename,cache_info->cache_filename,
3931 GetDistributeCacheFile((DistributeCacheInfo *)
3932 cache_info->server_info),type,(
double) cache_info->columns,
3933 (
double) cache_info->rows,(
double)
3934 cache_info->number_channels,format);
3935 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3940 if ((source_info.storage_class != UndefinedClass) &&
3942 RelinquishPixelCachePixels(&source_info);
3943 cache_info->type=UndefinedCache;
3944 return(MagickFalse);
3949 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3950 RelinquishPixelCachePixels(&source_info);
3951 cache_info->type=UndefinedCache;
3952 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3953 "CacheResourcesExhausted",
"`%s'",image->filename);
3954 return(MagickFalse);
3959 if (status == MagickFalse)
3961 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3962 RelinquishPixelCachePixels(&source_info);
3963 cache_info->type=UndefinedCache;
3964 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3965 "CacheResourcesExhausted",
"`%s'",image->filename);
3966 return(MagickFalse);
3968 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3969 (cache_info->mode != PersistMode))
3971 (void) ClosePixelCacheOnDisk(cache_info);
3972 *cache_info->cache_filename=
'\0';
3974 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3976 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3977 RelinquishPixelCachePixels(&source_info);
3978 cache_info->type=UndefinedCache;
3979 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3981 return(MagickFalse);
3983 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3984 cache_info->length);
3985 if (status == MagickFalse)
3987 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3988 RelinquishPixelCachePixels(&source_info);
3989 cache_info->type=UndefinedCache;
3990 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3992 return(MagickFalse);
3994 cache_info->type=DiskCache;
3995 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3996 cache_info->metacontent_extent);
3997 if (length == (MagickSizeType) ((
size_t) length))
3999 status=AcquireMagickResource(MapResource,cache_info->length);
4000 if (status != MagickFalse)
4002 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4003 cache_info->offset,(
size_t) cache_info->length);
4004 if (cache_info->pixels == (Quantum *) NULL)
4006 cache_info->mapped=source_info.mapped;
4007 cache_info->pixels=source_info.pixels;
4008 RelinquishMagickResource(MapResource,cache_info->length);
4015 (void) ClosePixelCacheOnDisk(cache_info);
4016 cache_info->type=MapCache;
4017 cache_info->mapped=MagickTrue;
4018 cache_info->metacontent=(
void *) NULL;
4019 if (cache_info->metacontent_extent != 0)
4020 cache_info->metacontent=(
void *) (cache_info->pixels+
4021 cache_info->number_channels*number_pixels);
4022 if ((source_info.storage_class != UndefinedClass) &&
4025 status=ClonePixelCacheRepository(cache_info,&source_info,
4027 RelinquishPixelCachePixels(&source_info);
4029 if (cache_info->debug != MagickFalse)
4031 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4032 MagickPathExtent,format);
4033 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4035 (void) FormatLocaleString(message,MagickPathExtent,
4036 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4037 cache_info->filename,cache_info->cache_filename,
4038 cache_info->file,type,(
double) cache_info->columns,
4039 (
double) cache_info->rows,(
double)
4040 cache_info->number_channels,format);
4041 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4046 if ((source_info.storage_class != UndefinedClass) &&
4048 RelinquishPixelCachePixels(&source_info);
4049 cache_info->type=UndefinedCache;
4050 return(MagickFalse);
4057 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4059 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4060 RelinquishPixelCachePixels(&source_info);
4062 if (cache_info->debug != MagickFalse)
4064 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4065 MagickPathExtent,format);
4066 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4068 (void) FormatLocaleString(message,MagickPathExtent,
4069 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4070 cache_info->cache_filename,cache_info->file,type,(
double)
4071 cache_info->columns,(
double) cache_info->rows,(
double)
4072 cache_info->number_channels,format);
4073 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4077 cache_info->type=UndefinedCache;
4078 return(MagickFalse);
4120MagickExport MagickBooleanType PersistPixelCache(Image *image,
4121 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4122 ExceptionInfo *exception)
4125 *magick_restrict cache_info,
4126 *magick_restrict clone_info;
4134 assert(image != (Image *) NULL);
4135 assert(image->signature == MagickCoreSignature);
4136 if (IsEventLogging() != MagickFalse)
4137 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4138 assert(image->cache != (
void *) NULL);
4139 assert(filename != (
const char *) NULL);
4140 assert(offset != (MagickOffsetType *) NULL);
4141 page_size=GetMagickPageSize();
4142 cache_info=(CacheInfo *) image->cache;
4143 assert(cache_info->signature == MagickCoreSignature);
4144#if defined(MAGICKCORE_OPENCL_SUPPORT)
4145 CopyOpenCLBuffer(cache_info);
4147 if (attach != MagickFalse)
4152 if (cache_info->debug != MagickFalse)
4153 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4154 "attach persistent cache");
4155 (void) CopyMagickString(cache_info->cache_filename,filename,
4157 cache_info->type=MapCache;
4158 cache_info->offset=(*offset);
4159 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4160 return(MagickFalse);
4161 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4162 ((MagickOffsetType) cache_info->length % page_size));
4168 status=AcquireMagickResource(DiskResource,cache_info->length);
4169 if (status == MagickFalse)
4171 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4172 "CacheResourcesExhausted",
"`%s'",image->filename);
4173 return(MagickFalse);
4175 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4176 clone_info->type=DiskCache;
4177 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4178 clone_info->file=(-1);
4179 clone_info->storage_class=cache_info->storage_class;
4180 clone_info->colorspace=cache_info->colorspace;
4181 clone_info->alpha_trait=cache_info->alpha_trait;
4182 clone_info->channels=cache_info->channels;
4183 clone_info->columns=cache_info->columns;
4184 clone_info->rows=cache_info->rows;
4185 clone_info->number_channels=cache_info->number_channels;
4186 clone_info->metacontent_extent=cache_info->metacontent_extent;
4187 clone_info->mode=PersistMode;
4188 clone_info->length=cache_info->length;
4189 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4190 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4191 clone_info->offset=(*offset);
4192 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4193 if (status != MagickFalse)
4194 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4195 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4196 ((MagickOffsetType) cache_info->length % page_size));
4197 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4239MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4240 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4241 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4244 *magick_restrict cache_info;
4253 *magick_restrict pixels;
4258 assert(image != (
const Image *) NULL);
4259 assert(image->signature == MagickCoreSignature);
4260 assert(image->cache != (Cache) NULL);
4261 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4262 if (cache_info == (Cache) NULL)
4263 return((Quantum *) NULL);
4264 assert(cache_info->signature == MagickCoreSignature);
4265 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4266 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4267 (y >= (ssize_t) cache_info->rows))
4269 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4270 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4271 return((Quantum *) NULL);
4273 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4274 return((Quantum *) NULL);
4275 offset=y*(MagickOffsetType) cache_info->columns+x;
4277 return((Quantum *) NULL);
4278 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4279 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4280 (MagickOffsetType) columns-1;
4281 if ((MagickSizeType) offset >= number_pixels)
4282 return((Quantum *) NULL);
4286 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4287 ((image->channels & WriteMaskChannel) != 0) ||
4288 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4289 nexus_info,exception);
4326static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4327 const ssize_t y,
const size_t columns,
const size_t rows,
4328 ExceptionInfo *exception)
4331 *magick_restrict cache_info;
4334 id = GetOpenMPThreadId();
4337 *magick_restrict pixels;
4339 assert(image != (
const Image *) NULL);
4340 assert(image->signature == MagickCoreSignature);
4341 assert(image->cache != (Cache) NULL);
4342 cache_info=(CacheInfo *) image->cache;
4343 assert(cache_info->signature == MagickCoreSignature);
4344 assert(
id < (
int) cache_info->number_threads);
4345 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4346 cache_info->nexus_info[
id],exception);
4406MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4407 const ssize_t y,
const size_t columns,
const size_t rows,
4408 ExceptionInfo *exception)
4411 *magick_restrict cache_info;
4414 id = GetOpenMPThreadId();
4417 *magick_restrict pixels;
4419 assert(image != (Image *) NULL);
4420 assert(image->signature == MagickCoreSignature);
4421 assert(image->cache != (Cache) NULL);
4422 cache_info=(CacheInfo *) image->cache;
4423 assert(cache_info->signature == MagickCoreSignature);
4424 if (cache_info->methods.queue_authentic_pixels_handler !=
4425 (QueueAuthenticPixelsHandler) NULL)
4427 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4428 columns,rows,exception);
4431 assert(
id < (
int) cache_info->number_threads);
4432 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4433 cache_info->nexus_info[
id],exception);
4466static inline MagickOffsetType ReadPixelCacheRegion(
4467 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4468 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4476#if !defined(MAGICKCORE_HAVE_PREAD)
4477 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4478 return((MagickOffsetType) -1);
4480 for (i=0; i < (MagickOffsetType) length; i+=count)
4482#if !defined(MAGICKCORE_HAVE_PREAD)
4483 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4484 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4486 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4487 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4499static MagickBooleanType ReadPixelCacheMetacontent(
4500 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4501 ExceptionInfo *exception)
4520 if (cache_info->metacontent_extent == 0)
4521 return(MagickFalse);
4522 if (nexus_info->authentic_pixel_cache != MagickFalse)
4524 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4525 return(MagickFalse);
4526 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4527 nexus_info->region.x;
4528 length=(MagickSizeType) nexus_info->region.width*
4529 cache_info->metacontent_extent;
4530 extent=length*nexus_info->region.height;
4531 rows=nexus_info->region.height;
4533 q=(
unsigned char *) nexus_info->metacontent;
4534 switch (cache_info->type)
4545 if ((cache_info->columns == nexus_info->region.width) &&
4546 (extent == (MagickSizeType) ((
size_t) extent)))
4551 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4552 cache_info->metacontent_extent;
4553 for (y=0; y < (ssize_t) rows; y++)
4555 (void) memcpy(q,p,(
size_t) length);
4556 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4557 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4566 LockSemaphoreInfo(cache_info->file_semaphore);
4567 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4569 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4570 cache_info->cache_filename);
4571 UnlockSemaphoreInfo(cache_info->file_semaphore);
4572 return(MagickFalse);
4574 if ((cache_info->columns == nexus_info->region.width) &&
4575 (extent <= MagickMaxBufferExtent))
4580 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4581 for (y=0; y < (ssize_t) rows; y++)
4583 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4584 (MagickOffsetType) extent*(MagickOffsetType)
4585 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4586 (MagickOffsetType) cache_info->metacontent_extent,length,
4587 (
unsigned char *) q);
4588 if (count != (MagickOffsetType) length)
4590 offset+=(MagickOffsetType) cache_info->columns;
4591 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4593 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4594 (void) ClosePixelCacheOnDisk(cache_info);
4595 UnlockSemaphoreInfo(cache_info->file_semaphore);
4598 case DistributedCache:
4606 LockSemaphoreInfo(cache_info->file_semaphore);
4607 region=nexus_info->region;
4608 if ((cache_info->columns != nexus_info->region.width) ||
4609 (extent > MagickMaxBufferExtent))
4616 for (y=0; y < (ssize_t) rows; y++)
4618 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4619 cache_info->server_info,®ion,length,(
unsigned char *) q);
4620 if (count != (MagickOffsetType) length)
4622 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4625 UnlockSemaphoreInfo(cache_info->file_semaphore);
4631 if (y < (ssize_t) rows)
4633 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4634 cache_info->cache_filename);
4635 return(MagickFalse);
4637 if ((cache_info->debug != MagickFalse) &&
4638 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4639 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4640 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4641 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4642 nexus_info->region.x,(
double) nexus_info->region.y);
4674static MagickBooleanType ReadPixelCachePixels(
4675 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4676 ExceptionInfo *exception)
4696 if (nexus_info->authentic_pixel_cache != MagickFalse)
4698 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4699 return(MagickFalse);
4700 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4701 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4702 return(MagickFalse);
4703 offset+=nexus_info->region.x;
4704 number_channels=cache_info->number_channels;
4705 length=(MagickSizeType) number_channels*nexus_info->region.width*
4707 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4708 return(MagickFalse);
4709 rows=nexus_info->region.height;
4711 if ((extent == 0) || ((extent/length) != rows))
4712 return(MagickFalse);
4714 q=nexus_info->pixels;
4715 switch (cache_info->type)
4726 if ((cache_info->columns == nexus_info->region.width) &&
4727 (extent == (MagickSizeType) ((
size_t) extent)))
4732 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4734 for (y=0; y < (ssize_t) rows; y++)
4736 (void) memcpy(q,p,(
size_t) length);
4737 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4738 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4747 LockSemaphoreInfo(cache_info->file_semaphore);
4748 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4750 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4751 cache_info->cache_filename);
4752 UnlockSemaphoreInfo(cache_info->file_semaphore);
4753 return(MagickFalse);
4755 if ((cache_info->columns == nexus_info->region.width) &&
4756 (extent <= MagickMaxBufferExtent))
4761 for (y=0; y < (ssize_t) rows; y++)
4763 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4764 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4765 sizeof(*q),length,(
unsigned char *) q);
4766 if (count != (MagickOffsetType) length)
4768 offset+=(MagickOffsetType) cache_info->columns;
4769 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4771 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4772 (void) ClosePixelCacheOnDisk(cache_info);
4773 UnlockSemaphoreInfo(cache_info->file_semaphore);
4776 case DistributedCache:
4784 LockSemaphoreInfo(cache_info->file_semaphore);
4785 region=nexus_info->region;
4786 if ((cache_info->columns != nexus_info->region.width) ||
4787 (extent > MagickMaxBufferExtent))
4794 for (y=0; y < (ssize_t) rows; y++)
4796 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4797 cache_info->server_info,®ion,length,(
unsigned char *) q);
4798 if (count != (MagickOffsetType) length)
4800 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4803 UnlockSemaphoreInfo(cache_info->file_semaphore);
4809 if (y < (ssize_t) rows)
4811 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4812 cache_info->cache_filename);
4813 return(MagickFalse);
4815 if ((cache_info->debug != MagickFalse) &&
4816 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4817 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4818 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4819 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4820 nexus_info->region.x,(
double) nexus_info->region.y);
4847MagickPrivate Cache ReferencePixelCache(Cache cache)
4850 *magick_restrict cache_info;
4852 assert(cache != (Cache *) NULL);
4853 cache_info=(CacheInfo *) cache;
4854 assert(cache_info->signature == MagickCoreSignature);
4855 LockSemaphoreInfo(cache_info->semaphore);
4856 cache_info->reference_count++;
4857 UnlockSemaphoreInfo(cache_info->semaphore);
4883MagickPrivate
void ResetPixelCacheChannels(Image *image)
4886 *magick_restrict cache_info;
4888 assert(image != (
const Image *) NULL);
4889 assert(image->signature == MagickCoreSignature);
4890 assert(image->cache != (Cache) NULL);
4891 cache_info=(CacheInfo *) image->cache;
4892 assert(cache_info->signature == MagickCoreSignature);
4893 cache_info->number_channels=GetPixelChannels(image);
4914MagickPrivate
void ResetCacheAnonymousMemory(
void)
4916 cache_anonymous_memory=0;
4948MagickExport MagickBooleanType ReshapePixelCache(Image *image,
4949 const size_t columns,
const size_t rows,ExceptionInfo *exception)
4957 assert(image != (Image *) NULL);
4958 assert(image->signature == MagickCoreSignature);
4959 if (IsEventLogging() != MagickFalse)
4960 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4961 assert(image->cache != (
void *) NULL);
4962 extent=(MagickSizeType) columns*rows;
4963 if (extent > ((MagickSizeType) image->columns*image->rows))
4964 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4966 image->columns=columns;
4968 cache_info=(CacheInfo *) image->cache;
4969 cache_info->columns=columns;
4970 cache_info->rows=rows;
4971 return(SyncImagePixelCache(image,exception));
4998MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
5001 *magick_restrict cache_info;
5003 GetOneAuthenticPixelFromHandler
5004 get_one_authentic_pixel_from_handler;
5006 GetOneVirtualPixelFromHandler
5007 get_one_virtual_pixel_from_handler;
5012 assert(cache != (Cache) NULL);
5013 assert(cache_methods != (CacheMethods *) NULL);
5014 cache_info=(CacheInfo *) cache;
5015 assert(cache_info->signature == MagickCoreSignature);
5016 if (IsEventLogging() != MagickFalse)
5017 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5018 cache_info->filename);
5019 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5020 cache_info->methods.get_virtual_pixel_handler=
5021 cache_methods->get_virtual_pixel_handler;
5022 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5023 cache_info->methods.destroy_pixel_handler=
5024 cache_methods->destroy_pixel_handler;
5025 if (cache_methods->get_virtual_metacontent_from_handler !=
5026 (GetVirtualMetacontentFromHandler) NULL)
5027 cache_info->methods.get_virtual_metacontent_from_handler=
5028 cache_methods->get_virtual_metacontent_from_handler;
5029 if (cache_methods->get_authentic_pixels_handler !=
5030 (GetAuthenticPixelsHandler) NULL)
5031 cache_info->methods.get_authentic_pixels_handler=
5032 cache_methods->get_authentic_pixels_handler;
5033 if (cache_methods->queue_authentic_pixels_handler !=
5034 (QueueAuthenticPixelsHandler) NULL)
5035 cache_info->methods.queue_authentic_pixels_handler=
5036 cache_methods->queue_authentic_pixels_handler;
5037 if (cache_methods->sync_authentic_pixels_handler !=
5038 (SyncAuthenticPixelsHandler) NULL)
5039 cache_info->methods.sync_authentic_pixels_handler=
5040 cache_methods->sync_authentic_pixels_handler;
5041 if (cache_methods->get_authentic_pixels_from_handler !=
5042 (GetAuthenticPixelsFromHandler) NULL)
5043 cache_info->methods.get_authentic_pixels_from_handler=
5044 cache_methods->get_authentic_pixels_from_handler;
5045 if (cache_methods->get_authentic_metacontent_from_handler !=
5046 (GetAuthenticMetacontentFromHandler) NULL)
5047 cache_info->methods.get_authentic_metacontent_from_handler=
5048 cache_methods->get_authentic_metacontent_from_handler;
5049 get_one_virtual_pixel_from_handler=
5050 cache_info->methods.get_one_virtual_pixel_from_handler;
5051 if (get_one_virtual_pixel_from_handler !=
5052 (GetOneVirtualPixelFromHandler) NULL)
5053 cache_info->methods.get_one_virtual_pixel_from_handler=
5054 cache_methods->get_one_virtual_pixel_from_handler;
5055 get_one_authentic_pixel_from_handler=
5056 cache_methods->get_one_authentic_pixel_from_handler;
5057 if (get_one_authentic_pixel_from_handler !=
5058 (GetOneAuthenticPixelFromHandler) NULL)
5059 cache_info->methods.get_one_authentic_pixel_from_handler=
5060 cache_methods->get_one_authentic_pixel_from_handler;
5101static inline MagickBooleanType AcquireCacheNexusPixels(
5102 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5103 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5105 if (length != (MagickSizeType) ((
size_t) length))
5107 (void) ThrowMagickException(exception,GetMagickModule(),
5108 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5109 cache_info->filename);
5110 return(MagickFalse);
5112 nexus_info->length=0;
5113 nexus_info->mapped=MagickFalse;
5114 if (cache_anonymous_memory <= 0)
5116 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5118 if (nexus_info->cache != (Quantum *) NULL)
5119 (void) memset(nexus_info->cache,0,(
size_t) length);
5123 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5124 if (nexus_info->cache != (Quantum *) NULL)
5125 nexus_info->mapped=MagickTrue;
5127 if (nexus_info->cache == (Quantum *) NULL)
5129 (void) ThrowMagickException(exception,GetMagickModule(),
5130 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5131 cache_info->filename);
5132 return(MagickFalse);
5134 nexus_info->length=length;
5138static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5141 if (nexus_info->length < CACHE_LINE_SIZE)
5143 if (mode == ReadMode)
5145 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5149 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5152static Quantum *SetPixelCacheNexusPixels(
5153 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5154 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5155 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5156 ExceptionInfo *exception)
5165 assert(cache_info != (
const CacheInfo *) NULL);
5166 assert(cache_info->signature == MagickCoreSignature);
5167 if (cache_info->type == UndefinedCache)
5168 return((Quantum *) NULL);
5169 assert(nexus_info->signature == MagickCoreSignature);
5170 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5171 if ((width == 0) || (height == 0))
5173 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5174 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5175 return((Quantum *) NULL);
5177 if (((MagickSizeType) width > cache_info->width_limit) ||
5178 ((MagickSizeType) height > cache_info->height_limit))
5180 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5181 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5182 return((Quantum *) NULL);
5184 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5185 (IsValidPixelOffset(y,height) == MagickFalse))
5187 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5188 "InvalidPixel",
"`%s'",cache_info->filename);
5189 return((Quantum *) NULL);
5191 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5192 (buffered == MagickFalse))
5194 if (((x >= 0) && (y >= 0) &&
5195 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5196 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5197 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5205 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5206 return((Quantum *) NULL);
5207 offset=y*(MagickOffsetType) cache_info->columns+x;
5208 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5209 cache_info->number_channels*offset;
5210 nexus_info->metacontent=(
void *) NULL;
5211 if (cache_info->metacontent_extent != 0)
5212 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5213 offset*(MagickOffsetType) cache_info->metacontent_extent;
5214 nexus_info->region.width=width;
5215 nexus_info->region.height=height;
5216 nexus_info->region.x=x;
5217 nexus_info->region.y=y;
5218 nexus_info->authentic_pixel_cache=MagickTrue;
5219 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5220 return(nexus_info->pixels);
5226 number_pixels=(MagickSizeType) width*height;
5227 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5228 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5229 if (cache_info->metacontent_extent != 0)
5230 length+=number_pixels*cache_info->metacontent_extent;
5232 if (nexus_info->cache == (Quantum *) NULL)
5233 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5235 if (nexus_info->length < length)
5237 RelinquishCacheNexusPixels(nexus_info);
5238 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5240 if (status == MagickFalse)
5241 return((Quantum *) NULL);
5242 nexus_info->pixels=nexus_info->cache;
5243 nexus_info->metacontent=(
void *) NULL;
5244 if (cache_info->metacontent_extent != 0)
5245 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5246 cache_info->number_channels*number_pixels);
5247 nexus_info->region.width=width;
5248 nexus_info->region.height=height;
5249 nexus_info->region.x=x;
5250 nexus_info->region.y=y;
5251 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5252 MagickTrue : MagickFalse;
5253 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5254 return(nexus_info->pixels);
5287static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5288 ExceptionInfo *exception)
5291 *magick_restrict image_view;
5299 assert(image != (Image *) NULL);
5300 assert(image->signature == MagickCoreSignature);
5301 if (IsEventLogging() != MagickFalse)
5302 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5303 assert(image->cache != (Cache) NULL);
5304 image->alpha_trait=BlendPixelTrait;
5306 image_view=AcquireVirtualCacheView(image,exception);
5307#if defined(MAGICKCORE_OPENMP_SUPPORT)
5308 #pragma omp parallel for schedule(static) shared(status) \
5309 magick_number_threads(image,image,image->rows,2)
5311 for (y=0; y < (ssize_t) image->rows; y++)
5319 if (status == MagickFalse)
5321 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5322 if (q == (Quantum *) NULL)
5327 for (x=0; x < (ssize_t) image->columns; x++)
5329 SetPixelAlpha(image,alpha,q);
5330 q+=(ptrdiff_t) GetPixelChannels(image);
5332 status=SyncCacheViewAuthenticPixels(image_view,exception);
5334 image_view=DestroyCacheView(image_view);
5338MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5339 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5342 *magick_restrict cache_info;
5347 assert(image != (Image *) NULL);
5348 assert(image->signature == MagickCoreSignature);
5349 if (IsEventLogging() != MagickFalse)
5350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5351 assert(image->cache != (Cache) NULL);
5352 cache_info=(CacheInfo *) image->cache;
5353 assert(cache_info->signature == MagickCoreSignature);
5354 method=cache_info->virtual_pixel_method;
5355 cache_info->virtual_pixel_method=virtual_pixel_method;
5356 if ((image->columns != 0) && (image->rows != 0))
5357 switch (virtual_pixel_method)
5359 case BackgroundVirtualPixelMethod:
5361 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5362 ((image->alpha_trait & BlendPixelTrait) == 0))
5363 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5364 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5365 (IsGrayColorspace(image->colorspace) != MagickFalse))
5366 (void) SetImageColorspace(image,sRGBColorspace,exception);
5369 case TransparentVirtualPixelMethod:
5371 if ((image->alpha_trait & BlendPixelTrait) == 0)
5372 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5381#if defined(MAGICKCORE_OPENCL_SUPPORT)
5406static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5408 assert(cache_info != (CacheInfo *) NULL);
5409 assert(cache_info->signature == MagickCoreSignature);
5410 if ((cache_info->type != MemoryCache) ||
5411 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5416 LockSemaphoreInfo(cache_info->semaphore);
5417 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5418 UnlockSemaphoreInfo(cache_info->semaphore);
5421MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5424 *magick_restrict cache_info;
5426 assert(image != (
const Image *) NULL);
5427 cache_info=(CacheInfo *) image->cache;
5428 CopyOpenCLBuffer(cache_info);
5461MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5462 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5465 *magick_restrict cache_info;
5473 assert(image != (Image *) NULL);
5474 assert(image->signature == MagickCoreSignature);
5475 if (image->cache == (Cache) NULL)
5476 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5477 cache_info=(CacheInfo *) image->cache;
5478 assert(cache_info->signature == MagickCoreSignature);
5479 if (cache_info->type == UndefinedCache)
5480 return(MagickFalse);
5481 if (image->mask_trait != UpdatePixelTrait)
5483 if (((image->channels & WriteMaskChannel) != 0) &&
5484 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5485 return(MagickFalse);
5486 if (((image->channels & CompositeMaskChannel) != 0) &&
5487 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5488 return(MagickFalse);
5490 if (nexus_info->authentic_pixel_cache != MagickFalse)
5492 if (image->taint == MagickFalse)
5493 image->taint=MagickTrue;
5496 assert(cache_info->signature == MagickCoreSignature);
5497 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5498 if ((cache_info->metacontent_extent != 0) &&
5499 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5500 return(MagickFalse);
5501 if ((status != MagickFalse) && (image->taint == MagickFalse))
5502 image->taint=MagickTrue;
5533static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5534 ExceptionInfo *exception)
5537 *magick_restrict cache_info;
5540 id = GetOpenMPThreadId();
5545 assert(image != (Image *) NULL);
5546 assert(image->signature == MagickCoreSignature);
5547 assert(image->cache != (Cache) NULL);
5548 cache_info=(CacheInfo *) image->cache;
5549 assert(cache_info->signature == MagickCoreSignature);
5550 assert(
id < (
int) cache_info->number_threads);
5551 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5583MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5584 ExceptionInfo *exception)
5587 *magick_restrict cache_info;
5590 id = GetOpenMPThreadId();
5595 assert(image != (Image *) NULL);
5596 assert(image->signature == MagickCoreSignature);
5597 assert(image->cache != (Cache) NULL);
5598 cache_info=(CacheInfo *) image->cache;
5599 assert(cache_info->signature == MagickCoreSignature);
5600 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5602 status=cache_info->methods.sync_authentic_pixels_handler(image,
5606 assert(
id < (
int) cache_info->number_threads);
5607 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5639MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5640 ExceptionInfo *exception)
5643 *magick_restrict cache_info;
5645 assert(image != (Image *) NULL);
5646 assert(exception != (ExceptionInfo *) NULL);
5647 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5648 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5679static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5680 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5699 if (cache_info->metacontent_extent == 0)
5700 return(MagickFalse);
5701 if (nexus_info->authentic_pixel_cache != MagickFalse)
5703 if (nexus_info->metacontent == (
unsigned char *) NULL)
5704 return(MagickFalse);
5705 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5706 return(MagickFalse);
5707 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5708 nexus_info->region.x;
5709 length=(MagickSizeType) nexus_info->region.width*
5710 cache_info->metacontent_extent;
5711 extent=(MagickSizeType) length*nexus_info->region.height;
5712 rows=nexus_info->region.height;
5714 p=(
unsigned char *) nexus_info->metacontent;
5715 switch (cache_info->type)
5726 if ((cache_info->columns == nexus_info->region.width) &&
5727 (extent == (MagickSizeType) ((
size_t) extent)))
5732 q=(
unsigned char *) cache_info->metacontent+offset*
5733 (MagickOffsetType) cache_info->metacontent_extent;
5734 for (y=0; y < (ssize_t) rows; y++)
5736 (void) memcpy(q,p,(
size_t) length);
5737 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5738 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5747 LockSemaphoreInfo(cache_info->file_semaphore);
5748 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5750 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5751 cache_info->cache_filename);
5752 UnlockSemaphoreInfo(cache_info->file_semaphore);
5753 return(MagickFalse);
5755 if ((cache_info->columns == nexus_info->region.width) &&
5756 (extent <= MagickMaxBufferExtent))
5761 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5762 for (y=0; y < (ssize_t) rows; y++)
5764 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5765 (MagickOffsetType) extent*(MagickOffsetType)
5766 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5767 (MagickOffsetType) cache_info->metacontent_extent,length,
5768 (
const unsigned char *) p);
5769 if (count != (MagickOffsetType) length)
5771 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5772 offset+=(MagickOffsetType) cache_info->columns;
5774 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5775 (void) ClosePixelCacheOnDisk(cache_info);
5776 UnlockSemaphoreInfo(cache_info->file_semaphore);
5779 case DistributedCache:
5787 LockSemaphoreInfo(cache_info->file_semaphore);
5788 region=nexus_info->region;
5789 if ((cache_info->columns != nexus_info->region.width) ||
5790 (extent > MagickMaxBufferExtent))
5797 for (y=0; y < (ssize_t) rows; y++)
5799 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5800 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5801 if (count != (MagickOffsetType) length)
5803 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5806 UnlockSemaphoreInfo(cache_info->file_semaphore);
5812 if (y < (ssize_t) rows)
5814 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5815 cache_info->cache_filename);
5816 return(MagickFalse);
5818 if ((cache_info->debug != MagickFalse) &&
5819 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5820 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5821 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5822 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5823 nexus_info->region.x,(
double) nexus_info->region.y);
5855static MagickBooleanType WritePixelCachePixels(
5856 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5857 ExceptionInfo *exception)
5876 if (nexus_info->authentic_pixel_cache != MagickFalse)
5878 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5879 return(MagickFalse);
5880 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5881 nexus_info->region.x;
5882 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5884 extent=length*nexus_info->region.height;
5885 rows=nexus_info->region.height;
5887 p=nexus_info->pixels;
5888 switch (cache_info->type)
5899 if ((cache_info->columns == nexus_info->region.width) &&
5900 (extent == (MagickSizeType) ((
size_t) extent)))
5905 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5907 for (y=0; y < (ssize_t) rows; y++)
5909 (void) memcpy(q,p,(
size_t) length);
5910 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5911 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5920 LockSemaphoreInfo(cache_info->file_semaphore);
5921 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5923 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5924 cache_info->cache_filename);
5925 UnlockSemaphoreInfo(cache_info->file_semaphore);
5926 return(MagickFalse);
5928 if ((cache_info->columns == nexus_info->region.width) &&
5929 (extent <= MagickMaxBufferExtent))
5934 for (y=0; y < (ssize_t) rows; y++)
5936 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5937 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5938 sizeof(*p),length,(
const unsigned char *) p);
5939 if (count != (MagickOffsetType) length)
5941 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5942 offset+=(MagickOffsetType) cache_info->columns;
5944 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5945 (void) ClosePixelCacheOnDisk(cache_info);
5946 UnlockSemaphoreInfo(cache_info->file_semaphore);
5949 case DistributedCache:
5957 LockSemaphoreInfo(cache_info->file_semaphore);
5958 region=nexus_info->region;
5959 if ((cache_info->columns != nexus_info->region.width) ||
5960 (extent > MagickMaxBufferExtent))
5967 for (y=0; y < (ssize_t) rows; y++)
5969 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
5970 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5971 if (count != (MagickOffsetType) length)
5973 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5976 UnlockSemaphoreInfo(cache_info->file_semaphore);
5982 if (y < (ssize_t) rows)
5984 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5985 cache_info->cache_filename);
5986 return(MagickFalse);
5988 if ((cache_info->debug != MagickFalse) &&
5989 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5990 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5991 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5992 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5993 nexus_info->region.x,(
double) nexus_info->region.y);