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)
114 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
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,
127 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
130 ReadPixelCacheMetacontent(
CacheInfo *magick_restrict,
139 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
141 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
143 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
144 const ssize_t,
const ssize_t,
const size_t,
const size_t,
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));
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)));
270 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
271 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
272 2*
sizeof(**nexus_info));
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,
318 *magick_restrict cache_info;
320 assert(image != (
const Image *) NULL);
321 assert(image->signature == MagickCoreSignature);
323 assert(exception->signature == MagickCoreSignature);
324 assert(image->cache != (Cache) NULL);
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,
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))
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);
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);
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);
561 assert(cache_info->signature == MagickCoreSignature);
562 source_info->methods=cache_info->methods;
594static MagickBooleanType ClonePixelCacheOnDisk(
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(
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);
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);
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';
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);
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);
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;
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);
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);
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,
1286 *magick_restrict cache_info;
1288 assert(image != (
const Image *) NULL);
1289 assert(device != (
const MagickCLDevice) NULL);
1291 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1293 SyncImagePixelCache((
Image *) image,exception);
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,
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);
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);
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);
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,
1518 *magick_restrict cache_info;
1521 id = GetOpenMPThreadId();
1526 assert(image != (
Image *) NULL);
1527 assert(image->signature == MagickCoreSignature);
1528 assert(image->cache != (Cache) NULL);
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,
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);
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);
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;
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,
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);
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);
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);
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);
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);
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);
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,
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);
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,
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);
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);
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);
2259 assert(cache_info->signature == MagickCoreSignature);
2260 return(cache_info->cache_filename);
2285MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
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,
2334 *magick_restrict cache_info;
2339 assert(cache != NULL);
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,
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);
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);
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);
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);
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);
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,
2589 *magick_restrict cache_info;
2591 assert(cache != (Cache) NULL);
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);
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,
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);
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);
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);
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,
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);
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);
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,
3420 *magick_restrict cache_info;
3422 assert(cache != (Cache) NULL);
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,
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))
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 inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3565 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3570 if ((count == 0) || (quantum == 0))
3572 length=count*quantum;
3573 if (quantum != (length/count))
3580 return(MagickFalse);
3583static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3592 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3594 if (*cache_info->cache_filename ==
'\0')
3595 file=AcquireUniqueFileResource(cache_info->cache_filename);
3601 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3606 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3607 O_BINARY | O_EXCL,S_MODE);
3609 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3615 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3618 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3623 return(MagickFalse);
3624 (void) AcquireMagickResource(FileResource,1);
3625 if (cache_info->file != -1)
3626 (void) ClosePixelCacheOnDisk(cache_info);
3627 cache_info->file=file;
3628 cache_info->disk_mode=mode;
3632static inline MagickOffsetType WritePixelCacheRegion(
3633 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3634 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3642#if !defined(MAGICKCORE_HAVE_PWRITE)
3643 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3644 return((MagickOffsetType) -1);
3646 for (i=0; i < (MagickOffsetType) length; i+=count)
3648#if !defined(MAGICKCORE_HAVE_PWRITE)
3649 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3650 (MagickSizeType) i,MagickMaxBufferExtent));
3652 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3653 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3665static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3668 *magick_restrict cache_info;
3674 if (cache_info->debug != MagickFalse)
3677 format[MagickPathExtent],
3678 message[MagickPathExtent];
3680 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3681 (void) FormatLocaleString(message,MagickPathExtent,
3682 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3683 cache_info->cache_filename,cache_info->file,format);
3684 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3686 if (length != (MagickSizeType) ((MagickOffsetType) length))
3687 return(MagickFalse);
3688 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3690 return(MagickFalse);
3691 if ((MagickSizeType) offset < length)
3697 extent=(MagickOffsetType) length-1;
3698 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3701 return(MagickFalse);
3702#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3703 if (cache_info->synchronize != MagickFalse)
3704 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3705 return(MagickFalse);
3708 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3710 return(MagickFalse);
3714static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3718 *magick_restrict cache_info,
3722 format[MagickPathExtent],
3723 message[MagickPathExtent];
3740 assert(image != (
const Image *) NULL);
3741 assert(image->signature == MagickCoreSignature);
3742 assert(image->cache != (Cache) NULL);
3743 if (IsEventLogging() != MagickFalse)
3744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3745 if (cache_anonymous_memory < 0)
3753 cache_anonymous_memory=0;
3754 value=GetPolicyValue(
"pixel-cache-memory");
3755 if (value == (
char *) NULL)
3756 value=GetPolicyValue(
"cache:memory-map");
3757 if (LocaleCompare(value,
"anonymous") == 0)
3759#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3760 cache_anonymous_memory=1;
3762 (void) ThrowMagickException(exception,GetMagickModule(),
3763 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3764 "`%s' (policy requires anonymous memory mapping)",image->filename);
3767 value=DestroyString(value);
3769 if ((image->columns == 0) || (image->rows == 0))
3770 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3772 assert(cache_info->signature == MagickCoreSignature);
3773 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3774 ((MagickSizeType) image->rows > cache_info->height_limit))
3776 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3777 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3778 image->filename, (double) image->columns, (
double) image->rows,
3779 (double) cache_info->width_limit,(
double) cache_info->height_limit);
3780 return(MagickFalse);
3782 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3784 length=GetImageListLength(image);
3785 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3786 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3789 source_info=(*cache_info);
3790 source_info.file=(-1);
3791 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3792 image->filename,(
double) image->scene);
3793 cache_info->storage_class=image->storage_class;
3794 cache_info->colorspace=image->colorspace;
3795 cache_info->alpha_trait=image->alpha_trait;
3796 cache_info->channels=image->channels;
3797 cache_info->rows=image->rows;
3798 cache_info->columns=image->columns;
3799 status=ResetPixelChannelMap(image,exception);
3800 if (status == MagickFalse)
3801 return(MagickFalse);
3802 cache_info->number_channels=GetPixelChannels(image);
3803 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3804 sizeof(*image->channel_map));
3805 cache_info->metacontent_extent=image->metacontent_extent;
3806 cache_info->mode=mode;
3807 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3808 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3809 if (image->metacontent_extent != 0)
3810 packet_size+=cache_info->metacontent_extent;
3811 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3813 cache_info->storage_class=UndefinedClass;
3814 cache_info->length=0;
3815 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3818 columns=(size_t) (length/cache_info->rows/packet_size);
3819 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3820 ((ssize_t) cache_info->rows < 0))
3822 cache_info->storage_class=UndefinedClass;
3823 cache_info->length=0;
3824 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3827 cache_info->length=length;
3828 if (image->ping != MagickFalse)
3830 cache_info->type=PingCache;
3833 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3834 cache_info->columns*cache_info->rows);
3835 if (cache_info->mode == PersistMode)
3837 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3838 cache_info->metacontent_extent);
3839 if ((status != MagickFalse) &&
3840 (length == (MagickSizeType) ((
size_t) length)) &&
3841 ((cache_info->type == UndefinedCache) ||
3842 (cache_info->type == MemoryCache)))
3844 status=AcquireMagickResource(MemoryResource,cache_info->length);
3845 if (status != MagickFalse)
3848 if (cache_anonymous_memory <= 0)
3850 cache_info->mapped=MagickFalse;
3851 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3852 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3856 cache_info->mapped=MagickTrue;
3857 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3858 cache_info->length);
3860 if (cache_info->pixels == (Quantum *) NULL)
3862 cache_info->mapped=source_info.mapped;
3863 cache_info->pixels=source_info.pixels;
3870 cache_info->type=MemoryCache;
3871 cache_info->metacontent=(
void *) NULL;
3872 if (cache_info->metacontent_extent != 0)
3873 cache_info->metacontent=(
void *) (cache_info->pixels+
3874 cache_info->number_channels*number_pixels);
3875 if ((source_info.storage_class != UndefinedClass) &&
3878 status=ClonePixelCacheRepository(cache_info,&source_info,
3880 RelinquishPixelCachePixels(&source_info);
3882 if (cache_info->debug != MagickFalse)
3884 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3885 MagickPathExtent,format);
3886 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3888 (void) FormatLocaleString(message,MagickPathExtent,
3889 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3890 cache_info->filename,cache_info->mapped != MagickFalse ?
3891 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3892 (double) cache_info->rows,(double)
3893 cache_info->number_channels,format);
3894 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3897 cache_info->storage_class=image->storage_class;
3900 if ((source_info.storage_class != UndefinedClass) &&
3902 RelinquishPixelCachePixels(&source_info);
3903 cache_info->type=UndefinedCache;
3904 return(MagickFalse);
3910 status=AcquireMagickResource(DiskResource,cache_info->length);
3911 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3913 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3921 server_info=AcquireDistributeCacheInfo(exception);
3924 status=OpenDistributePixelCache(server_info,image);
3925 if (status == MagickFalse)
3927 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3928 GetDistributeCacheHostname(server_info));
3929 server_info=DestroyDistributeCacheInfo(server_info);
3937 cache_info->type=DistributedCache;
3938 cache_info->server_info=server_info;
3939 (void) FormatLocaleString(cache_info->cache_filename,
3940 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3943 cache_info->server_info));
3944 if ((source_info.storage_class != UndefinedClass) &&
3947 status=ClonePixelCacheRepository(cache_info,&source_info,
3949 RelinquishPixelCachePixels(&source_info);
3951 if (cache_info->debug != MagickFalse)
3953 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3954 MagickPathExtent,format);
3955 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3957 (void) FormatLocaleString(message,MagickPathExtent,
3958 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3959 cache_info->filename,cache_info->cache_filename,
3961 cache_info->server_info),type,(double) cache_info->columns,
3962 (
double) cache_info->rows,(double)
3963 cache_info->number_channels,format);
3964 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3969 if ((source_info.storage_class != UndefinedClass) &&
3971 RelinquishPixelCachePixels(&source_info);
3972 cache_info->type=UndefinedCache;
3973 return(MagickFalse);
3978 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3979 RelinquishPixelCachePixels(&source_info);
3980 cache_info->type=UndefinedCache;
3981 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3982 "CacheResourcesExhausted",
"`%s'",image->filename);
3983 return(MagickFalse);
3988 if (status == MagickFalse)
3990 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3991 RelinquishPixelCachePixels(&source_info);
3992 cache_info->type=UndefinedCache;
3993 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3994 "CacheResourcesExhausted",
"`%s'",image->filename);
3995 return(MagickFalse);
3997 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3998 (cache_info->mode != PersistMode))
4000 (void) ClosePixelCacheOnDisk(cache_info);
4001 *cache_info->cache_filename=
'\0';
4003 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
4005 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4006 RelinquishPixelCachePixels(&source_info);
4007 cache_info->type=UndefinedCache;
4008 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
4010 return(MagickFalse);
4012 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
4013 cache_info->length);
4014 if (status == MagickFalse)
4016 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4017 RelinquishPixelCachePixels(&source_info);
4018 cache_info->type=UndefinedCache;
4019 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
4021 return(MagickFalse);
4023 cache_info->type=DiskCache;
4024 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
4025 cache_info->metacontent_extent);
4026 if (length == (MagickSizeType) ((
size_t) length))
4028 status=AcquireMagickResource(MapResource,cache_info->length);
4029 if (status != MagickFalse)
4031 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4032 cache_info->offset,(
size_t) cache_info->length);
4033 if (cache_info->pixels == (Quantum *) NULL)
4035 cache_info->mapped=source_info.mapped;
4036 cache_info->pixels=source_info.pixels;
4037 RelinquishMagickResource(MapResource,cache_info->length);
4044 (void) ClosePixelCacheOnDisk(cache_info);
4045 cache_info->type=MapCache;
4046 cache_info->mapped=MagickTrue;
4047 cache_info->metacontent=(
void *) NULL;
4048 if (cache_info->metacontent_extent != 0)
4049 cache_info->metacontent=(
void *) (cache_info->pixels+
4050 cache_info->number_channels*number_pixels);
4051 if ((source_info.storage_class != UndefinedClass) &&
4054 status=ClonePixelCacheRepository(cache_info,&source_info,
4056 RelinquishPixelCachePixels(&source_info);
4058 if (cache_info->debug != MagickFalse)
4060 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4061 MagickPathExtent,format);
4062 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4064 (void) FormatLocaleString(message,MagickPathExtent,
4065 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4066 cache_info->filename,cache_info->cache_filename,
4067 cache_info->file,type,(
double) cache_info->columns,
4068 (double) cache_info->rows,(
double)
4069 cache_info->number_channels,format);
4070 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4075 if ((source_info.storage_class != UndefinedClass) &&
4077 RelinquishPixelCachePixels(&source_info);
4078 cache_info->type=UndefinedCache;
4079 return(MagickFalse);
4086 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4088 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4089 RelinquishPixelCachePixels(&source_info);
4091 if (cache_info->debug != MagickFalse)
4093 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4094 MagickPathExtent,format);
4095 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4097 (void) FormatLocaleString(message,MagickPathExtent,
4098 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4099 cache_info->cache_filename,cache_info->file,type,(
double)
4100 cache_info->columns,(double) cache_info->rows,(
double)
4101 cache_info->number_channels,format);
4102 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4106 cache_info->type=UndefinedCache;
4107 return(MagickFalse);
4149MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4150 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4154 *magick_restrict cache_info,
4155 *magick_restrict clone_info;
4163 assert(image != (
Image *) NULL);
4164 assert(image->signature == MagickCoreSignature);
4165 if (IsEventLogging() != MagickFalse)
4166 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4167 assert(image->cache != (
void *) NULL);
4168 assert(filename != (
const char *) NULL);
4169 assert(offset != (MagickOffsetType *) NULL);
4170 page_size=GetMagickPageSize();
4172 assert(cache_info->signature == MagickCoreSignature);
4173#if defined(MAGICKCORE_OPENCL_SUPPORT)
4174 CopyOpenCLBuffer(cache_info);
4176 if (attach != MagickFalse)
4181 if (cache_info->debug != MagickFalse)
4182 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4183 "attach persistent cache");
4184 (void) CopyMagickString(cache_info->cache_filename,filename,
4186 cache_info->type=MapCache;
4187 cache_info->offset=(*offset);
4188 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4189 return(MagickFalse);
4190 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4191 ((MagickOffsetType) cache_info->length % page_size));
4197 status=AcquireMagickResource(DiskResource,cache_info->length);
4198 if (status == MagickFalse)
4200 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4201 "CacheResourcesExhausted",
"`%s'",image->filename);
4202 return(MagickFalse);
4204 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4205 clone_info->type=DiskCache;
4206 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4207 clone_info->file=(-1);
4208 clone_info->storage_class=cache_info->storage_class;
4209 clone_info->colorspace=cache_info->colorspace;
4210 clone_info->alpha_trait=cache_info->alpha_trait;
4211 clone_info->channels=cache_info->channels;
4212 clone_info->columns=cache_info->columns;
4213 clone_info->rows=cache_info->rows;
4214 clone_info->number_channels=cache_info->number_channels;
4215 clone_info->metacontent_extent=cache_info->metacontent_extent;
4216 clone_info->mode=PersistMode;
4217 clone_info->length=cache_info->length;
4218 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4219 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4220 clone_info->offset=(*offset);
4221 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4222 if (status != MagickFalse)
4223 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4224 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4225 ((MagickOffsetType) cache_info->length % page_size));
4226 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4268MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4269 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4273 *magick_restrict cache_info;
4282 *magick_restrict pixels;
4287 assert(image != (
const Image *) NULL);
4288 assert(image->signature == MagickCoreSignature);
4289 assert(image->cache != (Cache) NULL);
4290 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4291 if (cache_info == (Cache) NULL)
4292 return((Quantum *) NULL);
4293 assert(cache_info->signature == MagickCoreSignature);
4294 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4295 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4296 (y >= (ssize_t) cache_info->rows))
4298 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4299 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4300 return((Quantum *) NULL);
4302 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4303 return((Quantum *) NULL);
4304 offset=y*(MagickOffsetType) cache_info->columns+x;
4306 return((Quantum *) NULL);
4307 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4308 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4309 (MagickOffsetType) columns-1;
4310 if ((MagickSizeType) offset >= number_pixels)
4311 return((Quantum *) NULL);
4315 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4316 ((image->channels & WriteMaskChannel) != 0) ||
4317 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4318 nexus_info,exception);
4355static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4356 const ssize_t y,
const size_t columns,
const size_t rows,
4360 *magick_restrict cache_info;
4363 id = GetOpenMPThreadId();
4366 *magick_restrict pixels;
4368 assert(image != (
const Image *) NULL);
4369 assert(image->signature == MagickCoreSignature);
4370 assert(image->cache != (Cache) NULL);
4372 assert(cache_info->signature == MagickCoreSignature);
4373 assert(
id < (
int) cache_info->number_threads);
4374 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4375 cache_info->nexus_info[
id],exception);
4435MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4436 const ssize_t y,
const size_t columns,
const size_t rows,
4440 *magick_restrict cache_info;
4443 id = GetOpenMPThreadId();
4446 *magick_restrict pixels;
4448 assert(image != (
Image *) NULL);
4449 assert(image->signature == MagickCoreSignature);
4450 assert(image->cache != (Cache) NULL);
4452 assert(cache_info->signature == MagickCoreSignature);
4453 if (cache_info->methods.queue_authentic_pixels_handler !=
4454 (QueueAuthenticPixelsHandler) NULL)
4456 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4457 columns,rows,exception);
4460 assert(
id < (
int) cache_info->number_threads);
4461 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4462 cache_info->nexus_info[
id],exception);
4495static inline MagickOffsetType ReadPixelCacheRegion(
4496 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4497 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4505#if !defined(MAGICKCORE_HAVE_PREAD)
4506 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4507 return((MagickOffsetType) -1);
4509 for (i=0; i < (MagickOffsetType) length; i+=count)
4511#if !defined(MAGICKCORE_HAVE_PREAD)
4512 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4513 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4515 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4516 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4528static MagickBooleanType ReadPixelCacheMetacontent(
4549 if (cache_info->metacontent_extent == 0)
4550 return(MagickFalse);
4551 if (nexus_info->authentic_pixel_cache != MagickFalse)
4553 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4554 return(MagickFalse);
4555 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4556 nexus_info->region.x;
4557 length=(MagickSizeType) nexus_info->region.width*
4558 cache_info->metacontent_extent;
4559 extent=length*nexus_info->region.height;
4560 rows=nexus_info->region.height;
4562 q=(
unsigned char *) nexus_info->metacontent;
4563 switch (cache_info->type)
4574 if ((cache_info->columns == nexus_info->region.width) &&
4575 (extent == (MagickSizeType) ((
size_t) extent)))
4580 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4581 cache_info->metacontent_extent;
4582 for (y=0; y < (ssize_t) rows; y++)
4584 (void) memcpy(q,p,(
size_t) length);
4585 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4586 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4595 LockSemaphoreInfo(cache_info->file_semaphore);
4596 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4598 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4599 cache_info->cache_filename);
4600 UnlockSemaphoreInfo(cache_info->file_semaphore);
4601 return(MagickFalse);
4603 if ((cache_info->columns == nexus_info->region.width) &&
4604 (extent <= MagickMaxBufferExtent))
4609 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4610 for (y=0; y < (ssize_t) rows; y++)
4612 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4613 (MagickOffsetType) extent*(MagickOffsetType)
4614 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4615 (MagickOffsetType) cache_info->metacontent_extent,length,
4616 (
unsigned char *) q);
4617 if (count != (MagickOffsetType) length)
4619 offset+=(MagickOffsetType) cache_info->columns;
4620 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4622 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4623 (void) ClosePixelCacheOnDisk(cache_info);
4624 UnlockSemaphoreInfo(cache_info->file_semaphore);
4627 case DistributedCache:
4635 LockSemaphoreInfo(cache_info->file_semaphore);
4636 region=nexus_info->region;
4637 if ((cache_info->columns != nexus_info->region.width) ||
4638 (extent > MagickMaxBufferExtent))
4645 for (y=0; y < (ssize_t) rows; y++)
4648 cache_info->server_info,®ion,length,(
unsigned char *) q);
4649 if (count != (MagickOffsetType) length)
4651 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4654 UnlockSemaphoreInfo(cache_info->file_semaphore);
4660 if (y < (ssize_t) rows)
4662 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4663 cache_info->cache_filename);
4664 return(MagickFalse);
4666 if ((cache_info->debug != MagickFalse) &&
4667 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4668 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4669 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4670 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4671 nexus_info->region.x,(
double) nexus_info->region.y);
4703static MagickBooleanType ReadPixelCachePixels(
4725 if (nexus_info->authentic_pixel_cache != MagickFalse)
4727 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4728 return(MagickFalse);
4729 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4730 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4731 return(MagickFalse);
4732 offset+=nexus_info->region.x;
4733 number_channels=cache_info->number_channels;
4734 length=(MagickSizeType) number_channels*nexus_info->region.width*
4736 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4737 return(MagickFalse);
4738 rows=nexus_info->region.height;
4740 if ((extent == 0) || ((extent/length) != rows))
4741 return(MagickFalse);
4743 q=nexus_info->pixels;
4744 switch (cache_info->type)
4755 if ((cache_info->columns == nexus_info->region.width) &&
4756 (extent == (MagickSizeType) ((
size_t) extent)))
4761 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4763 for (y=0; y < (ssize_t) rows; y++)
4765 (void) memcpy(q,p,(
size_t) length);
4766 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4767 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4776 LockSemaphoreInfo(cache_info->file_semaphore);
4777 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4779 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4780 cache_info->cache_filename);
4781 UnlockSemaphoreInfo(cache_info->file_semaphore);
4782 return(MagickFalse);
4784 if ((cache_info->columns == nexus_info->region.width) &&
4785 (extent <= MagickMaxBufferExtent))
4790 for (y=0; y < (ssize_t) rows; y++)
4792 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4793 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4794 sizeof(*q),length,(
unsigned char *) q);
4795 if (count != (MagickOffsetType) length)
4797 offset+=(MagickOffsetType) cache_info->columns;
4798 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4800 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4801 (void) ClosePixelCacheOnDisk(cache_info);
4802 UnlockSemaphoreInfo(cache_info->file_semaphore);
4805 case DistributedCache:
4813 LockSemaphoreInfo(cache_info->file_semaphore);
4814 region=nexus_info->region;
4815 if ((cache_info->columns != nexus_info->region.width) ||
4816 (extent > MagickMaxBufferExtent))
4823 for (y=0; y < (ssize_t) rows; y++)
4826 cache_info->server_info,®ion,length,(
unsigned char *) q);
4827 if (count != (MagickOffsetType) length)
4829 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4832 UnlockSemaphoreInfo(cache_info->file_semaphore);
4838 if (y < (ssize_t) rows)
4840 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4841 cache_info->cache_filename);
4842 return(MagickFalse);
4844 if ((cache_info->debug != MagickFalse) &&
4845 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4846 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4847 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4848 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4849 nexus_info->region.x,(
double) nexus_info->region.y);
4876MagickPrivate Cache ReferencePixelCache(Cache cache)
4879 *magick_restrict cache_info;
4881 assert(cache != (Cache *) NULL);
4883 assert(cache_info->signature == MagickCoreSignature);
4884 LockSemaphoreInfo(cache_info->semaphore);
4885 cache_info->reference_count++;
4886 UnlockSemaphoreInfo(cache_info->semaphore);
4912MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4915 *magick_restrict cache_info;
4917 assert(image != (
const Image *) NULL);
4918 assert(image->signature == MagickCoreSignature);
4919 assert(image->cache != (Cache) NULL);
4921 assert(cache_info->signature == MagickCoreSignature);
4922 cache_info->number_channels=GetPixelChannels(image);
4943MagickPrivate
void ResetCacheAnonymousMemory(
void)
4945 cache_anonymous_memory=0;
4977MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4978 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4986 assert(image != (
Image *) NULL);
4987 assert(image->signature == MagickCoreSignature);
4988 if (IsEventLogging() != MagickFalse)
4989 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4990 assert(image->cache != (
void *) NULL);
4991 extent=(MagickSizeType) columns*rows;
4992 if (extent > ((MagickSizeType) image->columns*image->rows))
4993 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4995 image->columns=columns;
4998 cache_info->columns=columns;
4999 cache_info->rows=rows;
5000 return(SyncImagePixelCache(image,exception));
5027MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
5030 *magick_restrict cache_info;
5032 GetOneAuthenticPixelFromHandler
5033 get_one_authentic_pixel_from_handler;
5035 GetOneVirtualPixelFromHandler
5036 get_one_virtual_pixel_from_handler;
5041 assert(cache != (Cache) NULL);
5044 assert(cache_info->signature == MagickCoreSignature);
5045 if (IsEventLogging() != MagickFalse)
5046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5047 cache_info->filename);
5048 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5049 cache_info->methods.get_virtual_pixel_handler=
5050 cache_methods->get_virtual_pixel_handler;
5051 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5052 cache_info->methods.destroy_pixel_handler=
5053 cache_methods->destroy_pixel_handler;
5054 if (cache_methods->get_virtual_metacontent_from_handler !=
5055 (GetVirtualMetacontentFromHandler) NULL)
5056 cache_info->methods.get_virtual_metacontent_from_handler=
5057 cache_methods->get_virtual_metacontent_from_handler;
5058 if (cache_methods->get_authentic_pixels_handler !=
5059 (GetAuthenticPixelsHandler) NULL)
5060 cache_info->methods.get_authentic_pixels_handler=
5061 cache_methods->get_authentic_pixels_handler;
5062 if (cache_methods->queue_authentic_pixels_handler !=
5063 (QueueAuthenticPixelsHandler) NULL)
5064 cache_info->methods.queue_authentic_pixels_handler=
5065 cache_methods->queue_authentic_pixels_handler;
5066 if (cache_methods->sync_authentic_pixels_handler !=
5067 (SyncAuthenticPixelsHandler) NULL)
5068 cache_info->methods.sync_authentic_pixels_handler=
5069 cache_methods->sync_authentic_pixels_handler;
5070 if (cache_methods->get_authentic_pixels_from_handler !=
5071 (GetAuthenticPixelsFromHandler) NULL)
5072 cache_info->methods.get_authentic_pixels_from_handler=
5073 cache_methods->get_authentic_pixels_from_handler;
5074 if (cache_methods->get_authentic_metacontent_from_handler !=
5075 (GetAuthenticMetacontentFromHandler) NULL)
5076 cache_info->methods.get_authentic_metacontent_from_handler=
5077 cache_methods->get_authentic_metacontent_from_handler;
5078 get_one_virtual_pixel_from_handler=
5079 cache_info->methods.get_one_virtual_pixel_from_handler;
5080 if (get_one_virtual_pixel_from_handler !=
5081 (GetOneVirtualPixelFromHandler) NULL)
5082 cache_info->methods.get_one_virtual_pixel_from_handler=
5083 cache_methods->get_one_virtual_pixel_from_handler;
5084 get_one_authentic_pixel_from_handler=
5085 cache_methods->get_one_authentic_pixel_from_handler;
5086 if (get_one_authentic_pixel_from_handler !=
5087 (GetOneAuthenticPixelFromHandler) NULL)
5088 cache_info->methods.get_one_authentic_pixel_from_handler=
5089 cache_methods->get_one_authentic_pixel_from_handler;
5130static inline MagickBooleanType AcquireCacheNexusPixels(
5131 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5134 if (length != (MagickSizeType) ((
size_t) length))
5136 (void) ThrowMagickException(exception,GetMagickModule(),
5137 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5138 cache_info->filename);
5139 return(MagickFalse);
5141 nexus_info->length=0;
5142 nexus_info->mapped=MagickFalse;
5143 if (cache_anonymous_memory <= 0)
5145 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5147 if (nexus_info->cache != (Quantum *) NULL)
5148 (
void) memset(nexus_info->cache,0,(
size_t) length);
5152 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5153 if (nexus_info->cache != (Quantum *) NULL)
5154 nexus_info->mapped=MagickTrue;
5156 if (nexus_info->cache == (Quantum *) NULL)
5158 (void) ThrowMagickException(exception,GetMagickModule(),
5159 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5160 cache_info->filename);
5161 return(MagickFalse);
5163 nexus_info->length=length;
5167static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5170 if (nexus_info->length < CACHE_LINE_SIZE)
5172 if (mode == ReadMode)
5174 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5178 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5181static Quantum *SetPixelCacheNexusPixels(
5182 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5183 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5184 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5194 assert(cache_info != (
const CacheInfo *) NULL);
5195 assert(cache_info->signature == MagickCoreSignature);
5196 if (cache_info->type == UndefinedCache)
5197 return((Quantum *) NULL);
5198 assert(nexus_info->signature == MagickCoreSignature);
5199 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5200 if ((width == 0) || (height == 0))
5202 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5203 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5204 return((Quantum *) NULL);
5206 if (((MagickSizeType) width > cache_info->width_limit) ||
5207 ((MagickSizeType) height > cache_info->height_limit))
5209 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5210 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5211 return((Quantum *) NULL);
5213 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5214 (IsValidPixelOffset(y,height) == MagickFalse))
5216 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5217 "InvalidPixel",
"`%s'",cache_info->filename);
5218 return((Quantum *) NULL);
5220 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5221 (buffered == MagickFalse))
5223 if (((x >= 0) && (y >= 0) &&
5224 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5225 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5226 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5234 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5235 return((Quantum *) NULL);
5236 offset=y*(MagickOffsetType) cache_info->columns+x;
5237 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5238 cache_info->number_channels*offset;
5239 nexus_info->metacontent=(
void *) NULL;
5240 if (cache_info->metacontent_extent != 0)
5241 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5242 offset*(MagickOffsetType) cache_info->metacontent_extent;
5243 nexus_info->region.width=width;
5244 nexus_info->region.height=height;
5245 nexus_info->region.x=x;
5246 nexus_info->region.y=y;
5247 nexus_info->authentic_pixel_cache=MagickTrue;
5248 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5249 return(nexus_info->pixels);
5255 number_pixels=(MagickSizeType) width*height;
5256 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5257 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5258 if (cache_info->metacontent_extent != 0)
5259 length+=number_pixels*cache_info->metacontent_extent;
5261 if (nexus_info->cache == (Quantum *) NULL)
5262 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5264 if (nexus_info->length < length)
5266 RelinquishCacheNexusPixels(nexus_info);
5267 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5269 if (status == MagickFalse)
5270 return((Quantum *) NULL);
5271 nexus_info->pixels=nexus_info->cache;
5272 nexus_info->metacontent=(
void *) NULL;
5273 if (cache_info->metacontent_extent != 0)
5274 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5275 cache_info->number_channels*number_pixels);
5276 nexus_info->region.width=width;
5277 nexus_info->region.height=height;
5278 nexus_info->region.x=x;
5279 nexus_info->region.y=y;
5280 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5281 MagickTrue : MagickFalse;
5282 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5283 return(nexus_info->pixels);
5316static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5320 *magick_restrict image_view;
5328 assert(image != (
Image *) NULL);
5329 assert(image->signature == MagickCoreSignature);
5330 if (IsEventLogging() != MagickFalse)
5331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5332 assert(image->cache != (Cache) NULL);
5333 image->alpha_trait=BlendPixelTrait;
5335 image_view=AcquireVirtualCacheView(image,exception);
5336#if defined(MAGICKCORE_OPENMP_SUPPORT)
5337 #pragma omp parallel for schedule(static) shared(status) \
5338 magick_number_threads(image,image,image->rows,2)
5340 for (y=0; y < (ssize_t) image->rows; y++)
5348 if (status == MagickFalse)
5350 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5351 if (q == (Quantum *) NULL)
5356 for (x=0; x < (ssize_t) image->columns; x++)
5358 SetPixelAlpha(image,alpha,q);
5359 q+=(ptrdiff_t) GetPixelChannels(image);
5361 status=SyncCacheViewAuthenticPixels(image_view,exception);
5363 image_view=DestroyCacheView(image_view);
5367MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5368 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5371 *magick_restrict cache_info;
5376 assert(image != (
Image *) NULL);
5377 assert(image->signature == MagickCoreSignature);
5378 if (IsEventLogging() != MagickFalse)
5379 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5380 assert(image->cache != (Cache) NULL);
5382 assert(cache_info->signature == MagickCoreSignature);
5383 method=cache_info->virtual_pixel_method;
5384 cache_info->virtual_pixel_method=virtual_pixel_method;
5385 if ((image->columns != 0) && (image->rows != 0))
5386 switch (virtual_pixel_method)
5388 case BackgroundVirtualPixelMethod:
5390 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5391 ((image->alpha_trait & BlendPixelTrait) == 0))
5392 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5393 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5394 (IsGrayColorspace(image->colorspace) != MagickFalse))
5395 (void) SetImageColorspace(image,sRGBColorspace,exception);
5398 case TransparentVirtualPixelMethod:
5400 if ((image->alpha_trait & BlendPixelTrait) == 0)
5401 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5410#if defined(MAGICKCORE_OPENCL_SUPPORT)
5435static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5437 assert(cache_info != (
CacheInfo *) NULL);
5438 assert(cache_info->signature == MagickCoreSignature);
5439 if ((cache_info->type != MemoryCache) ||
5440 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5445 LockSemaphoreInfo(cache_info->semaphore);
5446 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5447 UnlockSemaphoreInfo(cache_info->semaphore);
5450MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5453 *magick_restrict cache_info;
5455 assert(image != (
const Image *) NULL);
5457 CopyOpenCLBuffer(cache_info);
5490MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5494 *magick_restrict cache_info;
5502 assert(image != (
Image *) NULL);
5503 assert(image->signature == MagickCoreSignature);
5504 if (image->cache == (Cache) NULL)
5505 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5507 assert(cache_info->signature == MagickCoreSignature);
5508 if (cache_info->type == UndefinedCache)
5509 return(MagickFalse);
5510 if (image->mask_trait != UpdatePixelTrait)
5512 if (((image->channels & WriteMaskChannel) != 0) &&
5513 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5514 return(MagickFalse);
5515 if (((image->channels & CompositeMaskChannel) != 0) &&
5516 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5517 return(MagickFalse);
5519 if (nexus_info->authentic_pixel_cache != MagickFalse)
5521 if (image->taint == MagickFalse)
5522 image->taint=MagickTrue;
5525 assert(cache_info->signature == MagickCoreSignature);
5526 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5527 if ((cache_info->metacontent_extent != 0) &&
5528 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5529 return(MagickFalse);
5530 if ((status != MagickFalse) && (image->taint == MagickFalse))
5531 image->taint=MagickTrue;
5562static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5566 *magick_restrict cache_info;
5569 id = GetOpenMPThreadId();
5574 assert(image != (
Image *) NULL);
5575 assert(image->signature == MagickCoreSignature);
5576 assert(image->cache != (Cache) NULL);
5578 assert(cache_info->signature == MagickCoreSignature);
5579 assert(
id < (
int) cache_info->number_threads);
5580 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5612MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5616 *magick_restrict cache_info;
5619 id = GetOpenMPThreadId();
5624 assert(image != (
Image *) NULL);
5625 assert(image->signature == MagickCoreSignature);
5626 assert(image->cache != (Cache) NULL);
5628 assert(cache_info->signature == MagickCoreSignature);
5629 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5631 status=cache_info->methods.sync_authentic_pixels_handler(image,
5635 assert(
id < (
int) cache_info->number_threads);
5636 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5668MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5672 *magick_restrict cache_info;
5674 assert(image != (
Image *) NULL);
5676 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5677 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5708static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5728 if (cache_info->metacontent_extent == 0)
5729 return(MagickFalse);
5730 if (nexus_info->authentic_pixel_cache != MagickFalse)
5732 if (nexus_info->metacontent == (
unsigned char *) NULL)
5733 return(MagickFalse);
5734 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5735 return(MagickFalse);
5736 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5737 nexus_info->region.x;
5738 length=(MagickSizeType) nexus_info->region.width*
5739 cache_info->metacontent_extent;
5740 extent=(MagickSizeType) length*nexus_info->region.height;
5741 rows=nexus_info->region.height;
5743 p=(
unsigned char *) nexus_info->metacontent;
5744 switch (cache_info->type)
5755 if ((cache_info->columns == nexus_info->region.width) &&
5756 (extent == (MagickSizeType) ((
size_t) extent)))
5761 q=(
unsigned char *) cache_info->metacontent+offset*
5762 (MagickOffsetType) cache_info->metacontent_extent;
5763 for (y=0; y < (ssize_t) rows; y++)
5765 (void) memcpy(q,p,(
size_t) length);
5766 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5767 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5776 LockSemaphoreInfo(cache_info->file_semaphore);
5777 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5779 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5780 cache_info->cache_filename);
5781 UnlockSemaphoreInfo(cache_info->file_semaphore);
5782 return(MagickFalse);
5784 if ((cache_info->columns == nexus_info->region.width) &&
5785 (extent <= MagickMaxBufferExtent))
5790 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5791 for (y=0; y < (ssize_t) rows; y++)
5793 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5794 (MagickOffsetType) extent*(MagickOffsetType)
5795 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5796 (MagickOffsetType) cache_info->metacontent_extent,length,
5797 (
const unsigned char *) p);
5798 if (count != (MagickOffsetType) length)
5800 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5801 offset+=(MagickOffsetType) cache_info->columns;
5803 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5804 (void) ClosePixelCacheOnDisk(cache_info);
5805 UnlockSemaphoreInfo(cache_info->file_semaphore);
5808 case DistributedCache:
5816 LockSemaphoreInfo(cache_info->file_semaphore);
5817 region=nexus_info->region;
5818 if ((cache_info->columns != nexus_info->region.width) ||
5819 (extent > MagickMaxBufferExtent))
5826 for (y=0; y < (ssize_t) rows; y++)
5829 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5830 if (count != (MagickOffsetType) length)
5832 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5835 UnlockSemaphoreInfo(cache_info->file_semaphore);
5841 if (y < (ssize_t) rows)
5843 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5844 cache_info->cache_filename);
5845 return(MagickFalse);
5847 if ((cache_info->debug != MagickFalse) &&
5848 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5849 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5850 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5851 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5852 nexus_info->region.x,(
double) nexus_info->region.y);
5884static MagickBooleanType WritePixelCachePixels(
5905 if (nexus_info->authentic_pixel_cache != MagickFalse)
5907 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5908 return(MagickFalse);
5909 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5910 nexus_info->region.x;
5911 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5913 extent=length*nexus_info->region.height;
5914 rows=nexus_info->region.height;
5916 p=nexus_info->pixels;
5917 switch (cache_info->type)
5928 if ((cache_info->columns == nexus_info->region.width) &&
5929 (extent == (MagickSizeType) ((
size_t) extent)))
5934 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5936 for (y=0; y < (ssize_t) rows; y++)
5938 (void) memcpy(q,p,(
size_t) length);
5939 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5940 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5949 LockSemaphoreInfo(cache_info->file_semaphore);
5950 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5952 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5953 cache_info->cache_filename);
5954 UnlockSemaphoreInfo(cache_info->file_semaphore);
5955 return(MagickFalse);
5957 if ((cache_info->columns == nexus_info->region.width) &&
5958 (extent <= MagickMaxBufferExtent))
5963 for (y=0; y < (ssize_t) rows; y++)
5965 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5966 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5967 sizeof(*p),length,(
const unsigned char *) p);
5968 if (count != (MagickOffsetType) length)
5970 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5971 offset+=(MagickOffsetType) cache_info->columns;
5973 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5974 (void) ClosePixelCacheOnDisk(cache_info);
5975 UnlockSemaphoreInfo(cache_info->file_semaphore);
5978 case DistributedCache:
5986 LockSemaphoreInfo(cache_info->file_semaphore);
5987 region=nexus_info->region;
5988 if ((cache_info->columns != nexus_info->region.width) ||
5989 (extent > MagickMaxBufferExtent))
5996 for (y=0; y < (ssize_t) rows; y++)
5999 cache_info->server_info,®ion,length,(
const unsigned char *) p);
6000 if (count != (MagickOffsetType) length)
6002 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
6005 UnlockSemaphoreInfo(cache_info->file_semaphore);
6011 if (y < (ssize_t) rows)
6013 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
6014 cache_info->cache_filename);
6015 return(MagickFalse);
6017 if ((cache_info->debug != MagickFalse) &&
6018 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6019 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6020 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6021 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6022 nexus_info->region.x,(
double) nexus_info->region.y);