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_ZLIB_DELEGATE)
85#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
86#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
87 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
102#if defined(__cplusplus) || defined(c_plusplus)
111 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
113 *GetVirtualPixelsCache(
const Image *);
116 *GetVirtualMetacontentFromCache(
const Image *);
118static MagickBooleanType
119 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,Quantum *,
121 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
124 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
127 ReadPixelCacheMetacontent(
CacheInfo *magick_restrict,
136 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
138 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
140 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
141 const ssize_t,
const ssize_t,
const size_t,
const size_t,
145#if defined(MAGICKCORE_OPENCL_SUPPORT)
147 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
150#if defined(__cplusplus) || defined(c_plusplus)
161 cache_anonymous_memory = (-1);
185MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
188 *magick_restrict cache_info;
193 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
195 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
196 (void) memset(cache_info,0,
sizeof(*cache_info));
197 cache_info->type=UndefinedCache;
198 cache_info->mode=IOMode;
199 cache_info->disk_mode=IOMode;
200 cache_info->colorspace=sRGBColorspace;
201 cache_info->file=(-1);
202 cache_info->id=GetMagickThreadId();
203 cache_info->number_threads=number_threads;
204 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
205 cache_info->number_threads=GetOpenMPMaximumThreads();
206 if (cache_info->number_threads == 0)
207 cache_info->number_threads=1;
208 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
209 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
210 if (value != (
const char *) NULL)
212 cache_info->synchronize=IsStringTrue(value);
213 value=DestroyString(value);
215 value=GetPolicyValue(
"cache:synchronize");
216 if (value != (
const char *) NULL)
218 cache_info->synchronize=IsStringTrue(value);
219 value=DestroyString(value);
221 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
222 (MagickSizeType) MAGICK_SSIZE_MAX);
223 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
224 (MagickSizeType) MAGICK_SSIZE_MAX);
225 cache_info->semaphore=AcquireSemaphoreInfo();
226 cache_info->reference_count=1;
227 cache_info->file_semaphore=AcquireSemaphoreInfo();
228 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
230 cache_info->signature=MagickCoreSignature;
231 return((Cache ) cache_info);
256MagickPrivate
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
259 **magick_restrict nexus_info;
264 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
265 number_threads,
sizeof(*nexus_info)));
267 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
268 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
269 2*
sizeof(**nexus_info));
271 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
272 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
273 for (i=0; i < (ssize_t) (2*number_threads); i++)
275 nexus_info[i]=(*nexus_info+i);
276 if (i < (ssize_t) number_threads)
277 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
278 nexus_info[i]->signature=MagickCoreSignature;
311MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
315 *magick_restrict cache_info;
317 assert(image != (
const Image *) NULL);
318 assert(image->signature == MagickCoreSignature);
320 assert(exception->signature == MagickCoreSignature);
321 assert(image->cache != (Cache) NULL);
324 assert(cache_info->signature == MagickCoreSignature);
326 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
327 return((
void *) NULL);
328 *length=(size_t) cache_info->length;
329 return(cache_info->pixels);
350MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
353 cache_semaphore=AcquireSemaphoreInfo();
375MagickPrivate
void CacheComponentTerminus(
void)
378 ActivateSemaphoreInfo(&cache_semaphore);
380 RelinquishSemaphoreInfo(&cache_semaphore);
412static MagickBooleanType ClipPixelCacheNexus(
Image *image,
416 *magick_restrict cache_info;
428 if (IsEventLogging() != MagickFalse)
429 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
430 if ((image->channels & WriteMaskChannel) == 0)
432 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
437 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
438 nexus_info->region.width,nexus_info->region.height,
439 nexus_info->virtual_nexus,exception);
440 q=nexus_info->pixels;
441 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
443 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
448 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
456 mask_alpha=QuantumScale*(double) GetPixelWriteMask(image,p);
457 if (fabs(mask_alpha) >= MagickEpsilon)
459 for (i=0; i < (ssize_t) image->number_channels; i++)
461 PixelChannel channel = GetPixelChannelChannel(image,i);
462 PixelTrait traits = GetPixelChannelTraits(image,channel);
463 if ((traits & UpdatePixelTrait) == 0)
465 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha*(
double)
466 GetPixelAlpha(image,p),(
double) q[i],(
double)
467 GetPixelAlpha(image,q)));
469 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
471 p+=(ptrdiff_t) GetPixelChannels(image);
472 q+=(ptrdiff_t) GetPixelChannels(image);
500MagickPrivate Cache ClonePixelCache(
const Cache cache)
503 *magick_restrict clone_info;
506 *magick_restrict cache_info;
508 assert(cache != NULL);
510 assert(cache_info->signature == MagickCoreSignature);
511 if (IsEventLogging() != MagickFalse)
512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
513 cache_info->filename);
514 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
515 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
516 return((Cache ) clone_info);
544MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
547 *magick_restrict cache_info,
548 *magick_restrict source_info;
550 assert(clone != (Cache) NULL);
552 assert(source_info->signature == MagickCoreSignature);
553 if (IsEventLogging() != MagickFalse)
554 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
555 source_info->filename);
556 assert(cache != (Cache) NULL);
558 assert(cache_info->signature == MagickCoreSignature);
559 source_info->methods=cache_info->methods;
591static MagickBooleanType ClonePixelCacheOnDisk(
612 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
613 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
615 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
616 (lseek(clone_info->file,0,SEEK_SET) < 0))
618 quantum=(size_t) MagickMaxBufferExtent;
619 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
621#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
622 if (cache_info->length < 0x7ffff000)
624 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
625 (
size_t) cache_info->length);
626 if (count == (ssize_t) cache_info->length)
628 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
629 (lseek(clone_info->file,0,SEEK_SET) < 0))
633 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
635 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
636 if (buffer == (
unsigned char *) NULL)
637 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
639 while ((count=read(cache_info->file,buffer,quantum)) > 0)
644 number_bytes=write(clone_info->file,buffer,(
size_t) count);
645 if (number_bytes != count)
647 extent+=(size_t) number_bytes;
649 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
650 if (extent != cache_info->length)
655#if defined(MAGICKCORE_OPENMP_SUPPORT)
656static inline int GetCacheNumberThreads(
const CacheInfo *source,
657 const CacheInfo *destination,
const size_t chunk,
const int factor)
660 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
661 number_threads = 1UL,
662 workload_factor = 64UL << factor;
667 number_threads=(chunk <= workload_factor) ? 1UL :
668 (chunk >= (workload_factor << 6)) ? max_threads :
669 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
673 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
674 ((destination->type != MemoryCache) && (destination->type != MapCache)))
675 number_threads=MagickMin(number_threads,4);
676 return((
int) number_threads);
680static MagickBooleanType ClonePixelCacheRepository(
684#define cache_number_threads(source,destination,chunk,factor) \
685 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
692 **magick_restrict cache_nexus,
693 **magick_restrict clone_nexus;
701 assert(cache_info != (
CacheInfo *) NULL);
702 assert(clone_info != (
CacheInfo *) NULL);
704 if (cache_info->type == PingCache)
706 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
707 if ((cache_info->storage_class == clone_info->storage_class) &&
708 (cache_info->colorspace == clone_info->colorspace) &&
709 (cache_info->alpha_trait == clone_info->alpha_trait) &&
710 (cache_info->channels == clone_info->channels) &&
711 (cache_info->columns == clone_info->columns) &&
712 (cache_info->rows == clone_info->rows) &&
713 (cache_info->number_channels == clone_info->number_channels) &&
714 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
715 (cache_info->metacontent_extent == clone_info->metacontent_extent))
720 if (((cache_info->type == MemoryCache) ||
721 (cache_info->type == MapCache)) &&
722 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
724 (void) memcpy(clone_info->pixels,cache_info->pixels,
725 cache_info->number_channels*cache_info->columns*cache_info->rows*
726 sizeof(*cache_info->pixels));
727 if ((cache_info->metacontent_extent != 0) &&
728 (clone_info->metacontent_extent != 0))
729 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
730 cache_info->columns*cache_info->rows*
731 clone_info->metacontent_extent*
sizeof(
unsigned char));
734 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
735 return(ClonePixelCacheOnDisk(cache_info,clone_info));
740 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
741 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
742 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
743 optimize=(cache_info->number_channels == clone_info->number_channels) &&
744 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
745 MagickTrue : MagickFalse;
746 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
747 clone_info->number_channels*clone_info->columns);
749#if defined(MAGICKCORE_OPENMP_SUPPORT)
750 #pragma omp parallel for schedule(static) shared(status) \
751 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
753 for (y=0; y < (ssize_t) cache_info->rows; y++)
756 id = GetOpenMPThreadId();
764 if (status == MagickFalse)
766 if (y >= (ssize_t) clone_info->rows)
768 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
769 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
770 if (pixels == (Quantum *) NULL)
772 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
773 if (status == MagickFalse)
775 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
776 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
777 if (pixels == (Quantum *) NULL)
779 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
780 if (optimize != MagickFalse)
781 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
794 p=cache_nexus[id]->pixels;
795 q=clone_nexus[id]->pixels;
796 for (x=0; x < (ssize_t) cache_info->columns; x++)
801 if (x == (ssize_t) clone_info->columns)
803 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
811 channel=clone_info->channel_map[i].channel;
812 traits=cache_info->channel_map[channel].traits;
813 if (traits != UndefinedPixelTrait)
814 *q=*(p+cache_info->channel_map[channel].offset);
817 p+=(ptrdiff_t) cache_info->number_channels;
820 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
822 if ((cache_info->metacontent_extent != 0) &&
823 (clone_info->metacontent_extent != 0))
828 length=(size_t) MagickMin(cache_info->metacontent_extent,
829 clone_info->metacontent_extent);
830#if defined(MAGICKCORE_OPENMP_SUPPORT)
831 #pragma omp parallel for schedule(static) shared(status) \
832 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
834 for (y=0; y < (ssize_t) cache_info->rows; y++)
837 id = GetOpenMPThreadId();
842 if (status == MagickFalse)
844 if (y >= (ssize_t) clone_info->rows)
846 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
847 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
848 if (pixels == (Quantum *) NULL)
850 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
851 if (status == MagickFalse)
853 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
854 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
855 if (pixels == (Quantum *) NULL)
857 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
858 (cache_nexus[
id]->metacontent != (
void *) NULL))
859 (void) memcpy(clone_nexus[
id]->metacontent,
860 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
861 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
864 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
865 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
866 if (cache_info->debug != MagickFalse)
869 message[MagickPathExtent];
871 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
872 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
873 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
874 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
901static void DestroyImagePixelCache(
Image *image)
903 assert(image != (
Image *) NULL);
904 assert(image->signature == MagickCoreSignature);
905 if (IsEventLogging() != MagickFalse)
906 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
907 if (image->cache != (
void *) NULL)
908 image->cache=DestroyPixelCache(image->cache);
933MagickExport
void DestroyImagePixels(
Image *image)
936 *magick_restrict cache_info;
938 assert(image != (
const Image *) NULL);
939 assert(image->signature == MagickCoreSignature);
940 if (IsEventLogging() != MagickFalse)
941 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
942 assert(image->cache != (Cache) NULL);
944 assert(cache_info->signature == MagickCoreSignature);
945 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
947 cache_info->methods.destroy_pixel_handler(image);
950 image->cache=DestroyPixelCache(image->cache);
976static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
982 if (cache_info->file != -1)
984 status=close_utf8(cache_info->file);
985 cache_info->file=(-1);
986 RelinquishMagickResource(FileResource,1);
988 return(status == -1 ? MagickFalse : MagickTrue);
991static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
993 switch (cache_info->type)
997 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
998#if defined(MAGICKCORE_OPENCL_SUPPORT)
999 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1001 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1003 cache_info->pixels=(Quantum *) NULL;
1007 if (cache_info->mapped == MagickFalse)
1008 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1009 cache_info->pixels);
1012 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1013 cache_info->pixels=(Quantum *) NULL;
1015 RelinquishMagickResource(MemoryResource,cache_info->length);
1020 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1021 cache_info->pixels=(Quantum *) NULL;
1022 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1023 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1024 *cache_info->cache_filename=
'\0';
1025 RelinquishMagickResource(MapResource,cache_info->length);
1030 if (cache_info->file != -1)
1031 (void) ClosePixelCacheOnDisk(cache_info);
1032 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1033 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1034 *cache_info->cache_filename=
'\0';
1035 RelinquishMagickResource(DiskResource,cache_info->length);
1038 case DistributedCache:
1040 *cache_info->cache_filename=
'\0';
1042 cache_info->server_info);
1048 cache_info->type=UndefinedCache;
1049 cache_info->mapped=MagickFalse;
1050 cache_info->metacontent=(
void *) NULL;
1053MagickPrivate Cache DestroyPixelCache(Cache cache)
1056 *magick_restrict cache_info;
1058 assert(cache != (Cache) NULL);
1060 assert(cache_info->signature == MagickCoreSignature);
1061 if (IsEventLogging() != MagickFalse)
1062 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1063 cache_info->filename);
1064 LockSemaphoreInfo(cache_info->semaphore);
1065 cache_info->reference_count--;
1066 if (cache_info->reference_count != 0)
1068 UnlockSemaphoreInfo(cache_info->semaphore);
1069 return((Cache) NULL);
1071 UnlockSemaphoreInfo(cache_info->semaphore);
1072 if (cache_info->debug != MagickFalse)
1075 message[MagickPathExtent];
1077 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1078 cache_info->filename);
1079 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1081 RelinquishPixelCachePixels(cache_info);
1084 cache_info->server_info);
1085 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1086 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1087 cache_info->number_threads);
1088 if (cache_info->random_info != (
RandomInfo *) NULL)
1089 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1091 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1093 RelinquishSemaphoreInfo(&cache_info->semaphore);
1094 cache_info->signature=(~MagickCoreSignature);
1095 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1126static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1128 if (nexus_info->mapped == MagickFalse)
1129 (void) RelinquishAlignedMemory(nexus_info->cache);
1131 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1132 nexus_info->cache=(Quantum *) NULL;
1133 nexus_info->pixels=(Quantum *) NULL;
1134 nexus_info->metacontent=(
void *) NULL;
1135 nexus_info->length=0;
1136 nexus_info->mapped=MagickFalse;
1140 const size_t number_threads)
1145 assert(nexus_info != (
NexusInfo **) NULL);
1146 for (i=0; i < (ssize_t) (2*number_threads); i++)
1148 if (nexus_info[i]->cache != (Quantum *) NULL)
1149 RelinquishCacheNexusPixels(nexus_info[i]);
1150 nexus_info[i]->signature=(~MagickCoreSignature);
1152 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1153 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1182MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1185 *magick_restrict cache_info;
1188 id = GetOpenMPThreadId();
1190 assert(image != (
const Image *) NULL);
1191 assert(image->signature == MagickCoreSignature);
1192 assert(image->cache != (Cache) NULL);
1194 assert(cache_info->signature == MagickCoreSignature);
1195 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1196 (GetAuthenticMetacontentFromHandler) NULL)
1201 metacontent=cache_info->methods.
1202 get_authentic_metacontent_from_handler(image);
1203 return(metacontent);
1205 assert(
id < (
int) cache_info->number_threads);
1206 return(cache_info->nexus_info[
id]->metacontent);
1233static void *GetAuthenticMetacontentFromCache(
const Image *image)
1236 *magick_restrict cache_info;
1239 id = GetOpenMPThreadId();
1241 assert(image != (
const Image *) NULL);
1242 assert(image->signature == MagickCoreSignature);
1243 assert(image->cache != (Cache) NULL);
1245 assert(cache_info->signature == MagickCoreSignature);
1246 assert(
id < (
int) cache_info->number_threads);
1247 return(cache_info->nexus_info[
id]->metacontent);
1250#if defined(MAGICKCORE_OPENCL_SUPPORT)
1279MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1283 *magick_restrict cache_info;
1285 assert(image != (
const Image *) NULL);
1286 assert(device != (
const MagickCLDevice) NULL);
1288 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1290 SyncImagePixelCache((
Image *) image,exception);
1293 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1294 return((cl_mem) NULL);
1295 LockSemaphoreInfo(cache_info->semaphore);
1296 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1297 (cache_info->opencl->device->context != device->context))
1298 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1299 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1301 assert(cache_info->pixels != (Quantum *) NULL);
1302 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1303 cache_info->length);
1305 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1306 RetainOpenCLMemObject(cache_info->opencl->buffer);
1307 UnlockSemaphoreInfo(cache_info->semaphore);
1308 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1309 return((cl_mem) NULL);
1310 assert(cache_info->opencl->pixels == cache_info->pixels);
1311 return(cache_info->opencl->buffer);
1350MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1351 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1355 *magick_restrict cache_info;
1358 *magick_restrict pixels;
1363 assert(image != (
Image *) NULL);
1364 assert(image->signature == MagickCoreSignature);
1365 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1366 nexus_info,exception);
1367 if (pixels == (Quantum *) NULL)
1368 return((Quantum *) NULL);
1370 assert(cache_info->signature == MagickCoreSignature);
1371 if (nexus_info->authentic_pixel_cache != MagickFalse)
1373 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1374 return((Quantum *) NULL);
1375 if (cache_info->metacontent_extent != 0)
1376 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1377 return((Quantum *) NULL);
1404static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1407 *magick_restrict cache_info;
1410 id = GetOpenMPThreadId();
1412 assert(image != (
const Image *) NULL);
1413 assert(image->signature == MagickCoreSignature);
1414 assert(image->cache != (Cache) NULL);
1416 assert(cache_info->signature == MagickCoreSignature);
1417 assert(
id < (
int) cache_info->number_threads);
1418 return(cache_info->nexus_info[
id]->pixels);
1445MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1448 *magick_restrict cache_info;
1451 id = GetOpenMPThreadId();
1453 assert(image != (
const Image *) NULL);
1454 assert(image->signature == MagickCoreSignature);
1455 assert(image->cache != (Cache) NULL);
1457 assert(cache_info->signature == MagickCoreSignature);
1458 if (cache_info->methods.get_authentic_pixels_from_handler !=
1459 (GetAuthenticPixelsFromHandler) NULL)
1460 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1461 assert(
id < (
int) cache_info->number_threads);
1462 return(cache_info->nexus_info[
id]->pixels);
1510MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1511 const ssize_t y,
const size_t columns,
const size_t rows,
1515 *magick_restrict cache_info;
1518 id = GetOpenMPThreadId();
1523 assert(image != (
Image *) NULL);
1524 assert(image->signature == MagickCoreSignature);
1525 assert(image->cache != (Cache) NULL);
1527 assert(cache_info->signature == MagickCoreSignature);
1528 if (cache_info->methods.get_authentic_pixels_handler !=
1529 (GetAuthenticPixelsHandler) NULL)
1531 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1535 assert(
id < (
int) cache_info->number_threads);
1536 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1537 cache_info->nexus_info[
id],exception);
1572static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1573 const ssize_t y,
const size_t columns,
const size_t rows,
1577 *magick_restrict cache_info;
1580 id = GetOpenMPThreadId();
1583 *magick_restrict pixels;
1585 assert(image != (
const Image *) NULL);
1586 assert(image->signature == MagickCoreSignature);
1587 assert(image->cache != (Cache) NULL);
1589 if (cache_info == (Cache) NULL)
1590 return((Quantum *) NULL);
1591 assert(cache_info->signature == MagickCoreSignature);
1592 assert(
id < (
int) cache_info->number_threads);
1593 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1594 cache_info->nexus_info[
id],exception);
1621MagickExport MagickSizeType GetImageExtent(
const Image *image)
1624 *magick_restrict cache_info;
1627 id = GetOpenMPThreadId();
1629 assert(image != (
Image *) NULL);
1630 assert(image->signature == MagickCoreSignature);
1631 if (IsEventLogging() != MagickFalse)
1632 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1633 assert(image->cache != (Cache) NULL);
1635 assert(cache_info->signature == MagickCoreSignature);
1636 assert(
id < (
int) cache_info->number_threads);
1637 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1670static MagickBooleanType GetDynamicThrottlePolicy(
void)
1672 static MagickBooleanType
1673 check_policy = MagickTrue;
1675 static MagickBooleanType
1676 dynamic_throttle = MagickFalse;
1678 if (check_policy != MagickFalse)
1680 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1681 if (value != (
char *) NULL)
1683 dynamic_throttle=IsStringTrue(value);
1684 value=DestroyString(value);
1686 check_policy=MagickFalse;
1688 return(dynamic_throttle);
1691static inline MagickBooleanType ValidatePixelCacheMorphology(
1692 const Image *magick_restrict image)
1695 *magick_restrict cache_info;
1705 p=image->channel_map;
1706 q=cache_info->channel_map;
1707 if ((image->storage_class != cache_info->storage_class) ||
1708 (image->colorspace != cache_info->colorspace) ||
1709 (image->alpha_trait != cache_info->alpha_trait) ||
1710 (image->channels != cache_info->channels) ||
1711 (image->columns != cache_info->columns) ||
1712 (image->rows != cache_info->rows) ||
1713 (image->number_channels != cache_info->number_channels) ||
1714 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1715 (image->metacontent_extent != cache_info->metacontent_extent) ||
1716 (cache_info->nexus_info == (
NexusInfo **) NULL))
1717 return(MagickFalse);
1721static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1725 *magick_restrict cache_info;
1729 status = MagickTrue;
1731 static MagickSizeType
1732 cpu_throttle = MagickResourceInfinity,
1735 if (IsImageTTLExpired(image) != MagickFalse)
1740 (void) ThrowMagickException(exception,GetMagickModule(),
1741 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1742 return((Cache) NULL);
1744 if (cpu_throttle == MagickResourceInfinity)
1745 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1746 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1759#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1760 if (getloadavg(&load_average,1) != 1)
1763 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1764 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1766 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1767 MagickDelay(cpu_throttle);
1769 LockSemaphoreInfo(image->semaphore);
1770 assert(image->cache != (Cache) NULL);
1772#if defined(MAGICKCORE_OPENCL_SUPPORT)
1773 CopyOpenCLBuffer(cache_info);
1775 destroy=MagickFalse;
1776 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1778 LockSemaphoreInfo(cache_info->semaphore);
1779 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1790 clone_image=(*image);
1791 clone_image.semaphore=AcquireSemaphoreInfo();
1792 clone_image.reference_count=1;
1793 clone_image.cache=ClonePixelCache(cache_info);
1794 clone_info=(
CacheInfo *) clone_image.cache;
1795 status=OpenPixelCache(&clone_image,IOMode,exception);
1796 if (status == MagickFalse)
1797 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1800 if (clone != MagickFalse)
1801 status=ClonePixelCacheRepository(clone_info,cache_info,
1803 if (status == MagickFalse)
1804 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1808 image->cache=clone_info;
1811 RelinquishSemaphoreInfo(&clone_image.semaphore);
1813 UnlockSemaphoreInfo(cache_info->semaphore);
1815 if (destroy != MagickFalse)
1816 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1817 if (status != MagickFalse)
1822 if (image->type != UndefinedType)
1823 image->type=UndefinedType;
1824 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1826 status=OpenPixelCache(image,IOMode,exception);
1828 if (cache_info->file != -1)
1829 (void) ClosePixelCacheOnDisk(cache_info);
1832 UnlockSemaphoreInfo(image->semaphore);
1833 if (status == MagickFalse)
1834 return((Cache) NULL);
1835 return(image->cache);
1861MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1864 *magick_restrict cache_info;
1866 assert(image != (
Image *) NULL);
1867 assert(image->signature == MagickCoreSignature);
1868 assert(image->cache != (Cache) NULL);
1870 assert(cache_info->signature == MagickCoreSignature);
1871 return(cache_info->type);
1905static inline MagickBooleanType CopyPixel(
const Image *image,
1906 const Quantum *source,Quantum *destination)
1911 if (source == (
const Quantum *) NULL)
1913 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1914 destination[GreenPixelChannel]=ClampToQuantum(
1915 image->background_color.green);
1916 destination[BluePixelChannel]=ClampToQuantum(
1917 image->background_color.blue);
1918 destination[BlackPixelChannel]=ClampToQuantum(
1919 image->background_color.black);
1920 destination[AlphaPixelChannel]=ClampToQuantum(
1921 image->background_color.alpha);
1922 return(MagickFalse);
1924 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1926 PixelChannel channel = GetPixelChannelChannel(image,i);
1927 destination[channel]=source[i];
1932MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1933 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1936 *magick_restrict cache_info;
1941 assert(image != (
Image *) NULL);
1942 assert(image->signature == MagickCoreSignature);
1943 assert(image->cache != (Cache) NULL);
1945 assert(cache_info->signature == MagickCoreSignature);
1946 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1947 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1948 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1949 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1950 return(CopyPixel(image,q,pixel));
1984static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
1985 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1988 *magick_restrict cache_info;
1991 id = GetOpenMPThreadId();
1996 assert(image != (
const Image *) NULL);
1997 assert(image->signature == MagickCoreSignature);
1998 assert(image->cache != (Cache) NULL);
2000 assert(cache_info->signature == MagickCoreSignature);
2001 assert(
id < (
int) cache_info->number_threads);
2002 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2003 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2005 return(CopyPixel(image,q,pixel));
2039MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2040 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2043 *magick_restrict cache_info;
2046 id = GetOpenMPThreadId();
2051 assert(image != (
const Image *) NULL);
2052 assert(image->signature == MagickCoreSignature);
2053 assert(image->cache != (Cache) NULL);
2055 assert(cache_info->signature == MagickCoreSignature);
2056 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2057 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2058 (GetOneVirtualPixelFromHandler) NULL)
2059 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2060 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2061 assert(
id < (
int) cache_info->number_threads);
2062 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2063 1UL,1UL,cache_info->nexus_info[
id],exception);
2064 return(CopyPixel(image,p,pixel));
2101static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2102 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2106 *magick_restrict cache_info;
2109 id = GetOpenMPThreadId();
2114 assert(image != (
const Image *) NULL);
2115 assert(image->signature == MagickCoreSignature);
2116 assert(image->cache != (Cache) NULL);
2118 assert(cache_info->signature == MagickCoreSignature);
2119 assert(
id < (
int) cache_info->number_threads);
2120 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2121 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2122 cache_info->nexus_info[
id],exception);
2123 return(CopyPixel(image,p,pixel));
2160MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2161 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2165 *magick_restrict cache_info;
2168 id = GetOpenMPThreadId();
2173 assert(image != (
const Image *) NULL);
2174 assert(image->signature == MagickCoreSignature);
2175 assert(image->cache != (Cache) NULL);
2177 assert(cache_info->signature == MagickCoreSignature);
2178 assert(
id < (
int) cache_info->number_threads);
2179 GetPixelInfo(image,pixel);
2180 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2181 cache_info->nexus_info[
id],exception);
2182 if (p == (
const Quantum *) NULL)
2183 return(MagickFalse);
2184 GetPixelInfoPixel(image,p,pixel);
2210MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2213 *magick_restrict cache_info;
2215 assert(cache != (Cache) NULL);
2217 assert(cache_info->signature == MagickCoreSignature);
2218 if (IsEventLogging() != MagickFalse)
2219 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2220 cache_info->filename);
2221 return(cache_info->colorspace);
2247MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2250 *magick_restrict cache_info;
2252 assert(image != (
const Image *) NULL);
2253 assert(image->signature == MagickCoreSignature);
2254 assert(image->cache != (Cache) NULL);
2256 assert(cache_info->signature == MagickCoreSignature);
2257 return(cache_info->cache_filename);
2282MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2285 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2286 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2287 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2288 cache_methods->get_virtual_metacontent_from_handler=
2289 GetVirtualMetacontentFromCache;
2290 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2291 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2292 cache_methods->get_authentic_metacontent_from_handler=
2293 GetAuthenticMetacontentFromCache;
2294 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2295 cache_methods->get_one_authentic_pixel_from_handler=
2296 GetOneAuthenticPixelFromCache;
2297 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2298 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2299 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2327MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2331 *magick_restrict cache_info;
2336 assert(cache != NULL);
2338 assert(cache_info->signature == MagickCoreSignature);
2339 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2341 return((MagickSizeType) cache_info->columns*cache_info->rows);
2372MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2376 *magick_restrict cache_info;
2378 assert(image != (
const Image *) NULL);
2379 assert(image->signature == MagickCoreSignature);
2380 assert(image->cache != (Cache) NULL);
2381 assert(length != (MagickSizeType *) NULL);
2382 magick_unreferenced(exception);
2384 assert(cache_info->signature == MagickCoreSignature);
2385 *length=cache_info->length;
2386 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2387 return((
void *) NULL);
2388 return((
void *) cache_info->pixels);
2415MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2418 *magick_restrict cache_info;
2420 assert(cache != (Cache) NULL);
2422 assert(cache_info->signature == MagickCoreSignature);
2423 if (IsEventLogging() != MagickFalse)
2424 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2425 cache_info->filename);
2426 return(cache_info->storage_class);
2456MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2460 *magick_restrict cache_info;
2462 assert(image != (
Image *) NULL);
2463 assert(image->signature == MagickCoreSignature);
2464 if (IsEventLogging() != MagickFalse)
2465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2467 assert(cache_info->signature == MagickCoreSignature);
2468 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2469 if (GetImagePixelCacheType(image) == DiskCache)
2470 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2498MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2501 *magick_restrict cache_info;
2503 assert(image != (
Image *) NULL);
2504 assert(image->signature == MagickCoreSignature);
2505 assert(image->cache != (Cache) NULL);
2507 assert(cache_info->signature == MagickCoreSignature);
2508 return(cache_info->virtual_pixel_method);
2534static const void *GetVirtualMetacontentFromCache(
const Image *image)
2537 *magick_restrict cache_info;
2540 id = GetOpenMPThreadId();
2543 *magick_restrict metacontent;
2545 assert(image != (
const Image *) NULL);
2546 assert(image->signature == MagickCoreSignature);
2547 assert(image->cache != (Cache) NULL);
2549 assert(cache_info->signature == MagickCoreSignature);
2550 assert(
id < (
int) cache_info->number_threads);
2551 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2552 cache_info->nexus_info[
id]);
2553 return(metacontent);
2582MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2586 *magick_restrict cache_info;
2588 assert(cache != (Cache) NULL);
2590 assert(cache_info->signature == MagickCoreSignature);
2591 if (cache_info->storage_class == UndefinedClass)
2592 return((
void *) NULL);
2593 return(nexus_info->metacontent);
2620MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2623 *magick_restrict cache_info;
2626 id = GetOpenMPThreadId();
2629 *magick_restrict metacontent;
2631 assert(image != (
const Image *) NULL);
2632 assert(image->signature == MagickCoreSignature);
2633 assert(image->cache != (Cache) NULL);
2635 assert(cache_info->signature == MagickCoreSignature);
2636 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2638 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2640 if (metacontent != (
const void *) NULL)
2641 return(metacontent);
2643 assert(
id < (
int) cache_info->number_threads);
2644 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2645 cache_info->nexus_info[
id]);
2646 return(metacontent);
2689 0, 48, 12, 60, 3, 51, 15, 63,
2690 32, 16, 44, 28, 35, 19, 47, 31,
2691 8, 56, 4, 52, 11, 59, 7, 55,
2692 40, 24, 36, 20, 43, 27, 39, 23,
2693 2, 50, 14, 62, 1, 49, 13, 61,
2694 34, 18, 46, 30, 33, 17, 45, 29,
2695 10, 58, 6, 54, 9, 57, 5, 53,
2696 42, 26, 38, 22, 41, 25, 37, 21
2699static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2704 index=x+DitherMatrix[x & 0x07]-32L;
2707 if (index >= (ssize_t) columns)
2708 return((ssize_t) columns-1L);
2712static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2717 index=y+DitherMatrix[y & 0x07]-32L;
2720 if (index >= (ssize_t) rows)
2721 return((ssize_t) rows-1L);
2725static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2729 if (x >= (ssize_t) columns)
2730 return((ssize_t) (columns-1));
2734static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2738 if (y >= (ssize_t) rows)
2739 return((ssize_t) (rows-1));
2743static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2744 const MagickOffsetType y)
2746 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2747 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2748 return(MagickFalse);
2752static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2754 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2757static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2759 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2762static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2763 const size_t extent)
2768 modulo.quotient=offset;
2772 modulo.quotient=offset/((ssize_t) extent);
2773 modulo.remainder=offset % ((ssize_t) extent);
2775 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2778 modulo.remainder+=((ssize_t) extent);
2783MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2784 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2785 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2789 *magick_restrict cache_info;
2805 *magick_restrict virtual_nexus;
2808 *magick_restrict pixels,
2810 virtual_pixel[MaxPixelChannels];
2821 *magick_restrict virtual_metacontent;
2826 assert(image != (
const Image *) NULL);
2827 assert(image->signature == MagickCoreSignature);
2828 assert(image->cache != (Cache) NULL);
2830 assert(cache_info->signature == MagickCoreSignature);
2831 if (cache_info->type == UndefinedCache)
2832 return((
const Quantum *) NULL);
2833#if defined(MAGICKCORE_OPENCL_SUPPORT)
2834 CopyOpenCLBuffer(cache_info);
2836 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2837 ((image->channels & WriteMaskChannel) != 0) ||
2838 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2839 nexus_info,exception);
2840 if (pixels == (Quantum *) NULL)
2841 return((
const Quantum *) NULL);
2842 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2843 return((
const Quantum *) NULL);
2844 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2845 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2846 return((
const Quantum *) NULL);
2847 offset+=nexus_info->region.x;
2848 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2849 nexus_info->region.width-1L;
2850 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2851 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2852 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2853 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2861 if (nexus_info->authentic_pixel_cache != MagickFalse)
2863 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2864 if (status == MagickFalse)
2865 return((
const Quantum *) NULL);
2866 if (cache_info->metacontent_extent != 0)
2868 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2869 if (status == MagickFalse)
2870 return((
const Quantum *) NULL);
2877 virtual_nexus=nexus_info->virtual_nexus;
2879 s=(
unsigned char *) nexus_info->metacontent;
2880 (void) memset(virtual_pixel,0,cache_info->number_channels*
2881 sizeof(*virtual_pixel));
2882 virtual_metacontent=(
void *) NULL;
2883 switch (virtual_pixel_method)
2885 case BackgroundVirtualPixelMethod:
2886 case BlackVirtualPixelMethod:
2887 case GrayVirtualPixelMethod:
2888 case TransparentVirtualPixelMethod:
2889 case MaskVirtualPixelMethod:
2890 case WhiteVirtualPixelMethod:
2891 case EdgeVirtualPixelMethod:
2892 case CheckerTileVirtualPixelMethod:
2893 case HorizontalTileVirtualPixelMethod:
2894 case VerticalTileVirtualPixelMethod:
2896 if (cache_info->metacontent_extent != 0)
2901 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2902 cache_info->metacontent_extent);
2903 if (virtual_metacontent == (
void *) NULL)
2905 (void) ThrowMagickException(exception,GetMagickModule(),
2906 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2907 return((
const Quantum *) NULL);
2909 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2911 switch (virtual_pixel_method)
2913 case BlackVirtualPixelMethod:
2915 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2916 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2917 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2920 case GrayVirtualPixelMethod:
2922 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2923 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2925 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2928 case TransparentVirtualPixelMethod:
2930 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2931 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2932 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2935 case MaskVirtualPixelMethod:
2936 case WhiteVirtualPixelMethod:
2938 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2939 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2940 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2945 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2947 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2949 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2951 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2953 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2963 for (v=0; v < (ssize_t) rows; v++)
2969 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2970 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2971 y_offset=EdgeY(y_offset,cache_info->rows);
2972 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2978 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2979 x_offset,(ssize_t) columns-u);
2980 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2981 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2991 length=(MagickSizeType) 1;
2992 switch (virtual_pixel_method)
2994 case EdgeVirtualPixelMethod:
2997 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2998 EdgeX(x_offset,cache_info->columns),
2999 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3001 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3004 case RandomVirtualPixelMethod:
3006 if (cache_info->random_info == (
RandomInfo *) NULL)
3007 cache_info->random_info=AcquireRandomInfo();
3008 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3009 RandomX(cache_info->random_info,cache_info->columns),
3010 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3011 virtual_nexus,exception);
3012 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3015 case DitherVirtualPixelMethod:
3017 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3018 DitherX(x_offset,cache_info->columns),
3019 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3021 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3024 case TileVirtualPixelMethod:
3026 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3027 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3028 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3029 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3031 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3034 case MirrorVirtualPixelMethod:
3036 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3037 if ((x_modulo.quotient & 0x01) == 1L)
3038 x_modulo.remainder=(ssize_t) cache_info->columns-
3039 x_modulo.remainder-1L;
3040 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3041 if ((y_modulo.quotient & 0x01) == 1L)
3042 y_modulo.remainder=(ssize_t) cache_info->rows-
3043 y_modulo.remainder-1L;
3044 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3045 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3047 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3050 case HorizontalTileEdgeVirtualPixelMethod:
3052 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3053 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3054 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3055 virtual_nexus,exception);
3056 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3059 case VerticalTileEdgeVirtualPixelMethod:
3061 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3062 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3063 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3064 virtual_nexus,exception);
3065 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3068 case BackgroundVirtualPixelMethod:
3069 case BlackVirtualPixelMethod:
3070 case GrayVirtualPixelMethod:
3071 case TransparentVirtualPixelMethod:
3072 case MaskVirtualPixelMethod:
3073 case WhiteVirtualPixelMethod:
3076 r=virtual_metacontent;
3079 case CheckerTileVirtualPixelMethod:
3081 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3082 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3083 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3086 r=virtual_metacontent;
3089 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3090 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3092 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3095 case HorizontalTileVirtualPixelMethod:
3097 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3100 r=virtual_metacontent;
3103 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3104 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3105 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3106 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3108 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3111 case VerticalTileVirtualPixelMethod:
3113 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3116 r=virtual_metacontent;
3119 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3120 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3121 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3122 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3124 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3128 if (p == (
const Quantum *) NULL)
3130 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3132 q+=(ptrdiff_t) cache_info->number_channels;
3133 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3135 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3136 s+=(ptrdiff_t) cache_info->metacontent_extent;
3143 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3144 (
size_t) length,1UL,virtual_nexus,exception);
3145 if (p == (
const Quantum *) NULL)
3147 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3148 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3150 q+=(ptrdiff_t) cache_info->number_channels*length;
3151 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3153 (void) memcpy(s,r,(
size_t) length);
3154 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3157 if (u < (ssize_t) columns)
3163 if (virtual_metacontent != (
void *) NULL)
3164 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3165 if (v < (ssize_t) rows)
3166 return((
const Quantum *) NULL);
3204static const Quantum *GetVirtualPixelCache(
const Image *image,
3205 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3206 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3209 *magick_restrict cache_info;
3212 id = GetOpenMPThreadId();
3217 assert(image != (
const Image *) NULL);
3218 assert(image->signature == MagickCoreSignature);
3219 assert(image->cache != (Cache) NULL);
3221 assert(cache_info->signature == MagickCoreSignature);
3222 assert(
id < (
int) cache_info->number_threads);
3223 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3224 cache_info->nexus_info[
id],exception);
3251MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3254 *magick_restrict cache_info;
3257 id = GetOpenMPThreadId();
3259 assert(image != (
const Image *) NULL);
3260 assert(image->signature == MagickCoreSignature);
3261 assert(image->cache != (Cache) NULL);
3263 assert(cache_info->signature == MagickCoreSignature);
3264 if (cache_info->methods.get_virtual_pixels_handler !=
3265 (GetVirtualPixelsHandler) NULL)
3266 return(cache_info->methods.get_virtual_pixels_handler(image));
3267 assert(
id < (
int) cache_info->number_threads);
3268 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3319MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3320 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3324 *magick_restrict cache_info;
3327 id = GetOpenMPThreadId();
3332 assert(image != (
const Image *) NULL);
3333 assert(image->signature == MagickCoreSignature);
3334 assert(image->cache != (Cache) NULL);
3336 assert(cache_info->signature == MagickCoreSignature);
3337 if (cache_info->methods.get_virtual_pixel_handler !=
3338 (GetVirtualPixelHandler) NULL)
3339 return(cache_info->methods.get_virtual_pixel_handler(image,
3340 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3341 assert(
id < (
int) cache_info->number_threads);
3342 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3343 columns,rows,cache_info->nexus_info[
id],exception);
3370static const Quantum *GetVirtualPixelsCache(
const Image *image)
3373 *magick_restrict cache_info;
3376 id = GetOpenMPThreadId();
3378 assert(image != (
const Image *) NULL);
3379 assert(image->signature == MagickCoreSignature);
3380 assert(image->cache != (Cache) NULL);
3382 assert(cache_info->signature == MagickCoreSignature);
3383 assert(
id < (
int) cache_info->number_threads);
3384 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3413MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3417 *magick_restrict cache_info;
3419 assert(cache != (Cache) NULL);
3421 assert(cache_info->signature == MagickCoreSignature);
3422 if (cache_info->storage_class == UndefinedClass)
3423 return((Quantum *) NULL);
3424 return((
const Quantum *) nexus_info->pixels);
3457static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3458 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3463 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3465 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3466 gamma=MagickSafeReciprocal(gamma);
3467 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3470static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3474 *magick_restrict cache_info;
3486 if (IsEventLogging() != MagickFalse)
3487 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3488 if ((image->channels & CompositeMaskChannel) == 0)
3490 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3493 if (cache_info == (Cache) NULL)
3494 return(MagickFalse);
3495 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3496 nexus_info->region.width,nexus_info->region.height,
3497 nexus_info->virtual_nexus,exception);
3498 q=nexus_info->pixels;
3499 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3500 return(MagickFalse);
3501 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3506 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3514 alpha=(double) GetPixelCompositeMask(image,p);
3515 for (i=0; i < (ssize_t) image->number_channels; i++)
3517 PixelChannel channel = GetPixelChannelChannel(image,i);
3518 PixelTrait traits = GetPixelChannelTraits(image,channel);
3519 if ((traits & UpdatePixelTrait) == 0)
3521 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3523 p+=(ptrdiff_t) GetPixelChannels(image);
3524 q+=(ptrdiff_t) GetPixelChannels(image);
3561static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3570 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3572 if (*cache_info->cache_filename ==
'\0')
3573 file=AcquireUniqueFileResource(cache_info->cache_filename);
3579 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3584 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3585 O_BINARY | O_EXCL,S_MODE);
3587 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3593 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3596 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3601 return(MagickFalse);
3602 (void) AcquireMagickResource(FileResource,1);
3603 if (cache_info->file != -1)
3604 (void) ClosePixelCacheOnDisk(cache_info);
3605 cache_info->file=file;
3606 cache_info->disk_mode=mode;
3610static inline MagickOffsetType WritePixelCacheRegion(
3611 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3612 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3620#if !defined(MAGICKCORE_HAVE_PWRITE)
3621 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3622 return((MagickOffsetType) -1);
3624 for (i=0; i < (MagickOffsetType) length; i+=count)
3626#if !defined(MAGICKCORE_HAVE_PWRITE)
3627 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3628 (MagickSizeType) i,MagickMaxBufferExtent));
3630 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3631 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3643static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3646 *magick_restrict cache_info;
3652 if (cache_info->debug != MagickFalse)
3655 format[MagickPathExtent],
3656 message[MagickPathExtent];
3658 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3659 (void) FormatLocaleString(message,MagickPathExtent,
3660 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3661 cache_info->cache_filename,cache_info->file,format);
3662 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3664 if (length != (MagickSizeType) ((MagickOffsetType) length))
3665 return(MagickFalse);
3666 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3668 return(MagickFalse);
3669 if ((MagickSizeType) offset < length)
3675 extent=(MagickOffsetType) length-1;
3676 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3679 return(MagickFalse);
3680#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3681 if (cache_info->synchronize != MagickFalse)
3682 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3683 return(MagickFalse);
3686 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3688 return(MagickFalse);
3692static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3696 *magick_restrict cache_info,
3700 format[MagickPathExtent],
3701 message[MagickPathExtent];
3718 assert(image != (
const Image *) NULL);
3719 assert(image->signature == MagickCoreSignature);
3720 assert(image->cache != (Cache) NULL);
3721 if (IsEventLogging() != MagickFalse)
3722 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3723 if (cache_anonymous_memory < 0)
3731 cache_anonymous_memory=0;
3732 value=GetPolicyValue(
"pixel-cache-memory");
3733 if (value == (
char *) NULL)
3734 value=GetPolicyValue(
"cache:memory-map");
3735 if (LocaleCompare(value,
"anonymous") == 0)
3737#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3738 cache_anonymous_memory=1;
3740 (void) ThrowMagickException(exception,GetMagickModule(),
3741 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3742 "`%s' (policy requires anonymous memory mapping)",image->filename);
3745 value=DestroyString(value);
3747 if ((image->columns == 0) || (image->rows == 0))
3748 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3750 assert(cache_info->signature == MagickCoreSignature);
3751 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3752 ((MagickSizeType) image->rows > cache_info->height_limit))
3754 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3755 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3756 image->filename, (double) image->columns, (
double) image->rows,
3757 (double) cache_info->width_limit,(
double) cache_info->height_limit);
3758 return(MagickFalse);
3760 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3762 length=GetImageListLength(image);
3763 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3764 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3767 source_info=(*cache_info);
3768 source_info.file=(-1);
3769 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3770 image->filename,(
double) image->scene);
3771 cache_info->storage_class=image->storage_class;
3772 cache_info->colorspace=image->colorspace;
3773 cache_info->alpha_trait=image->alpha_trait;
3774 cache_info->channels=image->channels;
3775 cache_info->rows=image->rows;
3776 cache_info->columns=image->columns;
3777 status=ResetPixelChannelMap(image,exception);
3778 if (status == MagickFalse)
3779 return(MagickFalse);
3780 cache_info->number_channels=GetPixelChannels(image);
3781 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3782 sizeof(*image->channel_map));
3783 cache_info->metacontent_extent=image->metacontent_extent;
3784 cache_info->mode=mode;
3785 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3786 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3787 if (image->metacontent_extent != 0)
3788 packet_size+=cache_info->metacontent_extent;
3789 length=number_pixels*packet_size;
3790 columns=(size_t) (length/cache_info->rows/packet_size);
3791 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3792 ((ssize_t) cache_info->rows < 0))
3793 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3795 cache_info->length=length;
3796 if (image->ping != MagickFalse)
3798 cache_info->type=PingCache;
3801 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3802 cache_info->columns*cache_info->rows);
3803 if (cache_info->mode == PersistMode)
3805 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3806 cache_info->metacontent_extent);
3807 if ((status != MagickFalse) &&
3808 (length == (MagickSizeType) ((
size_t) length)) &&
3809 ((cache_info->type == UndefinedCache) ||
3810 (cache_info->type == MemoryCache)))
3812 status=AcquireMagickResource(MemoryResource,cache_info->length);
3813 if (status != MagickFalse)
3816 if (cache_anonymous_memory <= 0)
3818 cache_info->mapped=MagickFalse;
3819 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3820 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3824 cache_info->mapped=MagickTrue;
3825 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3826 cache_info->length);
3828 if (cache_info->pixels == (Quantum *) NULL)
3830 cache_info->mapped=source_info.mapped;
3831 cache_info->pixels=source_info.pixels;
3838 cache_info->type=MemoryCache;
3839 cache_info->metacontent=(
void *) NULL;
3840 if (cache_info->metacontent_extent != 0)
3841 cache_info->metacontent=(
void *) (cache_info->pixels+
3842 cache_info->number_channels*number_pixels);
3843 if ((source_info.storage_class != UndefinedClass) &&
3846 status=ClonePixelCacheRepository(cache_info,&source_info,
3848 RelinquishPixelCachePixels(&source_info);
3850 if (cache_info->debug != MagickFalse)
3852 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3853 MagickPathExtent,format);
3854 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3856 (void) FormatLocaleString(message,MagickPathExtent,
3857 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3858 cache_info->filename,cache_info->mapped != MagickFalse ?
3859 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3860 (double) cache_info->rows,(double)
3861 cache_info->number_channels,format);
3862 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3865 cache_info->storage_class=image->storage_class;
3868 if ((source_info.storage_class != UndefinedClass) &&
3870 RelinquishPixelCachePixels(&source_info);
3871 cache_info->type=UndefinedCache;
3872 return(MagickFalse);
3878 status=AcquireMagickResource(DiskResource,cache_info->length);
3879 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3881 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3889 server_info=AcquireDistributeCacheInfo(exception);
3892 status=OpenDistributePixelCache(server_info,image);
3893 if (status == MagickFalse)
3895 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3896 GetDistributeCacheHostname(server_info));
3897 server_info=DestroyDistributeCacheInfo(server_info);
3905 cache_info->type=DistributedCache;
3906 cache_info->server_info=server_info;
3907 (void) FormatLocaleString(cache_info->cache_filename,
3908 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3911 cache_info->server_info));
3912 if ((source_info.storage_class != UndefinedClass) &&
3915 status=ClonePixelCacheRepository(cache_info,&source_info,
3917 RelinquishPixelCachePixels(&source_info);
3919 if (cache_info->debug != MagickFalse)
3921 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3922 MagickPathExtent,format);
3923 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3925 (void) FormatLocaleString(message,MagickPathExtent,
3926 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3927 cache_info->filename,cache_info->cache_filename,
3929 cache_info->server_info),type,(double) cache_info->columns,
3930 (
double) cache_info->rows,(double)
3931 cache_info->number_channels,format);
3932 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3937 if ((source_info.storage_class != UndefinedClass) &&
3939 RelinquishPixelCachePixels(&source_info);
3940 cache_info->type=UndefinedCache;
3941 return(MagickFalse);
3946 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3947 RelinquishPixelCachePixels(&source_info);
3948 cache_info->type=UndefinedCache;
3949 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3950 "CacheResourcesExhausted",
"`%s'",image->filename);
3951 return(MagickFalse);
3956 if (status == MagickFalse)
3958 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3959 RelinquishPixelCachePixels(&source_info);
3960 cache_info->type=UndefinedCache;
3961 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3962 "CacheResourcesExhausted",
"`%s'",image->filename);
3963 return(MagickFalse);
3965 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3966 (cache_info->mode != PersistMode))
3968 (void) ClosePixelCacheOnDisk(cache_info);
3969 *cache_info->cache_filename=
'\0';
3971 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3973 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3974 RelinquishPixelCachePixels(&source_info);
3975 cache_info->type=UndefinedCache;
3976 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3978 return(MagickFalse);
3980 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3981 cache_info->length);
3982 if (status == MagickFalse)
3984 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3985 RelinquishPixelCachePixels(&source_info);
3986 cache_info->type=UndefinedCache;
3987 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3989 return(MagickFalse);
3991 cache_info->type=DiskCache;
3992 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3993 cache_info->metacontent_extent);
3994 if (length == (MagickSizeType) ((
size_t) length))
3996 status=AcquireMagickResource(MapResource,cache_info->length);
3997 if (status != MagickFalse)
3999 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
4000 cache_info->offset,(
size_t) cache_info->length);
4001 if (cache_info->pixels == (Quantum *) NULL)
4003 cache_info->mapped=source_info.mapped;
4004 cache_info->pixels=source_info.pixels;
4005 RelinquishMagickResource(MapResource,cache_info->length);
4012 (void) ClosePixelCacheOnDisk(cache_info);
4013 cache_info->type=MapCache;
4014 cache_info->mapped=MagickTrue;
4015 cache_info->metacontent=(
void *) NULL;
4016 if (cache_info->metacontent_extent != 0)
4017 cache_info->metacontent=(
void *) (cache_info->pixels+
4018 cache_info->number_channels*number_pixels);
4019 if ((source_info.storage_class != UndefinedClass) &&
4022 status=ClonePixelCacheRepository(cache_info,&source_info,
4024 RelinquishPixelCachePixels(&source_info);
4026 if (cache_info->debug != MagickFalse)
4028 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4029 MagickPathExtent,format);
4030 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4032 (void) FormatLocaleString(message,MagickPathExtent,
4033 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4034 cache_info->filename,cache_info->cache_filename,
4035 cache_info->file,type,(
double) cache_info->columns,
4036 (double) cache_info->rows,(
double)
4037 cache_info->number_channels,format);
4038 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4043 if ((source_info.storage_class != UndefinedClass) &&
4045 RelinquishPixelCachePixels(&source_info);
4046 cache_info->type=UndefinedCache;
4047 return(MagickFalse);
4054 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4056 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4057 RelinquishPixelCachePixels(&source_info);
4059 if (cache_info->debug != MagickFalse)
4061 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4062 MagickPathExtent,format);
4063 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4065 (void) FormatLocaleString(message,MagickPathExtent,
4066 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4067 cache_info->cache_filename,cache_info->file,type,(
double)
4068 cache_info->columns,(double) cache_info->rows,(
double)
4069 cache_info->number_channels,format);
4070 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4074 cache_info->type=UndefinedCache;
4075 return(MagickFalse);
4117MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4118 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4122 *magick_restrict cache_info,
4123 *magick_restrict clone_info;
4131 assert(image != (
Image *) NULL);
4132 assert(image->signature == MagickCoreSignature);
4133 if (IsEventLogging() != MagickFalse)
4134 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4135 assert(image->cache != (
void *) NULL);
4136 assert(filename != (
const char *) NULL);
4137 assert(offset != (MagickOffsetType *) NULL);
4138 page_size=GetMagickPageSize();
4140 assert(cache_info->signature == MagickCoreSignature);
4141#if defined(MAGICKCORE_OPENCL_SUPPORT)
4142 CopyOpenCLBuffer(cache_info);
4144 if (attach != MagickFalse)
4149 if (cache_info->debug != MagickFalse)
4150 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4151 "attach persistent cache");
4152 (void) CopyMagickString(cache_info->cache_filename,filename,
4154 cache_info->type=MapCache;
4155 cache_info->offset=(*offset);
4156 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4157 return(MagickFalse);
4158 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4159 ((MagickOffsetType) cache_info->length % page_size));
4165 status=AcquireMagickResource(DiskResource,cache_info->length);
4166 if (status == MagickFalse)
4168 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4169 "CacheResourcesExhausted",
"`%s'",image->filename);
4170 return(MagickFalse);
4172 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4173 clone_info->type=DiskCache;
4174 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4175 clone_info->file=(-1);
4176 clone_info->storage_class=cache_info->storage_class;
4177 clone_info->colorspace=cache_info->colorspace;
4178 clone_info->alpha_trait=cache_info->alpha_trait;
4179 clone_info->channels=cache_info->channels;
4180 clone_info->columns=cache_info->columns;
4181 clone_info->rows=cache_info->rows;
4182 clone_info->number_channels=cache_info->number_channels;
4183 clone_info->metacontent_extent=cache_info->metacontent_extent;
4184 clone_info->mode=PersistMode;
4185 clone_info->length=cache_info->length;
4186 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4187 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4188 clone_info->offset=(*offset);
4189 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4190 if (status != MagickFalse)
4191 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4192 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4193 ((MagickOffsetType) cache_info->length % page_size));
4194 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4236MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4237 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4241 *magick_restrict cache_info;
4250 *magick_restrict pixels;
4255 assert(image != (
const Image *) NULL);
4256 assert(image->signature == MagickCoreSignature);
4257 assert(image->cache != (Cache) NULL);
4258 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4259 if (cache_info == (Cache) NULL)
4260 return((Quantum *) NULL);
4261 assert(cache_info->signature == MagickCoreSignature);
4262 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4263 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4264 (y >= (ssize_t) cache_info->rows))
4266 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4267 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4268 return((Quantum *) NULL);
4270 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4271 return((Quantum *) NULL);
4272 offset=y*(MagickOffsetType) cache_info->columns+x;
4274 return((Quantum *) NULL);
4275 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4276 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4277 (MagickOffsetType) columns-1;
4278 if ((MagickSizeType) offset >= number_pixels)
4279 return((Quantum *) NULL);
4283 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4284 ((image->channels & WriteMaskChannel) != 0) ||
4285 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4286 nexus_info,exception);
4323static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4324 const ssize_t y,
const size_t columns,
const size_t rows,
4328 *magick_restrict cache_info;
4331 id = GetOpenMPThreadId();
4334 *magick_restrict pixels;
4336 assert(image != (
const Image *) NULL);
4337 assert(image->signature == MagickCoreSignature);
4338 assert(image->cache != (Cache) NULL);
4340 assert(cache_info->signature == MagickCoreSignature);
4341 assert(
id < (
int) cache_info->number_threads);
4342 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4343 cache_info->nexus_info[
id],exception);
4403MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4404 const ssize_t y,
const size_t columns,
const size_t rows,
4408 *magick_restrict cache_info;
4411 id = GetOpenMPThreadId();
4414 *magick_restrict pixels;
4416 assert(image != (
Image *) NULL);
4417 assert(image->signature == MagickCoreSignature);
4418 assert(image->cache != (Cache) NULL);
4420 assert(cache_info->signature == MagickCoreSignature);
4421 if (cache_info->methods.queue_authentic_pixels_handler !=
4422 (QueueAuthenticPixelsHandler) NULL)
4424 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4425 columns,rows,exception);
4428 assert(
id < (
int) cache_info->number_threads);
4429 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4430 cache_info->nexus_info[
id],exception);
4463static inline MagickOffsetType ReadPixelCacheRegion(
4464 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4465 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4473#if !defined(MAGICKCORE_HAVE_PREAD)
4474 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4475 return((MagickOffsetType) -1);
4477 for (i=0; i < (MagickOffsetType) length; i+=count)
4479#if !defined(MAGICKCORE_HAVE_PREAD)
4480 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4481 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4483 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4484 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4496static MagickBooleanType ReadPixelCacheMetacontent(
4517 if (cache_info->metacontent_extent == 0)
4518 return(MagickFalse);
4519 if (nexus_info->authentic_pixel_cache != MagickFalse)
4521 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4522 return(MagickFalse);
4523 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4524 nexus_info->region.x;
4525 length=(MagickSizeType) nexus_info->region.width*
4526 cache_info->metacontent_extent;
4527 extent=length*nexus_info->region.height;
4528 rows=nexus_info->region.height;
4530 q=(
unsigned char *) nexus_info->metacontent;
4531 switch (cache_info->type)
4542 if ((cache_info->columns == nexus_info->region.width) &&
4543 (extent == (MagickSizeType) ((
size_t) extent)))
4548 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4549 cache_info->metacontent_extent;
4550 for (y=0; y < (ssize_t) rows; y++)
4552 (void) memcpy(q,p,(
size_t) length);
4553 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4554 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4563 LockSemaphoreInfo(cache_info->file_semaphore);
4564 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4566 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4567 cache_info->cache_filename);
4568 UnlockSemaphoreInfo(cache_info->file_semaphore);
4569 return(MagickFalse);
4571 if ((cache_info->columns == nexus_info->region.width) &&
4572 (extent <= MagickMaxBufferExtent))
4577 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4578 for (y=0; y < (ssize_t) rows; y++)
4580 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4581 (MagickOffsetType) extent*(MagickOffsetType)
4582 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4583 (MagickOffsetType) cache_info->metacontent_extent,length,
4584 (
unsigned char *) q);
4585 if (count != (MagickOffsetType) length)
4587 offset+=(MagickOffsetType) cache_info->columns;
4588 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4590 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4591 (void) ClosePixelCacheOnDisk(cache_info);
4592 UnlockSemaphoreInfo(cache_info->file_semaphore);
4595 case DistributedCache:
4603 LockSemaphoreInfo(cache_info->file_semaphore);
4604 region=nexus_info->region;
4605 if ((cache_info->columns != nexus_info->region.width) ||
4606 (extent > MagickMaxBufferExtent))
4613 for (y=0; y < (ssize_t) rows; y++)
4616 cache_info->server_info,®ion,length,(
unsigned char *) q);
4617 if (count != (MagickOffsetType) length)
4619 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4622 UnlockSemaphoreInfo(cache_info->file_semaphore);
4628 if (y < (ssize_t) rows)
4630 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4631 cache_info->cache_filename);
4632 return(MagickFalse);
4634 if ((cache_info->debug != MagickFalse) &&
4635 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4636 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4637 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4638 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4639 nexus_info->region.x,(
double) nexus_info->region.y);
4671static MagickBooleanType ReadPixelCachePixels(
4693 if (nexus_info->authentic_pixel_cache != MagickFalse)
4695 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4696 return(MagickFalse);
4697 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4698 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4699 return(MagickFalse);
4700 offset+=nexus_info->region.x;
4701 number_channels=cache_info->number_channels;
4702 length=(MagickSizeType) number_channels*nexus_info->region.width*
4704 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4705 return(MagickFalse);
4706 rows=nexus_info->region.height;
4708 if ((extent == 0) || ((extent/length) != rows))
4709 return(MagickFalse);
4711 q=nexus_info->pixels;
4712 switch (cache_info->type)
4723 if ((cache_info->columns == nexus_info->region.width) &&
4724 (extent == (MagickSizeType) ((
size_t) extent)))
4729 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4731 for (y=0; y < (ssize_t) rows; y++)
4733 (void) memcpy(q,p,(
size_t) length);
4734 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4735 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4744 LockSemaphoreInfo(cache_info->file_semaphore);
4745 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4747 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4748 cache_info->cache_filename);
4749 UnlockSemaphoreInfo(cache_info->file_semaphore);
4750 return(MagickFalse);
4752 if ((cache_info->columns == nexus_info->region.width) &&
4753 (extent <= MagickMaxBufferExtent))
4758 for (y=0; y < (ssize_t) rows; y++)
4760 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4761 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4762 sizeof(*q),length,(
unsigned char *) q);
4763 if (count != (MagickOffsetType) length)
4765 offset+=(MagickOffsetType) cache_info->columns;
4766 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4768 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4769 (void) ClosePixelCacheOnDisk(cache_info);
4770 UnlockSemaphoreInfo(cache_info->file_semaphore);
4773 case DistributedCache:
4781 LockSemaphoreInfo(cache_info->file_semaphore);
4782 region=nexus_info->region;
4783 if ((cache_info->columns != nexus_info->region.width) ||
4784 (extent > MagickMaxBufferExtent))
4791 for (y=0; y < (ssize_t) rows; y++)
4794 cache_info->server_info,®ion,length,(
unsigned char *) q);
4795 if (count != (MagickOffsetType) length)
4797 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4800 UnlockSemaphoreInfo(cache_info->file_semaphore);
4806 if (y < (ssize_t) rows)
4808 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4809 cache_info->cache_filename);
4810 return(MagickFalse);
4812 if ((cache_info->debug != MagickFalse) &&
4813 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4814 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4815 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4816 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4817 nexus_info->region.x,(
double) nexus_info->region.y);
4844MagickPrivate Cache ReferencePixelCache(Cache cache)
4847 *magick_restrict cache_info;
4849 assert(cache != (Cache *) NULL);
4851 assert(cache_info->signature == MagickCoreSignature);
4852 LockSemaphoreInfo(cache_info->semaphore);
4853 cache_info->reference_count++;
4854 UnlockSemaphoreInfo(cache_info->semaphore);
4880MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4883 *magick_restrict cache_info;
4885 assert(image != (
const Image *) NULL);
4886 assert(image->signature == MagickCoreSignature);
4887 assert(image->cache != (Cache) NULL);
4889 assert(cache_info->signature == MagickCoreSignature);
4890 cache_info->number_channels=GetPixelChannels(image);
4911MagickPrivate
void ResetCacheAnonymousMemory(
void)
4913 cache_anonymous_memory=0;
4945MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4946 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4954 assert(image != (
Image *) NULL);
4955 assert(image->signature == MagickCoreSignature);
4956 if (IsEventLogging() != MagickFalse)
4957 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4958 assert(image->cache != (
void *) NULL);
4959 extent=(MagickSizeType) columns*rows;
4960 if (extent > ((MagickSizeType) image->columns*image->rows))
4961 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4963 image->columns=columns;
4966 cache_info->columns=columns;
4967 cache_info->rows=rows;
4968 return(SyncImagePixelCache(image,exception));
4995MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4998 *magick_restrict cache_info;
5000 GetOneAuthenticPixelFromHandler
5001 get_one_authentic_pixel_from_handler;
5003 GetOneVirtualPixelFromHandler
5004 get_one_virtual_pixel_from_handler;
5009 assert(cache != (Cache) NULL);
5012 assert(cache_info->signature == MagickCoreSignature);
5013 if (IsEventLogging() != MagickFalse)
5014 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5015 cache_info->filename);
5016 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5017 cache_info->methods.get_virtual_pixel_handler=
5018 cache_methods->get_virtual_pixel_handler;
5019 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5020 cache_info->methods.destroy_pixel_handler=
5021 cache_methods->destroy_pixel_handler;
5022 if (cache_methods->get_virtual_metacontent_from_handler !=
5023 (GetVirtualMetacontentFromHandler) NULL)
5024 cache_info->methods.get_virtual_metacontent_from_handler=
5025 cache_methods->get_virtual_metacontent_from_handler;
5026 if (cache_methods->get_authentic_pixels_handler !=
5027 (GetAuthenticPixelsHandler) NULL)
5028 cache_info->methods.get_authentic_pixels_handler=
5029 cache_methods->get_authentic_pixels_handler;
5030 if (cache_methods->queue_authentic_pixels_handler !=
5031 (QueueAuthenticPixelsHandler) NULL)
5032 cache_info->methods.queue_authentic_pixels_handler=
5033 cache_methods->queue_authentic_pixels_handler;
5034 if (cache_methods->sync_authentic_pixels_handler !=
5035 (SyncAuthenticPixelsHandler) NULL)
5036 cache_info->methods.sync_authentic_pixels_handler=
5037 cache_methods->sync_authentic_pixels_handler;
5038 if (cache_methods->get_authentic_pixels_from_handler !=
5039 (GetAuthenticPixelsFromHandler) NULL)
5040 cache_info->methods.get_authentic_pixels_from_handler=
5041 cache_methods->get_authentic_pixels_from_handler;
5042 if (cache_methods->get_authentic_metacontent_from_handler !=
5043 (GetAuthenticMetacontentFromHandler) NULL)
5044 cache_info->methods.get_authentic_metacontent_from_handler=
5045 cache_methods->get_authentic_metacontent_from_handler;
5046 get_one_virtual_pixel_from_handler=
5047 cache_info->methods.get_one_virtual_pixel_from_handler;
5048 if (get_one_virtual_pixel_from_handler !=
5049 (GetOneVirtualPixelFromHandler) NULL)
5050 cache_info->methods.get_one_virtual_pixel_from_handler=
5051 cache_methods->get_one_virtual_pixel_from_handler;
5052 get_one_authentic_pixel_from_handler=
5053 cache_methods->get_one_authentic_pixel_from_handler;
5054 if (get_one_authentic_pixel_from_handler !=
5055 (GetOneAuthenticPixelFromHandler) NULL)
5056 cache_info->methods.get_one_authentic_pixel_from_handler=
5057 cache_methods->get_one_authentic_pixel_from_handler;
5098static inline MagickBooleanType AcquireCacheNexusPixels(
5099 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5102 if (length != (MagickSizeType) ((
size_t) length))
5104 (void) ThrowMagickException(exception,GetMagickModule(),
5105 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5106 cache_info->filename);
5107 return(MagickFalse);
5109 nexus_info->length=0;
5110 nexus_info->mapped=MagickFalse;
5111 if (cache_anonymous_memory <= 0)
5113 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5115 if (nexus_info->cache != (Quantum *) NULL)
5116 (
void) memset(nexus_info->cache,0,(
size_t) length);
5120 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5121 if (nexus_info->cache != (Quantum *) NULL)
5122 nexus_info->mapped=MagickTrue;
5124 if (nexus_info->cache == (Quantum *) NULL)
5126 (void) ThrowMagickException(exception,GetMagickModule(),
5127 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5128 cache_info->filename);
5129 return(MagickFalse);
5131 nexus_info->length=length;
5135static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5138 if (nexus_info->length < CACHE_LINE_SIZE)
5140 if (mode == ReadMode)
5142 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5146 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5149static Quantum *SetPixelCacheNexusPixels(
5150 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5151 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5152 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5162 assert(cache_info != (
const CacheInfo *) NULL);
5163 assert(cache_info->signature == MagickCoreSignature);
5164 if (cache_info->type == UndefinedCache)
5165 return((Quantum *) NULL);
5166 assert(nexus_info->signature == MagickCoreSignature);
5167 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5168 if ((width == 0) || (height == 0))
5170 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5171 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5172 return((Quantum *) NULL);
5174 if (((MagickSizeType) width > cache_info->width_limit) ||
5175 ((MagickSizeType) height > cache_info->height_limit))
5177 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5178 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5179 return((Quantum *) NULL);
5181 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5182 (IsValidPixelOffset(y,height) == MagickFalse))
5184 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5185 "InvalidPixel",
"`%s'",cache_info->filename);
5186 return((Quantum *) NULL);
5188 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5189 (buffered == MagickFalse))
5191 if (((x >= 0) && (y >= 0) &&
5192 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5193 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5194 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5202 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5203 return((Quantum *) NULL);
5204 offset=y*(MagickOffsetType) cache_info->columns+x;
5205 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5206 cache_info->number_channels*offset;
5207 nexus_info->metacontent=(
void *) NULL;
5208 if (cache_info->metacontent_extent != 0)
5209 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5210 offset*(MagickOffsetType) cache_info->metacontent_extent;
5211 nexus_info->region.width=width;
5212 nexus_info->region.height=height;
5213 nexus_info->region.x=x;
5214 nexus_info->region.y=y;
5215 nexus_info->authentic_pixel_cache=MagickTrue;
5216 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5217 return(nexus_info->pixels);
5223 number_pixels=(MagickSizeType) width*height;
5224 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5225 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5226 if (cache_info->metacontent_extent != 0)
5227 length+=number_pixels*cache_info->metacontent_extent;
5229 if (nexus_info->cache == (Quantum *) NULL)
5230 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5232 if (nexus_info->length < length)
5234 RelinquishCacheNexusPixels(nexus_info);
5235 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5237 if (status == MagickFalse)
5238 return((Quantum *) NULL);
5239 nexus_info->pixels=nexus_info->cache;
5240 nexus_info->metacontent=(
void *) NULL;
5241 if (cache_info->metacontent_extent != 0)
5242 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5243 cache_info->number_channels*number_pixels);
5244 nexus_info->region.width=width;
5245 nexus_info->region.height=height;
5246 nexus_info->region.x=x;
5247 nexus_info->region.y=y;
5248 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5249 MagickTrue : MagickFalse;
5250 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5251 return(nexus_info->pixels);
5284static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5288 *magick_restrict image_view;
5296 assert(image != (
Image *) NULL);
5297 assert(image->signature == MagickCoreSignature);
5298 if (IsEventLogging() != MagickFalse)
5299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5300 assert(image->cache != (Cache) NULL);
5301 image->alpha_trait=BlendPixelTrait;
5303 image_view=AcquireVirtualCacheView(image,exception);
5304#if defined(MAGICKCORE_OPENMP_SUPPORT)
5305 #pragma omp parallel for schedule(static) shared(status) \
5306 magick_number_threads(image,image,image->rows,2)
5308 for (y=0; y < (ssize_t) image->rows; y++)
5316 if (status == MagickFalse)
5318 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5319 if (q == (Quantum *) NULL)
5324 for (x=0; x < (ssize_t) image->columns; x++)
5326 SetPixelAlpha(image,alpha,q);
5327 q+=(ptrdiff_t) GetPixelChannels(image);
5329 status=SyncCacheViewAuthenticPixels(image_view,exception);
5331 image_view=DestroyCacheView(image_view);
5335MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5336 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5339 *magick_restrict cache_info;
5344 assert(image != (
Image *) NULL);
5345 assert(image->signature == MagickCoreSignature);
5346 if (IsEventLogging() != MagickFalse)
5347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5348 assert(image->cache != (Cache) NULL);
5350 assert(cache_info->signature == MagickCoreSignature);
5351 method=cache_info->virtual_pixel_method;
5352 cache_info->virtual_pixel_method=virtual_pixel_method;
5353 if ((image->columns != 0) && (image->rows != 0))
5354 switch (virtual_pixel_method)
5356 case BackgroundVirtualPixelMethod:
5358 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5359 ((image->alpha_trait & BlendPixelTrait) == 0))
5360 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5361 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5362 (IsGrayColorspace(image->colorspace) != MagickFalse))
5363 (void) SetImageColorspace(image,sRGBColorspace,exception);
5366 case TransparentVirtualPixelMethod:
5368 if ((image->alpha_trait & BlendPixelTrait) == 0)
5369 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5378#if defined(MAGICKCORE_OPENCL_SUPPORT)
5403static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5405 assert(cache_info != (
CacheInfo *) NULL);
5406 assert(cache_info->signature == MagickCoreSignature);
5407 if ((cache_info->type != MemoryCache) ||
5408 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5413 LockSemaphoreInfo(cache_info->semaphore);
5414 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5415 UnlockSemaphoreInfo(cache_info->semaphore);
5418MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5421 *magick_restrict cache_info;
5423 assert(image != (
const Image *) NULL);
5425 CopyOpenCLBuffer(cache_info);
5458MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5462 *magick_restrict cache_info;
5470 assert(image != (
Image *) NULL);
5471 assert(image->signature == MagickCoreSignature);
5472 if (image->cache == (Cache) NULL)
5473 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5475 assert(cache_info->signature == MagickCoreSignature);
5476 if (cache_info->type == UndefinedCache)
5477 return(MagickFalse);
5478 if (image->mask_trait != UpdatePixelTrait)
5480 if (((image->channels & WriteMaskChannel) != 0) &&
5481 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5482 return(MagickFalse);
5483 if (((image->channels & CompositeMaskChannel) != 0) &&
5484 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5485 return(MagickFalse);
5487 if (nexus_info->authentic_pixel_cache != MagickFalse)
5489 if (image->taint == MagickFalse)
5490 image->taint=MagickTrue;
5493 assert(cache_info->signature == MagickCoreSignature);
5494 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5495 if ((cache_info->metacontent_extent != 0) &&
5496 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5497 return(MagickFalse);
5498 if ((status != MagickFalse) && (image->taint == MagickFalse))
5499 image->taint=MagickTrue;
5530static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5534 *magick_restrict cache_info;
5537 id = GetOpenMPThreadId();
5542 assert(image != (
Image *) NULL);
5543 assert(image->signature == MagickCoreSignature);
5544 assert(image->cache != (Cache) NULL);
5546 assert(cache_info->signature == MagickCoreSignature);
5547 assert(
id < (
int) cache_info->number_threads);
5548 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5580MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5584 *magick_restrict cache_info;
5587 id = GetOpenMPThreadId();
5592 assert(image != (
Image *) NULL);
5593 assert(image->signature == MagickCoreSignature);
5594 assert(image->cache != (Cache) NULL);
5596 assert(cache_info->signature == MagickCoreSignature);
5597 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5599 status=cache_info->methods.sync_authentic_pixels_handler(image,
5603 assert(
id < (
int) cache_info->number_threads);
5604 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5636MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5640 *magick_restrict cache_info;
5642 assert(image != (
Image *) NULL);
5644 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5645 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5676static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5696 if (cache_info->metacontent_extent == 0)
5697 return(MagickFalse);
5698 if (nexus_info->authentic_pixel_cache != MagickFalse)
5700 if (nexus_info->metacontent == (
unsigned char *) NULL)
5701 return(MagickFalse);
5702 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5703 return(MagickFalse);
5704 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5705 nexus_info->region.x;
5706 length=(MagickSizeType) nexus_info->region.width*
5707 cache_info->metacontent_extent;
5708 extent=(MagickSizeType) length*nexus_info->region.height;
5709 rows=nexus_info->region.height;
5711 p=(
unsigned char *) nexus_info->metacontent;
5712 switch (cache_info->type)
5723 if ((cache_info->columns == nexus_info->region.width) &&
5724 (extent == (MagickSizeType) ((
size_t) extent)))
5729 q=(
unsigned char *) cache_info->metacontent+offset*
5730 (MagickOffsetType) cache_info->metacontent_extent;
5731 for (y=0; y < (ssize_t) rows; y++)
5733 (void) memcpy(q,p,(
size_t) length);
5734 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5735 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5744 LockSemaphoreInfo(cache_info->file_semaphore);
5745 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5747 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5748 cache_info->cache_filename);
5749 UnlockSemaphoreInfo(cache_info->file_semaphore);
5750 return(MagickFalse);
5752 if ((cache_info->columns == nexus_info->region.width) &&
5753 (extent <= MagickMaxBufferExtent))
5758 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5759 for (y=0; y < (ssize_t) rows; y++)
5761 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5762 (MagickOffsetType) extent*(MagickOffsetType)
5763 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5764 (MagickOffsetType) cache_info->metacontent_extent,length,
5765 (
const unsigned char *) p);
5766 if (count != (MagickOffsetType) length)
5768 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5769 offset+=(MagickOffsetType) cache_info->columns;
5771 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5772 (void) ClosePixelCacheOnDisk(cache_info);
5773 UnlockSemaphoreInfo(cache_info->file_semaphore);
5776 case DistributedCache:
5784 LockSemaphoreInfo(cache_info->file_semaphore);
5785 region=nexus_info->region;
5786 if ((cache_info->columns != nexus_info->region.width) ||
5787 (extent > MagickMaxBufferExtent))
5794 for (y=0; y < (ssize_t) rows; y++)
5797 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5798 if (count != (MagickOffsetType) length)
5800 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5803 UnlockSemaphoreInfo(cache_info->file_semaphore);
5809 if (y < (ssize_t) rows)
5811 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5812 cache_info->cache_filename);
5813 return(MagickFalse);
5815 if ((cache_info->debug != MagickFalse) &&
5816 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5817 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5818 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5819 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5820 nexus_info->region.x,(
double) nexus_info->region.y);
5852static MagickBooleanType WritePixelCachePixels(
5873 if (nexus_info->authentic_pixel_cache != MagickFalse)
5875 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5876 return(MagickFalse);
5877 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5878 nexus_info->region.x;
5879 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5881 extent=length*nexus_info->region.height;
5882 rows=nexus_info->region.height;
5884 p=nexus_info->pixels;
5885 switch (cache_info->type)
5896 if ((cache_info->columns == nexus_info->region.width) &&
5897 (extent == (MagickSizeType) ((
size_t) extent)))
5902 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5904 for (y=0; y < (ssize_t) rows; y++)
5906 (void) memcpy(q,p,(
size_t) length);
5907 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5908 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5917 LockSemaphoreInfo(cache_info->file_semaphore);
5918 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5920 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5921 cache_info->cache_filename);
5922 UnlockSemaphoreInfo(cache_info->file_semaphore);
5923 return(MagickFalse);
5925 if ((cache_info->columns == nexus_info->region.width) &&
5926 (extent <= MagickMaxBufferExtent))
5931 for (y=0; y < (ssize_t) rows; y++)
5933 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5934 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5935 sizeof(*p),length,(
const unsigned char *) p);
5936 if (count != (MagickOffsetType) length)
5938 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5939 offset+=(MagickOffsetType) cache_info->columns;
5941 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5942 (void) ClosePixelCacheOnDisk(cache_info);
5943 UnlockSemaphoreInfo(cache_info->file_semaphore);
5946 case DistributedCache:
5954 LockSemaphoreInfo(cache_info->file_semaphore);
5955 region=nexus_info->region;
5956 if ((cache_info->columns != nexus_info->region.width) ||
5957 (extent > MagickMaxBufferExtent))
5964 for (y=0; y < (ssize_t) rows; y++)
5967 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5968 if (count != (MagickOffsetType) length)
5970 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5973 UnlockSemaphoreInfo(cache_info->file_semaphore);
5979 if (y < (ssize_t) rows)
5981 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5982 cache_info->cache_filename);
5983 return(MagickFalse);
5985 if ((cache_info->debug != MagickFalse) &&
5986 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5987 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5988 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5989 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5990 nexus_info->region.x,(
double) nexus_info->region.y);