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)
655static inline int GetCacheNumberThreads(
const CacheInfo *source,
656 const CacheInfo *destination,
const size_t chunk,
const int factor)
659 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
660 number_threads = 1UL,
661 workload_factor = 64UL << factor;
666 number_threads=(chunk <= workload_factor) ? 1UL :
667 (chunk >= (workload_factor << 6)) ? max_threads :
668 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
672 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
673 ((destination->type != MemoryCache) && (destination->type != MapCache)))
674 number_threads=MagickMin(number_threads,4);
675 return((
int) number_threads);
678static MagickBooleanType ClonePixelCacheRepository(
682#define cache_number_threads(source,destination,chunk,factor) \
683 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
690 **magick_restrict cache_nexus,
691 **magick_restrict clone_nexus;
699 assert(cache_info != (
CacheInfo *) NULL);
700 assert(clone_info != (
CacheInfo *) NULL);
702 if (cache_info->type == PingCache)
704 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
705 if ((cache_info->storage_class == clone_info->storage_class) &&
706 (cache_info->colorspace == clone_info->colorspace) &&
707 (cache_info->alpha_trait == clone_info->alpha_trait) &&
708 (cache_info->channels == clone_info->channels) &&
709 (cache_info->columns == clone_info->columns) &&
710 (cache_info->rows == clone_info->rows) &&
711 (cache_info->number_channels == clone_info->number_channels) &&
712 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
713 (cache_info->metacontent_extent == clone_info->metacontent_extent))
718 if (((cache_info->type == MemoryCache) ||
719 (cache_info->type == MapCache)) &&
720 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
722 (void) memcpy(clone_info->pixels,cache_info->pixels,
723 cache_info->number_channels*cache_info->columns*cache_info->rows*
724 sizeof(*cache_info->pixels));
725 if ((cache_info->metacontent_extent != 0) &&
726 (clone_info->metacontent_extent != 0))
727 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
728 cache_info->columns*cache_info->rows*
729 clone_info->metacontent_extent*
sizeof(
unsigned char));
732 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
733 return(ClonePixelCacheOnDisk(cache_info,clone_info));
738 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
739 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
740 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
741 optimize=(cache_info->number_channels == clone_info->number_channels) &&
742 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
743 MagickTrue : MagickFalse;
744 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
745 clone_info->number_channels*clone_info->columns);
747#if defined(MAGICKCORE_OPENMP_SUPPORT)
748 #pragma omp parallel for schedule(static) shared(status) \
749 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
751 for (y=0; y < (ssize_t) cache_info->rows; y++)
754 id = GetOpenMPThreadId();
762 if (status == MagickFalse)
764 if (y >= (ssize_t) clone_info->rows)
766 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
767 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
768 if (pixels == (Quantum *) NULL)
770 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
771 if (status == MagickFalse)
773 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
774 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
775 if (pixels == (Quantum *) NULL)
777 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
778 if (optimize != MagickFalse)
779 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
792 p=cache_nexus[id]->pixels;
793 q=clone_nexus[id]->pixels;
794 for (x=0; x < (ssize_t) cache_info->columns; x++)
799 if (x == (ssize_t) clone_info->columns)
801 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
809 channel=clone_info->channel_map[i].channel;
810 traits=cache_info->channel_map[channel].traits;
811 if (traits != UndefinedPixelTrait)
812 *q=*(p+cache_info->channel_map[channel].offset);
815 p+=(ptrdiff_t) cache_info->number_channels;
818 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
820 if ((cache_info->metacontent_extent != 0) &&
821 (clone_info->metacontent_extent != 0))
826 length=(size_t) MagickMin(cache_info->metacontent_extent,
827 clone_info->metacontent_extent);
828#if defined(MAGICKCORE_OPENMP_SUPPORT)
829 #pragma omp parallel for schedule(static) shared(status) \
830 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
832 for (y=0; y < (ssize_t) cache_info->rows; y++)
835 id = GetOpenMPThreadId();
840 if (status == MagickFalse)
842 if (y >= (ssize_t) clone_info->rows)
844 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
845 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
846 if (pixels == (Quantum *) NULL)
848 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
849 if (status == MagickFalse)
851 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
852 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
853 if (pixels == (Quantum *) NULL)
855 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
856 (cache_nexus[
id]->metacontent != (
void *) NULL))
857 (void) memcpy(clone_nexus[
id]->metacontent,
858 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
859 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
862 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
863 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
864 if (cache_info->debug != MagickFalse)
867 message[MagickPathExtent];
869 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
870 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
871 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
872 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
899static void DestroyImagePixelCache(
Image *image)
901 assert(image != (
Image *) NULL);
902 assert(image->signature == MagickCoreSignature);
903 if (IsEventLogging() != MagickFalse)
904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
905 if (image->cache != (
void *) NULL)
906 image->cache=DestroyPixelCache(image->cache);
931MagickExport
void DestroyImagePixels(
Image *image)
934 *magick_restrict cache_info;
936 assert(image != (
const Image *) NULL);
937 assert(image->signature == MagickCoreSignature);
938 if (IsEventLogging() != MagickFalse)
939 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
940 assert(image->cache != (Cache) NULL);
942 assert(cache_info->signature == MagickCoreSignature);
943 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
945 cache_info->methods.destroy_pixel_handler(image);
948 image->cache=DestroyPixelCache(image->cache);
974static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
980 if (cache_info->file != -1)
982 status=close_utf8(cache_info->file);
983 cache_info->file=(-1);
984 RelinquishMagickResource(FileResource,1);
986 return(status == -1 ? MagickFalse : MagickTrue);
989static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
991 switch (cache_info->type)
995 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
996#if defined(MAGICKCORE_OPENCL_SUPPORT)
997 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
999 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1001 cache_info->pixels=(Quantum *) NULL;
1005 if (cache_info->mapped == MagickFalse)
1006 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1007 cache_info->pixels);
1010 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1011 cache_info->pixels=(Quantum *) NULL;
1013 RelinquishMagickResource(MemoryResource,cache_info->length);
1018 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1019 cache_info->pixels=(Quantum *) NULL;
1020 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1021 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1022 *cache_info->cache_filename=
'\0';
1023 RelinquishMagickResource(MapResource,cache_info->length);
1028 if (cache_info->file != -1)
1029 (void) ClosePixelCacheOnDisk(cache_info);
1030 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1031 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1032 *cache_info->cache_filename=
'\0';
1033 RelinquishMagickResource(DiskResource,cache_info->length);
1036 case DistributedCache:
1038 *cache_info->cache_filename=
'\0';
1040 cache_info->server_info);
1046 cache_info->type=UndefinedCache;
1047 cache_info->mapped=MagickFalse;
1048 cache_info->metacontent=(
void *) NULL;
1051MagickPrivate Cache DestroyPixelCache(Cache cache)
1054 *magick_restrict cache_info;
1056 assert(cache != (Cache) NULL);
1058 assert(cache_info->signature == MagickCoreSignature);
1059 if (IsEventLogging() != MagickFalse)
1060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1061 cache_info->filename);
1062 LockSemaphoreInfo(cache_info->semaphore);
1063 cache_info->reference_count--;
1064 if (cache_info->reference_count != 0)
1066 UnlockSemaphoreInfo(cache_info->semaphore);
1067 return((Cache) NULL);
1069 UnlockSemaphoreInfo(cache_info->semaphore);
1070 if (cache_info->debug != MagickFalse)
1073 message[MagickPathExtent];
1075 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1076 cache_info->filename);
1077 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1079 RelinquishPixelCachePixels(cache_info);
1082 cache_info->server_info);
1083 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1084 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1085 cache_info->number_threads);
1086 if (cache_info->random_info != (
RandomInfo *) NULL)
1087 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1089 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1091 RelinquishSemaphoreInfo(&cache_info->semaphore);
1092 cache_info->signature=(~MagickCoreSignature);
1093 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1124static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1126 if (nexus_info->mapped == MagickFalse)
1127 (void) RelinquishAlignedMemory(nexus_info->cache);
1129 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1130 nexus_info->cache=(Quantum *) NULL;
1131 nexus_info->pixels=(Quantum *) NULL;
1132 nexus_info->metacontent=(
void *) NULL;
1133 nexus_info->length=0;
1134 nexus_info->mapped=MagickFalse;
1138 const size_t number_threads)
1143 assert(nexus_info != (
NexusInfo **) NULL);
1144 for (i=0; i < (ssize_t) (2*number_threads); i++)
1146 if (nexus_info[i]->cache != (Quantum *) NULL)
1147 RelinquishCacheNexusPixels(nexus_info[i]);
1148 nexus_info[i]->signature=(~MagickCoreSignature);
1150 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1151 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1180MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1183 *magick_restrict cache_info;
1186 id = GetOpenMPThreadId();
1188 assert(image != (
const Image *) NULL);
1189 assert(image->signature == MagickCoreSignature);
1190 assert(image->cache != (Cache) NULL);
1192 assert(cache_info->signature == MagickCoreSignature);
1193 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1194 (GetAuthenticMetacontentFromHandler) NULL)
1199 metacontent=cache_info->methods.
1200 get_authentic_metacontent_from_handler(image);
1201 return(metacontent);
1203 assert(
id < (
int) cache_info->number_threads);
1204 return(cache_info->nexus_info[
id]->metacontent);
1231static void *GetAuthenticMetacontentFromCache(
const Image *image)
1234 *magick_restrict cache_info;
1237 id = GetOpenMPThreadId();
1239 assert(image != (
const Image *) NULL);
1240 assert(image->signature == MagickCoreSignature);
1241 assert(image->cache != (Cache) NULL);
1243 assert(cache_info->signature == MagickCoreSignature);
1244 assert(
id < (
int) cache_info->number_threads);
1245 return(cache_info->nexus_info[
id]->metacontent);
1248#if defined(MAGICKCORE_OPENCL_SUPPORT)
1277MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1281 *magick_restrict cache_info;
1283 assert(image != (
const Image *) NULL);
1284 assert(device != (
const MagickCLDevice) NULL);
1286 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1288 SyncImagePixelCache((
Image *) image,exception);
1291 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1292 return((cl_mem) NULL);
1293 LockSemaphoreInfo(cache_info->semaphore);
1294 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1295 (cache_info->opencl->device->context != device->context))
1296 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1297 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1299 assert(cache_info->pixels != (Quantum *) NULL);
1300 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1301 cache_info->length);
1303 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1304 RetainOpenCLMemObject(cache_info->opencl->buffer);
1305 UnlockSemaphoreInfo(cache_info->semaphore);
1306 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1307 return((cl_mem) NULL);
1308 assert(cache_info->opencl->pixels == cache_info->pixels);
1309 return(cache_info->opencl->buffer);
1348MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1349 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1353 *magick_restrict cache_info;
1356 *magick_restrict pixels;
1361 assert(image != (
Image *) NULL);
1362 assert(image->signature == MagickCoreSignature);
1363 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1364 nexus_info,exception);
1365 if (pixels == (Quantum *) NULL)
1366 return((Quantum *) NULL);
1368 assert(cache_info->signature == MagickCoreSignature);
1369 if (nexus_info->authentic_pixel_cache != MagickFalse)
1371 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1372 return((Quantum *) NULL);
1373 if (cache_info->metacontent_extent != 0)
1374 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1375 return((Quantum *) NULL);
1402static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1405 *magick_restrict cache_info;
1408 id = GetOpenMPThreadId();
1410 assert(image != (
const Image *) NULL);
1411 assert(image->signature == MagickCoreSignature);
1412 assert(image->cache != (Cache) NULL);
1414 assert(cache_info->signature == MagickCoreSignature);
1415 assert(
id < (
int) cache_info->number_threads);
1416 return(cache_info->nexus_info[
id]->pixels);
1443MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1446 *magick_restrict cache_info;
1449 id = GetOpenMPThreadId();
1451 assert(image != (
const Image *) NULL);
1452 assert(image->signature == MagickCoreSignature);
1453 assert(image->cache != (Cache) NULL);
1455 assert(cache_info->signature == MagickCoreSignature);
1456 if (cache_info->methods.get_authentic_pixels_from_handler !=
1457 (GetAuthenticPixelsFromHandler) NULL)
1458 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1459 assert(
id < (
int) cache_info->number_threads);
1460 return(cache_info->nexus_info[
id]->pixels);
1508MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1509 const ssize_t y,
const size_t columns,
const size_t rows,
1513 *magick_restrict cache_info;
1516 id = GetOpenMPThreadId();
1521 assert(image != (
Image *) NULL);
1522 assert(image->signature == MagickCoreSignature);
1523 assert(image->cache != (Cache) NULL);
1525 assert(cache_info->signature == MagickCoreSignature);
1526 if (cache_info->methods.get_authentic_pixels_handler !=
1527 (GetAuthenticPixelsHandler) NULL)
1529 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1533 assert(
id < (
int) cache_info->number_threads);
1534 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1535 cache_info->nexus_info[
id],exception);
1570static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1571 const ssize_t y,
const size_t columns,
const size_t rows,
1575 *magick_restrict cache_info;
1578 id = GetOpenMPThreadId();
1581 *magick_restrict pixels;
1583 assert(image != (
const Image *) NULL);
1584 assert(image->signature == MagickCoreSignature);
1585 assert(image->cache != (Cache) NULL);
1587 if (cache_info == (Cache) NULL)
1588 return((Quantum *) NULL);
1589 assert(cache_info->signature == MagickCoreSignature);
1590 assert(
id < (
int) cache_info->number_threads);
1591 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1592 cache_info->nexus_info[
id],exception);
1619MagickExport MagickSizeType GetImageExtent(
const Image *image)
1622 *magick_restrict cache_info;
1625 id = GetOpenMPThreadId();
1627 assert(image != (
Image *) NULL);
1628 assert(image->signature == MagickCoreSignature);
1629 if (IsEventLogging() != MagickFalse)
1630 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1631 assert(image->cache != (Cache) NULL);
1633 assert(cache_info->signature == MagickCoreSignature);
1634 assert(
id < (
int) cache_info->number_threads);
1635 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1668static MagickBooleanType GetDynamicThrottlePolicy(
void)
1670 static MagickBooleanType
1671 check_policy = MagickTrue;
1673 static MagickBooleanType
1674 dynamic_throttle = MagickFalse;
1676 if (check_policy != MagickFalse)
1678 char *value = GetPolicyValue(
"resource:dynamic-throttle");
1679 if (value != (
char *) NULL)
1681 dynamic_throttle=IsStringTrue(value);
1682 value=DestroyString(value);
1684 check_policy=MagickFalse;
1686 return(dynamic_throttle);
1689static inline MagickBooleanType ValidatePixelCacheMorphology(
1690 const Image *magick_restrict image)
1693 *magick_restrict cache_info;
1703 p=image->channel_map;
1704 q=cache_info->channel_map;
1705 if ((image->storage_class != cache_info->storage_class) ||
1706 (image->colorspace != cache_info->colorspace) ||
1707 (image->alpha_trait != cache_info->alpha_trait) ||
1708 (image->channels != cache_info->channels) ||
1709 (image->columns != cache_info->columns) ||
1710 (image->rows != cache_info->rows) ||
1711 (image->number_channels != cache_info->number_channels) ||
1712 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1713 (image->metacontent_extent != cache_info->metacontent_extent) ||
1714 (cache_info->nexus_info == (
NexusInfo **) NULL))
1715 return(MagickFalse);
1719static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1723 *magick_restrict cache_info;
1727 status = MagickTrue;
1729 static MagickSizeType
1730 cpu_throttle = MagickResourceInfinity,
1733 if (IsImageTTLExpired(image) != MagickFalse)
1738 (void) ThrowMagickException(exception,GetMagickModule(),
1739 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1740 return((Cache) NULL);
1742 if (cpu_throttle == MagickResourceInfinity)
1743 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1744 if ((GetDynamicThrottlePolicy() != MagickFalse) && ((cycles % 65536) == 0))
1757#if defined(MAGICKCORE_HAVE_GETLOADAVG)
1758 if (getloadavg(&load_average,1) != 1)
1761 load=MagickMax(load_average-GetOpenMPMaximumThreads(),0.0);
1762 cpu_throttle=(MagickSizeType) (max_delay*(1.0-exp(-sensitivity*load)));
1764 if ((cpu_throttle != 0) && ((cycles % 4096) == 0))
1765 MagickDelay(cpu_throttle);
1767 LockSemaphoreInfo(image->semaphore);
1768 assert(image->cache != (Cache) NULL);
1770#if defined(MAGICKCORE_OPENCL_SUPPORT)
1771 CopyOpenCLBuffer(cache_info);
1773 destroy=MagickFalse;
1774 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1776 LockSemaphoreInfo(cache_info->semaphore);
1777 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1788 clone_image=(*image);
1789 clone_image.semaphore=AcquireSemaphoreInfo();
1790 clone_image.reference_count=1;
1791 clone_image.cache=ClonePixelCache(cache_info);
1792 clone_info=(
CacheInfo *) clone_image.cache;
1793 status=OpenPixelCache(&clone_image,IOMode,exception);
1794 if (status == MagickFalse)
1795 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1798 if (clone != MagickFalse)
1799 status=ClonePixelCacheRepository(clone_info,cache_info,
1801 if (status == MagickFalse)
1802 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1806 image->cache=clone_info;
1809 RelinquishSemaphoreInfo(&clone_image.semaphore);
1811 UnlockSemaphoreInfo(cache_info->semaphore);
1813 if (destroy != MagickFalse)
1814 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1815 if (status != MagickFalse)
1820 if (image->type != UndefinedType)
1821 image->type=UndefinedType;
1822 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1824 status=OpenPixelCache(image,IOMode,exception);
1826 if (cache_info->file != -1)
1827 (void) ClosePixelCacheOnDisk(cache_info);
1830 UnlockSemaphoreInfo(image->semaphore);
1831 if (status == MagickFalse)
1832 return((Cache) NULL);
1833 return(image->cache);
1859MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1862 *magick_restrict cache_info;
1864 assert(image != (
Image *) NULL);
1865 assert(image->signature == MagickCoreSignature);
1866 assert(image->cache != (Cache) NULL);
1868 assert(cache_info->signature == MagickCoreSignature);
1869 return(cache_info->type);
1903static inline MagickBooleanType CopyPixel(
const Image *image,
1904 const Quantum *source,Quantum *destination)
1909 if (source == (
const Quantum *) NULL)
1911 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1912 destination[GreenPixelChannel]=ClampToQuantum(
1913 image->background_color.green);
1914 destination[BluePixelChannel]=ClampToQuantum(
1915 image->background_color.blue);
1916 destination[BlackPixelChannel]=ClampToQuantum(
1917 image->background_color.black);
1918 destination[AlphaPixelChannel]=ClampToQuantum(
1919 image->background_color.alpha);
1920 return(MagickFalse);
1922 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1924 PixelChannel channel = GetPixelChannelChannel(image,i);
1925 destination[channel]=source[i];
1930MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1931 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1934 *magick_restrict cache_info;
1939 assert(image != (
Image *) NULL);
1940 assert(image->signature == MagickCoreSignature);
1941 assert(image->cache != (Cache) NULL);
1943 assert(cache_info->signature == MagickCoreSignature);
1944 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1945 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1946 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1947 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1948 return(CopyPixel(image,q,pixel));
1982static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
1983 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1986 *magick_restrict cache_info;
1989 id = GetOpenMPThreadId();
1994 assert(image != (
const Image *) NULL);
1995 assert(image->signature == MagickCoreSignature);
1996 assert(image->cache != (Cache) NULL);
1998 assert(cache_info->signature == MagickCoreSignature);
1999 assert(
id < (
int) cache_info->number_threads);
2000 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2001 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
2003 return(CopyPixel(image,q,pixel));
2037MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
2038 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
2041 *magick_restrict cache_info;
2044 id = GetOpenMPThreadId();
2049 assert(image != (
const Image *) NULL);
2050 assert(image->signature == MagickCoreSignature);
2051 assert(image->cache != (Cache) NULL);
2053 assert(cache_info->signature == MagickCoreSignature);
2054 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2055 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2056 (GetOneVirtualPixelFromHandler) NULL)
2057 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2058 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2059 assert(
id < (
int) cache_info->number_threads);
2060 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2061 1UL,1UL,cache_info->nexus_info[
id],exception);
2062 return(CopyPixel(image,p,pixel));
2099static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2100 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2104 *magick_restrict cache_info;
2107 id = GetOpenMPThreadId();
2112 assert(image != (
const Image *) NULL);
2113 assert(image->signature == MagickCoreSignature);
2114 assert(image->cache != (Cache) NULL);
2116 assert(cache_info->signature == MagickCoreSignature);
2117 assert(
id < (
int) cache_info->number_threads);
2118 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2119 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2120 cache_info->nexus_info[
id],exception);
2121 return(CopyPixel(image,p,pixel));
2158MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2159 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2163 *magick_restrict cache_info;
2166 id = GetOpenMPThreadId();
2171 assert(image != (
const Image *) NULL);
2172 assert(image->signature == MagickCoreSignature);
2173 assert(image->cache != (Cache) NULL);
2175 assert(cache_info->signature == MagickCoreSignature);
2176 assert(
id < (
int) cache_info->number_threads);
2177 GetPixelInfo(image,pixel);
2178 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2179 cache_info->nexus_info[
id],exception);
2180 if (p == (
const Quantum *) NULL)
2181 return(MagickFalse);
2182 GetPixelInfoPixel(image,p,pixel);
2208MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2211 *magick_restrict cache_info;
2213 assert(cache != (Cache) NULL);
2215 assert(cache_info->signature == MagickCoreSignature);
2216 if (IsEventLogging() != MagickFalse)
2217 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2218 cache_info->filename);
2219 return(cache_info->colorspace);
2245MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2248 *magick_restrict cache_info;
2250 assert(image != (
const Image *) NULL);
2251 assert(image->signature == MagickCoreSignature);
2252 assert(image->cache != (Cache) NULL);
2254 assert(cache_info->signature == MagickCoreSignature);
2255 return(cache_info->cache_filename);
2280MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2283 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2284 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2285 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2286 cache_methods->get_virtual_metacontent_from_handler=
2287 GetVirtualMetacontentFromCache;
2288 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2289 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2290 cache_methods->get_authentic_metacontent_from_handler=
2291 GetAuthenticMetacontentFromCache;
2292 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2293 cache_methods->get_one_authentic_pixel_from_handler=
2294 GetOneAuthenticPixelFromCache;
2295 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2296 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2297 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2325MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2329 *magick_restrict cache_info;
2334 assert(cache != NULL);
2336 assert(cache_info->signature == MagickCoreSignature);
2337 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2339 return((MagickSizeType) cache_info->columns*cache_info->rows);
2370MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2374 *magick_restrict cache_info;
2376 assert(image != (
const Image *) NULL);
2377 assert(image->signature == MagickCoreSignature);
2378 assert(image->cache != (Cache) NULL);
2379 assert(length != (MagickSizeType *) NULL);
2380 magick_unreferenced(exception);
2382 assert(cache_info->signature == MagickCoreSignature);
2383 *length=cache_info->length;
2384 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2385 return((
void *) NULL);
2386 return((
void *) cache_info->pixels);
2413MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2416 *magick_restrict cache_info;
2418 assert(cache != (Cache) NULL);
2420 assert(cache_info->signature == MagickCoreSignature);
2421 if (IsEventLogging() != MagickFalse)
2422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2423 cache_info->filename);
2424 return(cache_info->storage_class);
2454MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2458 *magick_restrict cache_info;
2460 assert(image != (
Image *) NULL);
2461 assert(image->signature == MagickCoreSignature);
2462 if (IsEventLogging() != MagickFalse)
2463 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2465 assert(cache_info->signature == MagickCoreSignature);
2466 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2467 if (GetImagePixelCacheType(image) == DiskCache)
2468 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2496MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2499 *magick_restrict cache_info;
2501 assert(image != (
Image *) NULL);
2502 assert(image->signature == MagickCoreSignature);
2503 assert(image->cache != (Cache) NULL);
2505 assert(cache_info->signature == MagickCoreSignature);
2506 return(cache_info->virtual_pixel_method);
2532static const void *GetVirtualMetacontentFromCache(
const Image *image)
2535 *magick_restrict cache_info;
2538 id = GetOpenMPThreadId();
2541 *magick_restrict metacontent;
2543 assert(image != (
const Image *) NULL);
2544 assert(image->signature == MagickCoreSignature);
2545 assert(image->cache != (Cache) NULL);
2547 assert(cache_info->signature == MagickCoreSignature);
2548 assert(
id < (
int) cache_info->number_threads);
2549 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2550 cache_info->nexus_info[
id]);
2551 return(metacontent);
2580MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2584 *magick_restrict cache_info;
2586 assert(cache != (Cache) NULL);
2588 assert(cache_info->signature == MagickCoreSignature);
2589 if (cache_info->storage_class == UndefinedClass)
2590 return((
void *) NULL);
2591 return(nexus_info->metacontent);
2618MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2621 *magick_restrict cache_info;
2624 id = GetOpenMPThreadId();
2627 *magick_restrict metacontent;
2629 assert(image != (
const Image *) NULL);
2630 assert(image->signature == MagickCoreSignature);
2631 assert(image->cache != (Cache) NULL);
2633 assert(cache_info->signature == MagickCoreSignature);
2634 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2636 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2638 if (metacontent != (
const void *) NULL)
2639 return(metacontent);
2641 assert(
id < (
int) cache_info->number_threads);
2642 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2643 cache_info->nexus_info[
id]);
2644 return(metacontent);
2687 0, 48, 12, 60, 3, 51, 15, 63,
2688 32, 16, 44, 28, 35, 19, 47, 31,
2689 8, 56, 4, 52, 11, 59, 7, 55,
2690 40, 24, 36, 20, 43, 27, 39, 23,
2691 2, 50, 14, 62, 1, 49, 13, 61,
2692 34, 18, 46, 30, 33, 17, 45, 29,
2693 10, 58, 6, 54, 9, 57, 5, 53,
2694 42, 26, 38, 22, 41, 25, 37, 21
2697static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2702 index=x+DitherMatrix[x & 0x07]-32L;
2705 if (index >= (ssize_t) columns)
2706 return((ssize_t) columns-1L);
2710static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2715 index=y+DitherMatrix[y & 0x07]-32L;
2718 if (index >= (ssize_t) rows)
2719 return((ssize_t) rows-1L);
2723static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2727 if (x >= (ssize_t) columns)
2728 return((ssize_t) (columns-1));
2732static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2736 if (y >= (ssize_t) rows)
2737 return((ssize_t) (rows-1));
2741static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2742 const MagickOffsetType y)
2744 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2745 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2746 return(MagickFalse);
2750static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2752 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2755static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2757 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2760static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2761 const size_t extent)
2766 modulo.quotient=offset;
2770 modulo.quotient=offset/((ssize_t) extent);
2771 modulo.remainder=offset % ((ssize_t) extent);
2773 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2776 modulo.remainder+=((ssize_t) extent);
2781MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2782 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2783 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2787 *magick_restrict cache_info;
2803 *magick_restrict virtual_nexus;
2806 *magick_restrict pixels,
2808 virtual_pixel[MaxPixelChannels];
2819 *magick_restrict virtual_metacontent;
2824 assert(image != (
const Image *) NULL);
2825 assert(image->signature == MagickCoreSignature);
2826 assert(image->cache != (Cache) NULL);
2828 assert(cache_info->signature == MagickCoreSignature);
2829 if (cache_info->type == UndefinedCache)
2830 return((
const Quantum *) NULL);
2831#if defined(MAGICKCORE_OPENCL_SUPPORT)
2832 CopyOpenCLBuffer(cache_info);
2834 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2835 ((image->channels & WriteMaskChannel) != 0) ||
2836 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2837 nexus_info,exception);
2838 if (pixels == (Quantum *) NULL)
2839 return((
const Quantum *) NULL);
2840 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2841 return((
const Quantum *) NULL);
2842 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2843 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2844 return((
const Quantum *) NULL);
2845 offset+=nexus_info->region.x;
2846 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2847 nexus_info->region.width-1L;
2848 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2849 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2850 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2851 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2859 if (nexus_info->authentic_pixel_cache != MagickFalse)
2861 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2862 if (status == MagickFalse)
2863 return((
const Quantum *) NULL);
2864 if (cache_info->metacontent_extent != 0)
2866 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2867 if (status == MagickFalse)
2868 return((
const Quantum *) NULL);
2875 virtual_nexus=nexus_info->virtual_nexus;
2877 s=(
unsigned char *) nexus_info->metacontent;
2878 (void) memset(virtual_pixel,0,cache_info->number_channels*
2879 sizeof(*virtual_pixel));
2880 virtual_metacontent=(
void *) NULL;
2881 switch (virtual_pixel_method)
2883 case BackgroundVirtualPixelMethod:
2884 case BlackVirtualPixelMethod:
2885 case GrayVirtualPixelMethod:
2886 case TransparentVirtualPixelMethod:
2887 case MaskVirtualPixelMethod:
2888 case WhiteVirtualPixelMethod:
2889 case EdgeVirtualPixelMethod:
2890 case CheckerTileVirtualPixelMethod:
2891 case HorizontalTileVirtualPixelMethod:
2892 case VerticalTileVirtualPixelMethod:
2894 if (cache_info->metacontent_extent != 0)
2899 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2900 cache_info->metacontent_extent);
2901 if (virtual_metacontent == (
void *) NULL)
2903 (void) ThrowMagickException(exception,GetMagickModule(),
2904 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2905 return((
const Quantum *) NULL);
2907 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2909 switch (virtual_pixel_method)
2911 case BlackVirtualPixelMethod:
2913 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2914 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2915 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2918 case GrayVirtualPixelMethod:
2920 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2921 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2923 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2926 case TransparentVirtualPixelMethod:
2928 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2929 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2930 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2933 case MaskVirtualPixelMethod:
2934 case WhiteVirtualPixelMethod:
2936 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2937 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2938 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2943 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2945 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2947 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2949 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2951 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2961 for (v=0; v < (ssize_t) rows; v++)
2967 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2968 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2969 y_offset=EdgeY(y_offset,cache_info->rows);
2970 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2976 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2977 x_offset,(ssize_t) columns-u);
2978 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2979 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2989 length=(MagickSizeType) 1;
2990 switch (virtual_pixel_method)
2992 case EdgeVirtualPixelMethod:
2995 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2996 EdgeX(x_offset,cache_info->columns),
2997 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2999 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3002 case RandomVirtualPixelMethod:
3004 if (cache_info->random_info == (
RandomInfo *) NULL)
3005 cache_info->random_info=AcquireRandomInfo();
3006 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3007 RandomX(cache_info->random_info,cache_info->columns),
3008 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
3009 virtual_nexus,exception);
3010 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3013 case DitherVirtualPixelMethod:
3015 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3016 DitherX(x_offset,cache_info->columns),
3017 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
3019 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3022 case TileVirtualPixelMethod:
3024 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3025 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3026 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3027 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3029 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3032 case MirrorVirtualPixelMethod:
3034 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3035 if ((x_modulo.quotient & 0x01) == 1L)
3036 x_modulo.remainder=(ssize_t) cache_info->columns-
3037 x_modulo.remainder-1L;
3038 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3039 if ((y_modulo.quotient & 0x01) == 1L)
3040 y_modulo.remainder=(ssize_t) cache_info->rows-
3041 y_modulo.remainder-1L;
3042 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3043 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3045 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3048 case HorizontalTileEdgeVirtualPixelMethod:
3050 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3051 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3052 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3053 virtual_nexus,exception);
3054 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3057 case VerticalTileEdgeVirtualPixelMethod:
3059 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3060 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3061 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3062 virtual_nexus,exception);
3063 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3066 case BackgroundVirtualPixelMethod:
3067 case BlackVirtualPixelMethod:
3068 case GrayVirtualPixelMethod:
3069 case TransparentVirtualPixelMethod:
3070 case MaskVirtualPixelMethod:
3071 case WhiteVirtualPixelMethod:
3074 r=virtual_metacontent;
3077 case CheckerTileVirtualPixelMethod:
3079 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3080 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3081 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3084 r=virtual_metacontent;
3087 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3088 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3090 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3093 case HorizontalTileVirtualPixelMethod:
3095 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3098 r=virtual_metacontent;
3101 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3102 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3103 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3104 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3106 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3109 case VerticalTileVirtualPixelMethod:
3111 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3114 r=virtual_metacontent;
3117 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3118 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3119 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3120 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3122 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3126 if (p == (
const Quantum *) NULL)
3128 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3130 q+=(ptrdiff_t) cache_info->number_channels;
3131 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3133 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3134 s+=(ptrdiff_t) cache_info->metacontent_extent;
3141 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3142 (
size_t) length,1UL,virtual_nexus,exception);
3143 if (p == (
const Quantum *) NULL)
3145 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3146 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3148 q+=(ptrdiff_t) cache_info->number_channels*length;
3149 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3151 (void) memcpy(s,r,(
size_t) length);
3152 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3155 if (u < (ssize_t) columns)
3161 if (virtual_metacontent != (
void *) NULL)
3162 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3163 if (v < (ssize_t) rows)
3164 return((
const Quantum *) NULL);
3202static const Quantum *GetVirtualPixelCache(
const Image *image,
3203 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3204 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3207 *magick_restrict cache_info;
3210 id = GetOpenMPThreadId();
3215 assert(image != (
const Image *) NULL);
3216 assert(image->signature == MagickCoreSignature);
3217 assert(image->cache != (Cache) NULL);
3219 assert(cache_info->signature == MagickCoreSignature);
3220 assert(
id < (
int) cache_info->number_threads);
3221 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3222 cache_info->nexus_info[
id],exception);
3249MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3252 *magick_restrict cache_info;
3255 id = GetOpenMPThreadId();
3257 assert(image != (
const Image *) NULL);
3258 assert(image->signature == MagickCoreSignature);
3259 assert(image->cache != (Cache) NULL);
3261 assert(cache_info->signature == MagickCoreSignature);
3262 if (cache_info->methods.get_virtual_pixels_handler !=
3263 (GetVirtualPixelsHandler) NULL)
3264 return(cache_info->methods.get_virtual_pixels_handler(image));
3265 assert(
id < (
int) cache_info->number_threads);
3266 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3317MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3318 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3322 *magick_restrict cache_info;
3325 id = GetOpenMPThreadId();
3330 assert(image != (
const Image *) NULL);
3331 assert(image->signature == MagickCoreSignature);
3332 assert(image->cache != (Cache) NULL);
3334 assert(cache_info->signature == MagickCoreSignature);
3335 if (cache_info->methods.get_virtual_pixel_handler !=
3336 (GetVirtualPixelHandler) NULL)
3337 return(cache_info->methods.get_virtual_pixel_handler(image,
3338 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3339 assert(
id < (
int) cache_info->number_threads);
3340 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3341 columns,rows,cache_info->nexus_info[
id],exception);
3368static const Quantum *GetVirtualPixelsCache(
const Image *image)
3371 *magick_restrict cache_info;
3374 id = GetOpenMPThreadId();
3376 assert(image != (
const Image *) NULL);
3377 assert(image->signature == MagickCoreSignature);
3378 assert(image->cache != (Cache) NULL);
3380 assert(cache_info->signature == MagickCoreSignature);
3381 assert(
id < (
int) cache_info->number_threads);
3382 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3411MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3415 *magick_restrict cache_info;
3417 assert(cache != (Cache) NULL);
3419 assert(cache_info->signature == MagickCoreSignature);
3420 if (cache_info->storage_class == UndefinedClass)
3421 return((Quantum *) NULL);
3422 return((
const Quantum *) nexus_info->pixels);
3455static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3456 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3461 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3463 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3464 gamma=MagickSafeReciprocal(gamma);
3465 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3468static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3472 *magick_restrict cache_info;
3484 if (IsEventLogging() != MagickFalse)
3485 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3486 if ((image->channels & CompositeMaskChannel) == 0)
3488 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3491 if (cache_info == (Cache) NULL)
3492 return(MagickFalse);
3493 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3494 nexus_info->region.width,nexus_info->region.height,
3495 nexus_info->virtual_nexus,exception);
3496 q=nexus_info->pixels;
3497 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3498 return(MagickFalse);
3499 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3504 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3512 alpha=(double) GetPixelCompositeMask(image,p);
3513 for (i=0; i < (ssize_t) image->number_channels; i++)
3515 PixelChannel channel = GetPixelChannelChannel(image,i);
3516 PixelTrait traits = GetPixelChannelTraits(image,channel);
3517 if ((traits & UpdatePixelTrait) == 0)
3519 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3521 p+=(ptrdiff_t) GetPixelChannels(image);
3522 q+=(ptrdiff_t) GetPixelChannels(image);
3559static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3568 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3570 if (*cache_info->cache_filename ==
'\0')
3571 file=AcquireUniqueFileResource(cache_info->cache_filename);
3577 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3582 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3583 O_BINARY | O_EXCL,S_MODE);
3585 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3591 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3594 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3599 return(MagickFalse);
3600 (void) AcquireMagickResource(FileResource,1);
3601 if (cache_info->file != -1)
3602 (void) ClosePixelCacheOnDisk(cache_info);
3603 cache_info->file=file;
3604 cache_info->disk_mode=mode;
3608static inline MagickOffsetType WritePixelCacheRegion(
3609 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3610 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3618#if !defined(MAGICKCORE_HAVE_PWRITE)
3619 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3620 return((MagickOffsetType) -1);
3622 for (i=0; i < (MagickOffsetType) length; i+=count)
3624#if !defined(MAGICKCORE_HAVE_PWRITE)
3625 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3626 (MagickSizeType) i,MagickMaxBufferExtent));
3628 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3629 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3641static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3644 *magick_restrict cache_info;
3650 if (cache_info->debug != MagickFalse)
3653 format[MagickPathExtent],
3654 message[MagickPathExtent];
3656 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3657 (void) FormatLocaleString(message,MagickPathExtent,
3658 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3659 cache_info->cache_filename,cache_info->file,format);
3660 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3662 if (length != (MagickSizeType) ((MagickOffsetType) length))
3663 return(MagickFalse);
3664 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3666 return(MagickFalse);
3667 if ((MagickSizeType) offset < length)
3673 extent=(MagickOffsetType) length-1;
3674 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3677 return(MagickFalse);
3678#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3679 if (cache_info->synchronize != MagickFalse)
3680 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3681 return(MagickFalse);
3684 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3686 return(MagickFalse);
3690static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3694 *magick_restrict cache_info,
3698 format[MagickPathExtent],
3699 message[MagickPathExtent];
3716 assert(image != (
const Image *) NULL);
3717 assert(image->signature == MagickCoreSignature);
3718 assert(image->cache != (Cache) NULL);
3719 if (IsEventLogging() != MagickFalse)
3720 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3721 if (cache_anonymous_memory < 0)
3729 cache_anonymous_memory=0;
3730 value=GetPolicyValue(
"pixel-cache-memory");
3731 if (value == (
char *) NULL)
3732 value=GetPolicyValue(
"cache:memory-map");
3733 if (LocaleCompare(value,
"anonymous") == 0)
3735#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3736 cache_anonymous_memory=1;
3738 (void) ThrowMagickException(exception,GetMagickModule(),
3739 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3740 "`%s' (policy requires anonymous memory mapping)",image->filename);
3743 value=DestroyString(value);
3745 if ((image->columns == 0) || (image->rows == 0))
3746 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3748 assert(cache_info->signature == MagickCoreSignature);
3749 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3750 ((MagickSizeType) image->rows > cache_info->height_limit))
3752 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3753 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3754 image->filename, (double) image->columns, (
double) image->rows,
3755 (double) cache_info->width_limit,(
double) cache_info->height_limit);
3756 return(MagickFalse);
3758 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3760 length=GetImageListLength(image);
3761 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3762 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3765 source_info=(*cache_info);
3766 source_info.file=(-1);
3767 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3768 image->filename,(
double) image->scene);
3769 cache_info->storage_class=image->storage_class;
3770 cache_info->colorspace=image->colorspace;
3771 cache_info->alpha_trait=image->alpha_trait;
3772 cache_info->channels=image->channels;
3773 cache_info->rows=image->rows;
3774 cache_info->columns=image->columns;
3775 status=ResetPixelChannelMap(image,exception);
3776 if (status == MagickFalse)
3777 return(MagickFalse);
3778 cache_info->number_channels=GetPixelChannels(image);
3779 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3780 sizeof(*image->channel_map));
3781 cache_info->metacontent_extent=image->metacontent_extent;
3782 cache_info->mode=mode;
3783 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3784 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3785 if (image->metacontent_extent != 0)
3786 packet_size+=cache_info->metacontent_extent;
3787 length=number_pixels*packet_size;
3788 columns=(size_t) (length/cache_info->rows/packet_size);
3789 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3790 ((ssize_t) cache_info->rows < 0))
3791 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3793 cache_info->length=length;
3794 if (image->ping != MagickFalse)
3796 cache_info->type=PingCache;
3799 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3800 cache_info->columns*cache_info->rows);
3801 if (cache_info->mode == PersistMode)
3803 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3804 cache_info->metacontent_extent);
3805 if ((status != MagickFalse) &&
3806 (length == (MagickSizeType) ((
size_t) length)) &&
3807 ((cache_info->type == UndefinedCache) ||
3808 (cache_info->type == MemoryCache)))
3810 status=AcquireMagickResource(MemoryResource,cache_info->length);
3811 if (status != MagickFalse)
3814 if (cache_anonymous_memory <= 0)
3816 cache_info->mapped=MagickFalse;
3817 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3818 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3822 cache_info->mapped=MagickTrue;
3823 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3824 cache_info->length);
3826 if (cache_info->pixels == (Quantum *) NULL)
3828 cache_info->mapped=source_info.mapped;
3829 cache_info->pixels=source_info.pixels;
3836 cache_info->type=MemoryCache;
3837 cache_info->metacontent=(
void *) NULL;
3838 if (cache_info->metacontent_extent != 0)
3839 cache_info->metacontent=(
void *) (cache_info->pixels+
3840 cache_info->number_channels*number_pixels);
3841 if ((source_info.storage_class != UndefinedClass) &&
3844 status=ClonePixelCacheRepository(cache_info,&source_info,
3846 RelinquishPixelCachePixels(&source_info);
3848 if (cache_info->debug != MagickFalse)
3850 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3851 MagickPathExtent,format);
3852 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3854 (void) FormatLocaleString(message,MagickPathExtent,
3855 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3856 cache_info->filename,cache_info->mapped != MagickFalse ?
3857 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3858 (double) cache_info->rows,(double)
3859 cache_info->number_channels,format);
3860 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3863 cache_info->storage_class=image->storage_class;
3866 if ((source_info.storage_class != UndefinedClass) &&
3868 RelinquishPixelCachePixels(&source_info);
3869 cache_info->type=UndefinedCache;
3870 return(MagickFalse);
3876 status=AcquireMagickResource(DiskResource,cache_info->length);
3877 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3879 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3887 server_info=AcquireDistributeCacheInfo(exception);
3890 status=OpenDistributePixelCache(server_info,image);
3891 if (status == MagickFalse)
3893 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3894 GetDistributeCacheHostname(server_info));
3895 server_info=DestroyDistributeCacheInfo(server_info);
3903 cache_info->type=DistributedCache;
3904 cache_info->server_info=server_info;
3905 (void) FormatLocaleString(cache_info->cache_filename,
3906 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3909 cache_info->server_info));
3910 if ((source_info.storage_class != UndefinedClass) &&
3913 status=ClonePixelCacheRepository(cache_info,&source_info,
3915 RelinquishPixelCachePixels(&source_info);
3917 if (cache_info->debug != MagickFalse)
3919 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3920 MagickPathExtent,format);
3921 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3923 (void) FormatLocaleString(message,MagickPathExtent,
3924 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3925 cache_info->filename,cache_info->cache_filename,
3927 cache_info->server_info),type,(double) cache_info->columns,
3928 (
double) cache_info->rows,(double)
3929 cache_info->number_channels,format);
3930 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3935 if ((source_info.storage_class != UndefinedClass) &&
3937 RelinquishPixelCachePixels(&source_info);
3938 cache_info->type=UndefinedCache;
3939 return(MagickFalse);
3944 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3945 RelinquishPixelCachePixels(&source_info);
3946 cache_info->type=UndefinedCache;
3947 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3948 "CacheResourcesExhausted",
"`%s'",image->filename);
3949 return(MagickFalse);
3954 if (status == MagickFalse)
3956 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3957 RelinquishPixelCachePixels(&source_info);
3958 cache_info->type=UndefinedCache;
3959 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3960 "CacheResourcesExhausted",
"`%s'",image->filename);
3961 return(MagickFalse);
3963 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3964 (cache_info->mode != PersistMode))
3966 (void) ClosePixelCacheOnDisk(cache_info);
3967 *cache_info->cache_filename=
'\0';
3969 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3971 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3972 RelinquishPixelCachePixels(&source_info);
3973 cache_info->type=UndefinedCache;
3974 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3976 return(MagickFalse);
3978 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3979 cache_info->length);
3980 if (status == MagickFalse)
3982 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3983 RelinquishPixelCachePixels(&source_info);
3984 cache_info->type=UndefinedCache;
3985 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3987 return(MagickFalse);
3989 cache_info->type=DiskCache;
3990 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3991 cache_info->metacontent_extent);
3992 if (length == (MagickSizeType) ((
size_t) length))
3994 status=AcquireMagickResource(MapResource,cache_info->length);
3995 if (status != MagickFalse)
3997 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3998 cache_info->offset,(
size_t) cache_info->length);
3999 if (cache_info->pixels == (Quantum *) NULL)
4001 cache_info->mapped=source_info.mapped;
4002 cache_info->pixels=source_info.pixels;
4003 RelinquishMagickResource(MapResource,cache_info->length);
4010 (void) ClosePixelCacheOnDisk(cache_info);
4011 cache_info->type=MapCache;
4012 cache_info->mapped=MagickTrue;
4013 cache_info->metacontent=(
void *) NULL;
4014 if (cache_info->metacontent_extent != 0)
4015 cache_info->metacontent=(
void *) (cache_info->pixels+
4016 cache_info->number_channels*number_pixels);
4017 if ((source_info.storage_class != UndefinedClass) &&
4020 status=ClonePixelCacheRepository(cache_info,&source_info,
4022 RelinquishPixelCachePixels(&source_info);
4024 if (cache_info->debug != MagickFalse)
4026 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4027 MagickPathExtent,format);
4028 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4030 (void) FormatLocaleString(message,MagickPathExtent,
4031 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4032 cache_info->filename,cache_info->cache_filename,
4033 cache_info->file,type,(
double) cache_info->columns,
4034 (double) cache_info->rows,(
double)
4035 cache_info->number_channels,format);
4036 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4041 if ((source_info.storage_class != UndefinedClass) &&
4043 RelinquishPixelCachePixels(&source_info);
4044 cache_info->type=UndefinedCache;
4045 return(MagickFalse);
4052 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4054 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4055 RelinquishPixelCachePixels(&source_info);
4057 if (cache_info->debug != MagickFalse)
4059 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4060 MagickPathExtent,format);
4061 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4063 (void) FormatLocaleString(message,MagickPathExtent,
4064 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4065 cache_info->cache_filename,cache_info->file,type,(
double)
4066 cache_info->columns,(double) cache_info->rows,(
double)
4067 cache_info->number_channels,format);
4068 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4072 cache_info->type=UndefinedCache;
4073 return(MagickFalse);
4115MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4116 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4120 *magick_restrict cache_info,
4121 *magick_restrict clone_info;
4129 assert(image != (
Image *) NULL);
4130 assert(image->signature == MagickCoreSignature);
4131 if (IsEventLogging() != MagickFalse)
4132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4133 assert(image->cache != (
void *) NULL);
4134 assert(filename != (
const char *) NULL);
4135 assert(offset != (MagickOffsetType *) NULL);
4136 page_size=GetMagickPageSize();
4138 assert(cache_info->signature == MagickCoreSignature);
4139#if defined(MAGICKCORE_OPENCL_SUPPORT)
4140 CopyOpenCLBuffer(cache_info);
4142 if (attach != MagickFalse)
4147 if (cache_info->debug != MagickFalse)
4148 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4149 "attach persistent cache");
4150 (void) CopyMagickString(cache_info->cache_filename,filename,
4152 cache_info->type=MapCache;
4153 cache_info->offset=(*offset);
4154 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4155 return(MagickFalse);
4156 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4157 ((MagickOffsetType) cache_info->length % page_size));
4163 status=AcquireMagickResource(DiskResource,cache_info->length);
4164 if (status == MagickFalse)
4166 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4167 "CacheResourcesExhausted",
"`%s'",image->filename);
4168 return(MagickFalse);
4170 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4171 clone_info->type=DiskCache;
4172 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4173 clone_info->file=(-1);
4174 clone_info->storage_class=cache_info->storage_class;
4175 clone_info->colorspace=cache_info->colorspace;
4176 clone_info->alpha_trait=cache_info->alpha_trait;
4177 clone_info->channels=cache_info->channels;
4178 clone_info->columns=cache_info->columns;
4179 clone_info->rows=cache_info->rows;
4180 clone_info->number_channels=cache_info->number_channels;
4181 clone_info->metacontent_extent=cache_info->metacontent_extent;
4182 clone_info->mode=PersistMode;
4183 clone_info->length=cache_info->length;
4184 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4185 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4186 clone_info->offset=(*offset);
4187 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4188 if (status != MagickFalse)
4189 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4190 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4191 ((MagickOffsetType) cache_info->length % page_size));
4192 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4234MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4235 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4239 *magick_restrict cache_info;
4248 *magick_restrict pixels;
4253 assert(image != (
const Image *) NULL);
4254 assert(image->signature == MagickCoreSignature);
4255 assert(image->cache != (Cache) NULL);
4256 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4257 if (cache_info == (Cache) NULL)
4258 return((Quantum *) NULL);
4259 assert(cache_info->signature == MagickCoreSignature);
4260 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4261 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4262 (y >= (ssize_t) cache_info->rows))
4264 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4265 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4266 return((Quantum *) NULL);
4268 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4269 return((Quantum *) NULL);
4270 offset=y*(MagickOffsetType) cache_info->columns+x;
4272 return((Quantum *) NULL);
4273 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4274 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4275 (MagickOffsetType) columns-1;
4276 if ((MagickSizeType) offset >= number_pixels)
4277 return((Quantum *) NULL);
4281 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4282 ((image->channels & WriteMaskChannel) != 0) ||
4283 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4284 nexus_info,exception);
4321static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4322 const ssize_t y,
const size_t columns,
const size_t rows,
4326 *magick_restrict cache_info;
4329 id = GetOpenMPThreadId();
4332 *magick_restrict pixels;
4334 assert(image != (
const Image *) NULL);
4335 assert(image->signature == MagickCoreSignature);
4336 assert(image->cache != (Cache) NULL);
4338 assert(cache_info->signature == MagickCoreSignature);
4339 assert(
id < (
int) cache_info->number_threads);
4340 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4341 cache_info->nexus_info[
id],exception);
4401MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4402 const ssize_t y,
const size_t columns,
const size_t rows,
4406 *magick_restrict cache_info;
4409 id = GetOpenMPThreadId();
4412 *magick_restrict pixels;
4414 assert(image != (
Image *) NULL);
4415 assert(image->signature == MagickCoreSignature);
4416 assert(image->cache != (Cache) NULL);
4418 assert(cache_info->signature == MagickCoreSignature);
4419 if (cache_info->methods.queue_authentic_pixels_handler !=
4420 (QueueAuthenticPixelsHandler) NULL)
4422 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4423 columns,rows,exception);
4426 assert(
id < (
int) cache_info->number_threads);
4427 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4428 cache_info->nexus_info[
id],exception);
4461static inline MagickOffsetType ReadPixelCacheRegion(
4462 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4463 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4471#if !defined(MAGICKCORE_HAVE_PREAD)
4472 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4473 return((MagickOffsetType) -1);
4475 for (i=0; i < (MagickOffsetType) length; i+=count)
4477#if !defined(MAGICKCORE_HAVE_PREAD)
4478 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4479 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4481 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4482 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4494static MagickBooleanType ReadPixelCacheMetacontent(
4515 if (cache_info->metacontent_extent == 0)
4516 return(MagickFalse);
4517 if (nexus_info->authentic_pixel_cache != MagickFalse)
4519 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4520 return(MagickFalse);
4521 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4522 nexus_info->region.x;
4523 length=(MagickSizeType) nexus_info->region.width*
4524 cache_info->metacontent_extent;
4525 extent=length*nexus_info->region.height;
4526 rows=nexus_info->region.height;
4528 q=(
unsigned char *) nexus_info->metacontent;
4529 switch (cache_info->type)
4540 if ((cache_info->columns == nexus_info->region.width) &&
4541 (extent == (MagickSizeType) ((
size_t) extent)))
4546 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4547 cache_info->metacontent_extent;
4548 for (y=0; y < (ssize_t) rows; y++)
4550 (void) memcpy(q,p,(
size_t) length);
4551 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4552 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4561 LockSemaphoreInfo(cache_info->file_semaphore);
4562 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4564 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4565 cache_info->cache_filename);
4566 UnlockSemaphoreInfo(cache_info->file_semaphore);
4567 return(MagickFalse);
4569 if ((cache_info->columns == nexus_info->region.width) &&
4570 (extent <= MagickMaxBufferExtent))
4575 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4576 for (y=0; y < (ssize_t) rows; y++)
4578 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4579 (MagickOffsetType) extent*(MagickOffsetType)
4580 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4581 (MagickOffsetType) cache_info->metacontent_extent,length,
4582 (
unsigned char *) q);
4583 if (count != (MagickOffsetType) length)
4585 offset+=(MagickOffsetType) cache_info->columns;
4586 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4588 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4589 (void) ClosePixelCacheOnDisk(cache_info);
4590 UnlockSemaphoreInfo(cache_info->file_semaphore);
4593 case DistributedCache:
4601 LockSemaphoreInfo(cache_info->file_semaphore);
4602 region=nexus_info->region;
4603 if ((cache_info->columns != nexus_info->region.width) ||
4604 (extent > MagickMaxBufferExtent))
4611 for (y=0; y < (ssize_t) rows; y++)
4614 cache_info->server_info,®ion,length,(
unsigned char *) q);
4615 if (count != (MagickOffsetType) length)
4617 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4620 UnlockSemaphoreInfo(cache_info->file_semaphore);
4626 if (y < (ssize_t) rows)
4628 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4629 cache_info->cache_filename);
4630 return(MagickFalse);
4632 if ((cache_info->debug != MagickFalse) &&
4633 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4634 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4635 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4636 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4637 nexus_info->region.x,(
double) nexus_info->region.y);
4669static MagickBooleanType ReadPixelCachePixels(
4691 if (nexus_info->authentic_pixel_cache != MagickFalse)
4693 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4694 return(MagickFalse);
4695 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4696 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4697 return(MagickFalse);
4698 offset+=nexus_info->region.x;
4699 number_channels=cache_info->number_channels;
4700 length=(MagickSizeType) number_channels*nexus_info->region.width*
4702 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4703 return(MagickFalse);
4704 rows=nexus_info->region.height;
4706 if ((extent == 0) || ((extent/length) != rows))
4707 return(MagickFalse);
4709 q=nexus_info->pixels;
4710 switch (cache_info->type)
4721 if ((cache_info->columns == nexus_info->region.width) &&
4722 (extent == (MagickSizeType) ((
size_t) extent)))
4727 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4729 for (y=0; y < (ssize_t) rows; y++)
4731 (void) memcpy(q,p,(
size_t) length);
4732 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4733 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4742 LockSemaphoreInfo(cache_info->file_semaphore);
4743 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4745 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4746 cache_info->cache_filename);
4747 UnlockSemaphoreInfo(cache_info->file_semaphore);
4748 return(MagickFalse);
4750 if ((cache_info->columns == nexus_info->region.width) &&
4751 (extent <= MagickMaxBufferExtent))
4756 for (y=0; y < (ssize_t) rows; y++)
4758 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4759 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4760 sizeof(*q),length,(
unsigned char *) q);
4761 if (count != (MagickOffsetType) length)
4763 offset+=(MagickOffsetType) cache_info->columns;
4764 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4766 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4767 (void) ClosePixelCacheOnDisk(cache_info);
4768 UnlockSemaphoreInfo(cache_info->file_semaphore);
4771 case DistributedCache:
4779 LockSemaphoreInfo(cache_info->file_semaphore);
4780 region=nexus_info->region;
4781 if ((cache_info->columns != nexus_info->region.width) ||
4782 (extent > MagickMaxBufferExtent))
4789 for (y=0; y < (ssize_t) rows; y++)
4792 cache_info->server_info,®ion,length,(
unsigned char *) q);
4793 if (count != (MagickOffsetType) length)
4795 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4798 UnlockSemaphoreInfo(cache_info->file_semaphore);
4804 if (y < (ssize_t) rows)
4806 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4807 cache_info->cache_filename);
4808 return(MagickFalse);
4810 if ((cache_info->debug != MagickFalse) &&
4811 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4812 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4813 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4814 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4815 nexus_info->region.x,(
double) nexus_info->region.y);
4842MagickPrivate Cache ReferencePixelCache(Cache cache)
4845 *magick_restrict cache_info;
4847 assert(cache != (Cache *) NULL);
4849 assert(cache_info->signature == MagickCoreSignature);
4850 LockSemaphoreInfo(cache_info->semaphore);
4851 cache_info->reference_count++;
4852 UnlockSemaphoreInfo(cache_info->semaphore);
4878MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4881 *magick_restrict cache_info;
4883 assert(image != (
const Image *) NULL);
4884 assert(image->signature == MagickCoreSignature);
4885 assert(image->cache != (Cache) NULL);
4887 assert(cache_info->signature == MagickCoreSignature);
4888 cache_info->number_channels=GetPixelChannels(image);
4909MagickPrivate
void ResetCacheAnonymousMemory(
void)
4911 cache_anonymous_memory=0;
4943MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4944 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4952 assert(image != (
Image *) NULL);
4953 assert(image->signature == MagickCoreSignature);
4954 if (IsEventLogging() != MagickFalse)
4955 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4956 assert(image->cache != (
void *) NULL);
4957 extent=(MagickSizeType) columns*rows;
4958 if (extent > ((MagickSizeType) image->columns*image->rows))
4959 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4961 image->columns=columns;
4964 cache_info->columns=columns;
4965 cache_info->rows=rows;
4966 return(SyncImagePixelCache(image,exception));
4993MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4996 *magick_restrict cache_info;
4998 GetOneAuthenticPixelFromHandler
4999 get_one_authentic_pixel_from_handler;
5001 GetOneVirtualPixelFromHandler
5002 get_one_virtual_pixel_from_handler;
5007 assert(cache != (Cache) NULL);
5010 assert(cache_info->signature == MagickCoreSignature);
5011 if (IsEventLogging() != MagickFalse)
5012 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
5013 cache_info->filename);
5014 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5015 cache_info->methods.get_virtual_pixel_handler=
5016 cache_methods->get_virtual_pixel_handler;
5017 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5018 cache_info->methods.destroy_pixel_handler=
5019 cache_methods->destroy_pixel_handler;
5020 if (cache_methods->get_virtual_metacontent_from_handler !=
5021 (GetVirtualMetacontentFromHandler) NULL)
5022 cache_info->methods.get_virtual_metacontent_from_handler=
5023 cache_methods->get_virtual_metacontent_from_handler;
5024 if (cache_methods->get_authentic_pixels_handler !=
5025 (GetAuthenticPixelsHandler) NULL)
5026 cache_info->methods.get_authentic_pixels_handler=
5027 cache_methods->get_authentic_pixels_handler;
5028 if (cache_methods->queue_authentic_pixels_handler !=
5029 (QueueAuthenticPixelsHandler) NULL)
5030 cache_info->methods.queue_authentic_pixels_handler=
5031 cache_methods->queue_authentic_pixels_handler;
5032 if (cache_methods->sync_authentic_pixels_handler !=
5033 (SyncAuthenticPixelsHandler) NULL)
5034 cache_info->methods.sync_authentic_pixels_handler=
5035 cache_methods->sync_authentic_pixels_handler;
5036 if (cache_methods->get_authentic_pixels_from_handler !=
5037 (GetAuthenticPixelsFromHandler) NULL)
5038 cache_info->methods.get_authentic_pixels_from_handler=
5039 cache_methods->get_authentic_pixels_from_handler;
5040 if (cache_methods->get_authentic_metacontent_from_handler !=
5041 (GetAuthenticMetacontentFromHandler) NULL)
5042 cache_info->methods.get_authentic_metacontent_from_handler=
5043 cache_methods->get_authentic_metacontent_from_handler;
5044 get_one_virtual_pixel_from_handler=
5045 cache_info->methods.get_one_virtual_pixel_from_handler;
5046 if (get_one_virtual_pixel_from_handler !=
5047 (GetOneVirtualPixelFromHandler) NULL)
5048 cache_info->methods.get_one_virtual_pixel_from_handler=
5049 cache_methods->get_one_virtual_pixel_from_handler;
5050 get_one_authentic_pixel_from_handler=
5051 cache_methods->get_one_authentic_pixel_from_handler;
5052 if (get_one_authentic_pixel_from_handler !=
5053 (GetOneAuthenticPixelFromHandler) NULL)
5054 cache_info->methods.get_one_authentic_pixel_from_handler=
5055 cache_methods->get_one_authentic_pixel_from_handler;
5096static inline MagickBooleanType AcquireCacheNexusPixels(
5097 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5100 if (length != (MagickSizeType) ((
size_t) length))
5102 (void) ThrowMagickException(exception,GetMagickModule(),
5103 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5104 cache_info->filename);
5105 return(MagickFalse);
5107 nexus_info->length=0;
5108 nexus_info->mapped=MagickFalse;
5109 if (cache_anonymous_memory <= 0)
5111 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5113 if (nexus_info->cache != (Quantum *) NULL)
5114 (
void) memset(nexus_info->cache,0,(
size_t) length);
5118 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5119 if (nexus_info->cache != (Quantum *) NULL)
5120 nexus_info->mapped=MagickTrue;
5122 if (nexus_info->cache == (Quantum *) NULL)
5124 (void) ThrowMagickException(exception,GetMagickModule(),
5125 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5126 cache_info->filename);
5127 return(MagickFalse);
5129 nexus_info->length=length;
5133static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5136 if (nexus_info->length < CACHE_LINE_SIZE)
5138 if (mode == ReadMode)
5140 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5144 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5147static Quantum *SetPixelCacheNexusPixels(
5148 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5149 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5150 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5160 assert(cache_info != (
const CacheInfo *) NULL);
5161 assert(cache_info->signature == MagickCoreSignature);
5162 if (cache_info->type == UndefinedCache)
5163 return((Quantum *) NULL);
5164 assert(nexus_info->signature == MagickCoreSignature);
5165 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5166 if ((width == 0) || (height == 0))
5168 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5169 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5170 return((Quantum *) NULL);
5172 if (((MagickSizeType) width > cache_info->width_limit) ||
5173 ((MagickSizeType) height > cache_info->height_limit))
5175 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5176 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5177 return((Quantum *) NULL);
5179 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5180 (IsValidPixelOffset(y,height) == MagickFalse))
5182 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5183 "InvalidPixel",
"`%s'",cache_info->filename);
5184 return((Quantum *) NULL);
5186 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5187 (buffered == MagickFalse))
5189 if (((x >= 0) && (y >= 0) &&
5190 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5191 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5192 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5200 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5201 return((Quantum *) NULL);
5202 offset=y*(MagickOffsetType) cache_info->columns+x;
5203 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5204 cache_info->number_channels*offset;
5205 nexus_info->metacontent=(
void *) NULL;
5206 if (cache_info->metacontent_extent != 0)
5207 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5208 offset*(MagickOffsetType) cache_info->metacontent_extent;
5209 nexus_info->region.width=width;
5210 nexus_info->region.height=height;
5211 nexus_info->region.x=x;
5212 nexus_info->region.y=y;
5213 nexus_info->authentic_pixel_cache=MagickTrue;
5214 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5215 return(nexus_info->pixels);
5221 number_pixels=(MagickSizeType) width*height;
5222 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5223 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5224 if (cache_info->metacontent_extent != 0)
5225 length+=number_pixels*cache_info->metacontent_extent;
5227 if (nexus_info->cache == (Quantum *) NULL)
5228 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5230 if (nexus_info->length < length)
5232 RelinquishCacheNexusPixels(nexus_info);
5233 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5235 if (status == MagickFalse)
5236 return((Quantum *) NULL);
5237 nexus_info->pixels=nexus_info->cache;
5238 nexus_info->metacontent=(
void *) NULL;
5239 if (cache_info->metacontent_extent != 0)
5240 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5241 cache_info->number_channels*number_pixels);
5242 nexus_info->region.width=width;
5243 nexus_info->region.height=height;
5244 nexus_info->region.x=x;
5245 nexus_info->region.y=y;
5246 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5247 MagickTrue : MagickFalse;
5248 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5249 return(nexus_info->pixels);
5282static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5286 *magick_restrict image_view;
5294 assert(image != (
Image *) NULL);
5295 assert(image->signature == MagickCoreSignature);
5296 if (IsEventLogging() != MagickFalse)
5297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5298 assert(image->cache != (Cache) NULL);
5299 image->alpha_trait=BlendPixelTrait;
5301 image_view=AcquireVirtualCacheView(image,exception);
5302#if defined(MAGICKCORE_OPENMP_SUPPORT)
5303 #pragma omp parallel for schedule(static) shared(status) \
5304 magick_number_threads(image,image,image->rows,2)
5306 for (y=0; y < (ssize_t) image->rows; y++)
5314 if (status == MagickFalse)
5316 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5317 if (q == (Quantum *) NULL)
5322 for (x=0; x < (ssize_t) image->columns; x++)
5324 SetPixelAlpha(image,alpha,q);
5325 q+=(ptrdiff_t) GetPixelChannels(image);
5327 status=SyncCacheViewAuthenticPixels(image_view,exception);
5329 image_view=DestroyCacheView(image_view);
5333MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5334 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5337 *magick_restrict cache_info;
5342 assert(image != (
Image *) NULL);
5343 assert(image->signature == MagickCoreSignature);
5344 if (IsEventLogging() != MagickFalse)
5345 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5346 assert(image->cache != (Cache) NULL);
5348 assert(cache_info->signature == MagickCoreSignature);
5349 method=cache_info->virtual_pixel_method;
5350 cache_info->virtual_pixel_method=virtual_pixel_method;
5351 if ((image->columns != 0) && (image->rows != 0))
5352 switch (virtual_pixel_method)
5354 case BackgroundVirtualPixelMethod:
5356 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5357 ((image->alpha_trait & BlendPixelTrait) == 0))
5358 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5359 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5360 (IsGrayColorspace(image->colorspace) != MagickFalse))
5361 (void) SetImageColorspace(image,sRGBColorspace,exception);
5364 case TransparentVirtualPixelMethod:
5366 if ((image->alpha_trait & BlendPixelTrait) == 0)
5367 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5376#if defined(MAGICKCORE_OPENCL_SUPPORT)
5401static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5403 assert(cache_info != (
CacheInfo *) NULL);
5404 assert(cache_info->signature == MagickCoreSignature);
5405 if ((cache_info->type != MemoryCache) ||
5406 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5411 LockSemaphoreInfo(cache_info->semaphore);
5412 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5413 UnlockSemaphoreInfo(cache_info->semaphore);
5416MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5419 *magick_restrict cache_info;
5421 assert(image != (
const Image *) NULL);
5423 CopyOpenCLBuffer(cache_info);
5456MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5460 *magick_restrict cache_info;
5468 assert(image != (
Image *) NULL);
5469 assert(image->signature == MagickCoreSignature);
5470 if (image->cache == (Cache) NULL)
5471 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5473 assert(cache_info->signature == MagickCoreSignature);
5474 if (cache_info->type == UndefinedCache)
5475 return(MagickFalse);
5476 if (image->mask_trait != UpdatePixelTrait)
5478 if (((image->channels & WriteMaskChannel) != 0) &&
5479 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5480 return(MagickFalse);
5481 if (((image->channels & CompositeMaskChannel) != 0) &&
5482 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5483 return(MagickFalse);
5485 if (nexus_info->authentic_pixel_cache != MagickFalse)
5487 if (image->taint == MagickFalse)
5488 image->taint=MagickTrue;
5491 assert(cache_info->signature == MagickCoreSignature);
5492 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5493 if ((cache_info->metacontent_extent != 0) &&
5494 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5495 return(MagickFalse);
5496 if ((status != MagickFalse) && (image->taint == MagickFalse))
5497 image->taint=MagickTrue;
5528static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5532 *magick_restrict cache_info;
5535 id = GetOpenMPThreadId();
5540 assert(image != (
Image *) NULL);
5541 assert(image->signature == MagickCoreSignature);
5542 assert(image->cache != (Cache) NULL);
5544 assert(cache_info->signature == MagickCoreSignature);
5545 assert(
id < (
int) cache_info->number_threads);
5546 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5578MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5582 *magick_restrict cache_info;
5585 id = GetOpenMPThreadId();
5590 assert(image != (
Image *) NULL);
5591 assert(image->signature == MagickCoreSignature);
5592 assert(image->cache != (Cache) NULL);
5594 assert(cache_info->signature == MagickCoreSignature);
5595 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5597 status=cache_info->methods.sync_authentic_pixels_handler(image,
5601 assert(
id < (
int) cache_info->number_threads);
5602 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5634MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5638 *magick_restrict cache_info;
5640 assert(image != (
Image *) NULL);
5642 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5643 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5674static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5694 if (cache_info->metacontent_extent == 0)
5695 return(MagickFalse);
5696 if (nexus_info->authentic_pixel_cache != MagickFalse)
5698 if (nexus_info->metacontent == (
unsigned char *) NULL)
5699 return(MagickFalse);
5700 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5701 return(MagickFalse);
5702 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5703 nexus_info->region.x;
5704 length=(MagickSizeType) nexus_info->region.width*
5705 cache_info->metacontent_extent;
5706 extent=(MagickSizeType) length*nexus_info->region.height;
5707 rows=nexus_info->region.height;
5709 p=(
unsigned char *) nexus_info->metacontent;
5710 switch (cache_info->type)
5721 if ((cache_info->columns == nexus_info->region.width) &&
5722 (extent == (MagickSizeType) ((
size_t) extent)))
5727 q=(
unsigned char *) cache_info->metacontent+offset*
5728 (MagickOffsetType) cache_info->metacontent_extent;
5729 for (y=0; y < (ssize_t) rows; y++)
5731 (void) memcpy(q,p,(
size_t) length);
5732 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5733 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5742 LockSemaphoreInfo(cache_info->file_semaphore);
5743 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5745 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5746 cache_info->cache_filename);
5747 UnlockSemaphoreInfo(cache_info->file_semaphore);
5748 return(MagickFalse);
5750 if ((cache_info->columns == nexus_info->region.width) &&
5751 (extent <= MagickMaxBufferExtent))
5756 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5757 for (y=0; y < (ssize_t) rows; y++)
5759 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5760 (MagickOffsetType) extent*(MagickOffsetType)
5761 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5762 (MagickOffsetType) cache_info->metacontent_extent,length,
5763 (
const unsigned char *) p);
5764 if (count != (MagickOffsetType) length)
5766 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5767 offset+=(MagickOffsetType) cache_info->columns;
5769 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5770 (void) ClosePixelCacheOnDisk(cache_info);
5771 UnlockSemaphoreInfo(cache_info->file_semaphore);
5774 case DistributedCache:
5782 LockSemaphoreInfo(cache_info->file_semaphore);
5783 region=nexus_info->region;
5784 if ((cache_info->columns != nexus_info->region.width) ||
5785 (extent > MagickMaxBufferExtent))
5792 for (y=0; y < (ssize_t) rows; y++)
5795 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5796 if (count != (MagickOffsetType) length)
5798 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5801 UnlockSemaphoreInfo(cache_info->file_semaphore);
5807 if (y < (ssize_t) rows)
5809 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5810 cache_info->cache_filename);
5811 return(MagickFalse);
5813 if ((cache_info->debug != MagickFalse) &&
5814 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5815 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5816 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5817 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5818 nexus_info->region.x,(
double) nexus_info->region.y);
5850static MagickBooleanType WritePixelCachePixels(
5871 if (nexus_info->authentic_pixel_cache != MagickFalse)
5873 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5874 return(MagickFalse);
5875 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5876 nexus_info->region.x;
5877 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5879 extent=length*nexus_info->region.height;
5880 rows=nexus_info->region.height;
5882 p=nexus_info->pixels;
5883 switch (cache_info->type)
5894 if ((cache_info->columns == nexus_info->region.width) &&
5895 (extent == (MagickSizeType) ((
size_t) extent)))
5900 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5902 for (y=0; y < (ssize_t) rows; y++)
5904 (void) memcpy(q,p,(
size_t) length);
5905 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5906 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5915 LockSemaphoreInfo(cache_info->file_semaphore);
5916 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5918 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5919 cache_info->cache_filename);
5920 UnlockSemaphoreInfo(cache_info->file_semaphore);
5921 return(MagickFalse);
5923 if ((cache_info->columns == nexus_info->region.width) &&
5924 (extent <= MagickMaxBufferExtent))
5929 for (y=0; y < (ssize_t) rows; y++)
5931 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5932 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5933 sizeof(*p),length,(
const unsigned char *) p);
5934 if (count != (MagickOffsetType) length)
5936 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5937 offset+=(MagickOffsetType) cache_info->columns;
5939 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5940 (void) ClosePixelCacheOnDisk(cache_info);
5941 UnlockSemaphoreInfo(cache_info->file_semaphore);
5944 case DistributedCache:
5952 LockSemaphoreInfo(cache_info->file_semaphore);
5953 region=nexus_info->region;
5954 if ((cache_info->columns != nexus_info->region.width) ||
5955 (extent > MagickMaxBufferExtent))
5962 for (y=0; y < (ssize_t) rows; y++)
5965 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5966 if (count != (MagickOffsetType) length)
5968 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5971 UnlockSemaphoreInfo(cache_info->file_semaphore);
5977 if (y < (ssize_t) rows)
5979 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5980 cache_info->cache_filename);
5981 return(MagickFalse);
5983 if ((cache_info->debug != MagickFalse) &&
5984 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5985 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5986 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5987 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5988 nexus_info->region.x,(
double) nexus_info->region.y);