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))
435 if (cache_info == (Cache) NULL)
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 MagickBooleanType ClonePixelCacheRepository(
659#define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
660#define cache_number_threads(source,destination,chunk,multithreaded) \
661 num_threads((multithreaded) == 0 ? 1 : \
662 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
663 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
664 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
665 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
672 **magick_restrict cache_nexus,
673 **magick_restrict clone_nexus;
681 assert(cache_info != (
CacheInfo *) NULL);
682 assert(clone_info != (
CacheInfo *) NULL);
684 if (cache_info->type == PingCache)
686 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
687 if ((cache_info->storage_class == clone_info->storage_class) &&
688 (cache_info->colorspace == clone_info->colorspace) &&
689 (cache_info->alpha_trait == clone_info->alpha_trait) &&
690 (cache_info->channels == clone_info->channels) &&
691 (cache_info->columns == clone_info->columns) &&
692 (cache_info->rows == clone_info->rows) &&
693 (cache_info->number_channels == clone_info->number_channels) &&
694 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
695 (cache_info->metacontent_extent == clone_info->metacontent_extent))
700 if (((cache_info->type == MemoryCache) ||
701 (cache_info->type == MapCache)) &&
702 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
704 (void) memcpy(clone_info->pixels,cache_info->pixels,
705 cache_info->number_channels*cache_info->columns*cache_info->rows*
706 sizeof(*cache_info->pixels));
707 if ((cache_info->metacontent_extent != 0) &&
708 (clone_info->metacontent_extent != 0))
709 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
710 cache_info->columns*cache_info->rows*
711 clone_info->metacontent_extent*
sizeof(
unsigned char));
714 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
715 return(ClonePixelCacheOnDisk(cache_info,clone_info));
720 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
721 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
722 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
723 optimize=(cache_info->number_channels == clone_info->number_channels) &&
724 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
725 MagickTrue : MagickFalse;
726 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
727 clone_info->number_channels*clone_info->columns);
729#if defined(MAGICKCORE_OPENMP_SUPPORT)
730 #pragma omp parallel for schedule(static) shared(status) \
731 cache_number_threads(cache_info,clone_info,(int) cache_info->rows,4)
733 for (y=0; y < (ssize_t) cache_info->rows; y++)
736 id = GetOpenMPThreadId();
744 if (status == MagickFalse)
746 if (y >= (ssize_t) clone_info->rows)
748 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
749 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
750 if (pixels == (Quantum *) NULL)
752 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
753 if (status == MagickFalse)
755 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
756 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
757 if (pixels == (Quantum *) NULL)
759 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
760 if (optimize != MagickFalse)
761 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
774 p=cache_nexus[id]->pixels;
775 q=clone_nexus[id]->pixels;
776 for (x=0; x < (ssize_t) cache_info->columns; x++)
781 if (x == (ssize_t) clone_info->columns)
783 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
791 channel=clone_info->channel_map[i].channel;
792 traits=cache_info->channel_map[channel].traits;
793 if (traits != UndefinedPixelTrait)
794 *q=*(p+cache_info->channel_map[channel].offset);
797 p+=(ptrdiff_t) cache_info->number_channels;
800 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
802 if ((cache_info->metacontent_extent != 0) &&
803 (clone_info->metacontent_extent != 0))
808 length=(size_t) MagickMin(cache_info->metacontent_extent,
809 clone_info->metacontent_extent);
810#if defined(MAGICKCORE_OPENMP_SUPPORT)
811 #pragma omp parallel for schedule(static) shared(status) \
812 cache_number_threads(cache_info,clone_info,(int) cache_info->rows,4)
814 for (y=0; y < (ssize_t) cache_info->rows; y++)
817 id = GetOpenMPThreadId();
822 if (status == MagickFalse)
824 if (y >= (ssize_t) clone_info->rows)
826 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
827 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
828 if (pixels == (Quantum *) NULL)
830 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
831 if (status == MagickFalse)
833 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
834 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
835 if (pixels == (Quantum *) NULL)
837 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
838 (cache_nexus[
id]->metacontent != (
void *) NULL))
839 (void) memcpy(clone_nexus[
id]->metacontent,
840 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
841 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
844 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
845 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
846 if (cache_info->debug != MagickFalse)
849 message[MagickPathExtent];
851 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
852 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
853 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
854 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
881static void DestroyImagePixelCache(
Image *image)
883 assert(image != (
Image *) NULL);
884 assert(image->signature == MagickCoreSignature);
885 if (IsEventLogging() != MagickFalse)
886 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
887 if (image->cache != (
void *) NULL)
888 image->cache=DestroyPixelCache(image->cache);
913MagickExport
void DestroyImagePixels(
Image *image)
916 *magick_restrict cache_info;
918 assert(image != (
const Image *) NULL);
919 assert(image->signature == MagickCoreSignature);
920 if (IsEventLogging() != MagickFalse)
921 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
922 assert(image->cache != (Cache) NULL);
924 assert(cache_info->signature == MagickCoreSignature);
925 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
927 cache_info->methods.destroy_pixel_handler(image);
930 image->cache=DestroyPixelCache(image->cache);
956static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
962 if (cache_info->file != -1)
964 status=close(cache_info->file);
965 cache_info->file=(-1);
966 RelinquishMagickResource(FileResource,1);
968 return(status == -1 ? MagickFalse : MagickTrue);
971static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
973 switch (cache_info->type)
977 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
978#if defined(MAGICKCORE_OPENCL_SUPPORT)
979 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
981 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
983 cache_info->pixels=(Quantum *) NULL;
987 if (cache_info->mapped == MagickFalse)
988 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
992 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
993 cache_info->pixels=(Quantum *) NULL;
995 RelinquishMagickResource(MemoryResource,cache_info->length);
1000 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1001 cache_info->pixels=(Quantum *) NULL;
1002 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1003 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1004 *cache_info->cache_filename=
'\0';
1005 RelinquishMagickResource(MapResource,cache_info->length);
1010 if (cache_info->file != -1)
1011 (void) ClosePixelCacheOnDisk(cache_info);
1012 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1013 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1014 *cache_info->cache_filename=
'\0';
1015 RelinquishMagickResource(DiskResource,cache_info->length);
1018 case DistributedCache:
1020 *cache_info->cache_filename=
'\0';
1022 cache_info->server_info);
1028 cache_info->type=UndefinedCache;
1029 cache_info->mapped=MagickFalse;
1030 cache_info->metacontent=(
void *) NULL;
1033MagickPrivate Cache DestroyPixelCache(Cache cache)
1036 *magick_restrict cache_info;
1038 assert(cache != (Cache) NULL);
1040 assert(cache_info->signature == MagickCoreSignature);
1041 if (IsEventLogging() != MagickFalse)
1042 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1043 cache_info->filename);
1044 LockSemaphoreInfo(cache_info->semaphore);
1045 cache_info->reference_count--;
1046 if (cache_info->reference_count != 0)
1048 UnlockSemaphoreInfo(cache_info->semaphore);
1049 return((Cache) NULL);
1051 UnlockSemaphoreInfo(cache_info->semaphore);
1052 if (cache_info->debug != MagickFalse)
1055 message[MagickPathExtent];
1057 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1058 cache_info->filename);
1059 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1061 RelinquishPixelCachePixels(cache_info);
1064 cache_info->server_info);
1065 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1066 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1067 cache_info->number_threads);
1068 if (cache_info->random_info != (
RandomInfo *) NULL)
1069 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1071 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1073 RelinquishSemaphoreInfo(&cache_info->semaphore);
1074 cache_info->signature=(~MagickCoreSignature);
1075 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1106static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1108 if (nexus_info->mapped == MagickFalse)
1109 (void) RelinquishAlignedMemory(nexus_info->cache);
1111 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1112 nexus_info->cache=(Quantum *) NULL;
1113 nexus_info->pixels=(Quantum *) NULL;
1114 nexus_info->metacontent=(
void *) NULL;
1115 nexus_info->length=0;
1116 nexus_info->mapped=MagickFalse;
1120 const size_t number_threads)
1125 assert(nexus_info != (
NexusInfo **) NULL);
1126 for (i=0; i < (ssize_t) (2*number_threads); i++)
1128 if (nexus_info[i]->cache != (Quantum *) NULL)
1129 RelinquishCacheNexusPixels(nexus_info[i]);
1130 nexus_info[i]->signature=(~MagickCoreSignature);
1132 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1133 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1162MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1165 *magick_restrict cache_info;
1168 id = GetOpenMPThreadId();
1170 assert(image != (
const Image *) NULL);
1171 assert(image->signature == MagickCoreSignature);
1172 assert(image->cache != (Cache) NULL);
1174 assert(cache_info->signature == MagickCoreSignature);
1175 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1176 (GetAuthenticMetacontentFromHandler) NULL)
1181 metacontent=cache_info->methods.
1182 get_authentic_metacontent_from_handler(image);
1183 return(metacontent);
1185 assert(
id < (
int) cache_info->number_threads);
1186 return(cache_info->nexus_info[
id]->metacontent);
1213static void *GetAuthenticMetacontentFromCache(
const Image *image)
1216 *magick_restrict cache_info;
1219 id = GetOpenMPThreadId();
1221 assert(image != (
const Image *) NULL);
1222 assert(image->signature == MagickCoreSignature);
1223 assert(image->cache != (Cache) NULL);
1225 assert(cache_info->signature == MagickCoreSignature);
1226 assert(
id < (
int) cache_info->number_threads);
1227 return(cache_info->nexus_info[
id]->metacontent);
1230#if defined(MAGICKCORE_OPENCL_SUPPORT)
1259MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1263 *magick_restrict cache_info;
1265 assert(image != (
const Image *) NULL);
1266 assert(device != (
const MagickCLDevice) NULL);
1268 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1270 SyncImagePixelCache((
Image *) image,exception);
1273 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1274 return((cl_mem) NULL);
1275 LockSemaphoreInfo(cache_info->semaphore);
1276 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1277 (cache_info->opencl->device->context != device->context))
1278 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1279 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1281 assert(cache_info->pixels != (Quantum *) NULL);
1282 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1283 cache_info->length);
1285 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1286 RetainOpenCLMemObject(cache_info->opencl->buffer);
1287 UnlockSemaphoreInfo(cache_info->semaphore);
1288 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1289 return((cl_mem) NULL);
1290 assert(cache_info->opencl->pixels == cache_info->pixels);
1291 return(cache_info->opencl->buffer);
1330MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1331 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1335 *magick_restrict cache_info;
1338 *magick_restrict pixels;
1343 assert(image != (
Image *) NULL);
1344 assert(image->signature == MagickCoreSignature);
1345 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1346 nexus_info,exception);
1347 if (pixels == (Quantum *) NULL)
1348 return((Quantum *) NULL);
1350 assert(cache_info->signature == MagickCoreSignature);
1351 if (nexus_info->authentic_pixel_cache != MagickFalse)
1353 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1354 return((Quantum *) NULL);
1355 if (cache_info->metacontent_extent != 0)
1356 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1357 return((Quantum *) NULL);
1384static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1387 *magick_restrict cache_info;
1390 id = GetOpenMPThreadId();
1392 assert(image != (
const Image *) NULL);
1393 assert(image->signature == MagickCoreSignature);
1394 assert(image->cache != (Cache) NULL);
1396 assert(cache_info->signature == MagickCoreSignature);
1397 assert(
id < (
int) cache_info->number_threads);
1398 return(cache_info->nexus_info[
id]->pixels);
1425MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1428 *magick_restrict cache_info;
1431 id = GetOpenMPThreadId();
1433 assert(image != (
const Image *) NULL);
1434 assert(image->signature == MagickCoreSignature);
1435 assert(image->cache != (Cache) NULL);
1437 assert(cache_info->signature == MagickCoreSignature);
1438 if (cache_info->methods.get_authentic_pixels_from_handler !=
1439 (GetAuthenticPixelsFromHandler) NULL)
1440 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1441 assert(
id < (
int) cache_info->number_threads);
1442 return(cache_info->nexus_info[
id]->pixels);
1490MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1491 const ssize_t y,
const size_t columns,
const size_t rows,
1495 *magick_restrict cache_info;
1498 id = GetOpenMPThreadId();
1503 assert(image != (
Image *) NULL);
1504 assert(image->signature == MagickCoreSignature);
1505 assert(image->cache != (Cache) NULL);
1507 assert(cache_info->signature == MagickCoreSignature);
1508 if (cache_info->methods.get_authentic_pixels_handler !=
1509 (GetAuthenticPixelsHandler) NULL)
1511 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1515 assert(
id < (
int) cache_info->number_threads);
1516 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1517 cache_info->nexus_info[
id],exception);
1552static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1553 const ssize_t y,
const size_t columns,
const size_t rows,
1557 *magick_restrict cache_info;
1560 id = GetOpenMPThreadId();
1563 *magick_restrict pixels;
1565 assert(image != (
const Image *) NULL);
1566 assert(image->signature == MagickCoreSignature);
1567 assert(image->cache != (Cache) NULL);
1569 if (cache_info == (Cache) NULL)
1570 return((Quantum *) NULL);
1571 assert(cache_info->signature == MagickCoreSignature);
1572 assert(
id < (
int) cache_info->number_threads);
1573 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1574 cache_info->nexus_info[
id],exception);
1601MagickExport MagickSizeType GetImageExtent(
const Image *image)
1604 *magick_restrict cache_info;
1607 id = GetOpenMPThreadId();
1609 assert(image != (
Image *) NULL);
1610 assert(image->signature == MagickCoreSignature);
1611 if (IsEventLogging() != MagickFalse)
1612 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1613 assert(image->cache != (Cache) NULL);
1615 assert(cache_info->signature == MagickCoreSignature);
1616 assert(
id < (
int) cache_info->number_threads);
1617 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1650static inline MagickBooleanType ValidatePixelCacheMorphology(
1651 const Image *magick_restrict image)
1654 *magick_restrict cache_info;
1664 p=image->channel_map;
1665 q=cache_info->channel_map;
1666 if ((image->storage_class != cache_info->storage_class) ||
1667 (image->colorspace != cache_info->colorspace) ||
1668 (image->alpha_trait != cache_info->alpha_trait) ||
1669 (image->channels != cache_info->channels) ||
1670 (image->columns != cache_info->columns) ||
1671 (image->rows != cache_info->rows) ||
1672 (image->number_channels != cache_info->number_channels) ||
1673 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1674 (image->metacontent_extent != cache_info->metacontent_extent) ||
1675 (cache_info->nexus_info == (
NexusInfo **) NULL))
1676 return(MagickFalse);
1680static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1684 *magick_restrict cache_info;
1688 status = MagickTrue;
1690 static MagickSizeType
1691 cpu_throttle = MagickResourceInfinity,
1694 if (IsImageTTLExpired(image) != MagickFalse)
1699 (void) ThrowMagickException(exception,GetMagickModule(),
1700 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1701 return((Cache) NULL);
1703 if (cpu_throttle == MagickResourceInfinity)
1704 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1705 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1706 MagickDelay(cpu_throttle);
1707 LockSemaphoreInfo(image->semaphore);
1708 assert(image->cache != (Cache) NULL);
1710#if defined(MAGICKCORE_OPENCL_SUPPORT)
1711 CopyOpenCLBuffer(cache_info);
1713 destroy=MagickFalse;
1714 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1716 LockSemaphoreInfo(cache_info->semaphore);
1717 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1728 clone_image=(*image);
1729 clone_image.semaphore=AcquireSemaphoreInfo();
1730 clone_image.reference_count=1;
1731 clone_image.cache=ClonePixelCache(cache_info);
1732 clone_info=(
CacheInfo *) clone_image.cache;
1733 status=OpenPixelCache(&clone_image,IOMode,exception);
1734 if (status == MagickFalse)
1735 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1738 if (clone != MagickFalse)
1739 status=ClonePixelCacheRepository(clone_info,cache_info,
1741 if (status == MagickFalse)
1742 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1746 image->cache=clone_info;
1749 RelinquishSemaphoreInfo(&clone_image.semaphore);
1751 UnlockSemaphoreInfo(cache_info->semaphore);
1753 if (destroy != MagickFalse)
1754 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1755 if (status != MagickFalse)
1760 if (image->type != UndefinedType)
1761 image->type=UndefinedType;
1762 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1764 status=OpenPixelCache(image,IOMode,exception);
1766 if (cache_info->file != -1)
1767 (void) ClosePixelCacheOnDisk(cache_info);
1770 UnlockSemaphoreInfo(image->semaphore);
1771 if (status == MagickFalse)
1772 return((Cache) NULL);
1773 return(image->cache);
1799MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1802 *magick_restrict cache_info;
1804 assert(image != (
Image *) NULL);
1805 assert(image->signature == MagickCoreSignature);
1806 assert(image->cache != (Cache) NULL);
1808 assert(cache_info->signature == MagickCoreSignature);
1809 return(cache_info->type);
1843static inline MagickBooleanType CopyPixel(
const Image *image,
1844 const Quantum *source,Quantum *destination)
1849 if (source == (
const Quantum *) NULL)
1851 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1852 destination[GreenPixelChannel]=ClampToQuantum(
1853 image->background_color.green);
1854 destination[BluePixelChannel]=ClampToQuantum(
1855 image->background_color.blue);
1856 destination[BlackPixelChannel]=ClampToQuantum(
1857 image->background_color.black);
1858 destination[AlphaPixelChannel]=ClampToQuantum(
1859 image->background_color.alpha);
1860 return(MagickFalse);
1862 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1864 PixelChannel channel = GetPixelChannelChannel(image,i);
1865 destination[channel]=source[i];
1870MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1871 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1874 *magick_restrict cache_info;
1879 assert(image != (
Image *) NULL);
1880 assert(image->signature == MagickCoreSignature);
1881 assert(image->cache != (Cache) NULL);
1883 assert(cache_info->signature == MagickCoreSignature);
1884 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1885 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1886 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1887 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1888 return(CopyPixel(image,q,pixel));
1922static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
1923 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1926 *magick_restrict cache_info;
1929 id = GetOpenMPThreadId();
1934 assert(image != (
const Image *) NULL);
1935 assert(image->signature == MagickCoreSignature);
1936 assert(image->cache != (Cache) NULL);
1938 assert(cache_info->signature == MagickCoreSignature);
1939 assert(
id < (
int) cache_info->number_threads);
1940 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1941 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
1943 return(CopyPixel(image,q,pixel));
1977MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
1978 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1981 *magick_restrict cache_info;
1984 id = GetOpenMPThreadId();
1989 assert(image != (
const Image *) NULL);
1990 assert(image->signature == MagickCoreSignature);
1991 assert(image->cache != (Cache) NULL);
1993 assert(cache_info->signature == MagickCoreSignature);
1994 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1995 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
1996 (GetOneVirtualPixelFromHandler) NULL)
1997 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
1998 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
1999 assert(
id < (
int) cache_info->number_threads);
2000 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2001 1UL,1UL,cache_info->nexus_info[
id],exception);
2002 return(CopyPixel(image,p,pixel));
2039static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2040 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2044 *magick_restrict cache_info;
2047 id = GetOpenMPThreadId();
2052 assert(image != (
const Image *) NULL);
2053 assert(image->signature == MagickCoreSignature);
2054 assert(image->cache != (Cache) NULL);
2056 assert(cache_info->signature == MagickCoreSignature);
2057 assert(
id < (
int) cache_info->number_threads);
2058 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2059 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2060 cache_info->nexus_info[
id],exception);
2061 return(CopyPixel(image,p,pixel));
2098MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2099 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2103 *magick_restrict cache_info;
2106 id = GetOpenMPThreadId();
2111 assert(image != (
const Image *) NULL);
2112 assert(image->signature == MagickCoreSignature);
2113 assert(image->cache != (Cache) NULL);
2115 assert(cache_info->signature == MagickCoreSignature);
2116 assert(
id < (
int) cache_info->number_threads);
2117 GetPixelInfo(image,pixel);
2118 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2119 cache_info->nexus_info[
id],exception);
2120 if (p == (
const Quantum *) NULL)
2121 return(MagickFalse);
2122 GetPixelInfoPixel(image,p,pixel);
2148MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2151 *magick_restrict cache_info;
2153 assert(cache != (Cache) NULL);
2155 assert(cache_info->signature == MagickCoreSignature);
2156 if (IsEventLogging() != MagickFalse)
2157 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2158 cache_info->filename);
2159 return(cache_info->colorspace);
2185MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2188 *magick_restrict cache_info;
2190 assert(image != (
const Image *) NULL);
2191 assert(image->signature == MagickCoreSignature);
2192 assert(image->cache != (Cache) NULL);
2194 assert(cache_info->signature == MagickCoreSignature);
2195 return(cache_info->cache_filename);
2220MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2223 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2224 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2225 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2226 cache_methods->get_virtual_metacontent_from_handler=
2227 GetVirtualMetacontentFromCache;
2228 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2229 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2230 cache_methods->get_authentic_metacontent_from_handler=
2231 GetAuthenticMetacontentFromCache;
2232 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2233 cache_methods->get_one_authentic_pixel_from_handler=
2234 GetOneAuthenticPixelFromCache;
2235 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2236 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2237 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2265MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2269 *magick_restrict cache_info;
2274 assert(cache != NULL);
2276 assert(cache_info->signature == MagickCoreSignature);
2277 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2279 return((MagickSizeType) cache_info->columns*cache_info->rows);
2310MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2314 *magick_restrict cache_info;
2316 assert(image != (
const Image *) NULL);
2317 assert(image->signature == MagickCoreSignature);
2318 assert(image->cache != (Cache) NULL);
2319 assert(length != (MagickSizeType *) NULL);
2320 magick_unreferenced(exception);
2322 assert(cache_info->signature == MagickCoreSignature);
2323 *length=cache_info->length;
2324 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2325 return((
void *) NULL);
2326 return((
void *) cache_info->pixels);
2353MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2356 *magick_restrict cache_info;
2358 assert(cache != (Cache) NULL);
2360 assert(cache_info->signature == MagickCoreSignature);
2361 if (IsEventLogging() != MagickFalse)
2362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2363 cache_info->filename);
2364 return(cache_info->storage_class);
2394MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2398 *magick_restrict cache_info;
2400 assert(image != (
Image *) NULL);
2401 assert(image->signature == MagickCoreSignature);
2402 if (IsEventLogging() != MagickFalse)
2403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2405 assert(cache_info->signature == MagickCoreSignature);
2406 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2407 if (GetImagePixelCacheType(image) == DiskCache)
2408 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2436MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2439 *magick_restrict cache_info;
2441 assert(image != (
Image *) NULL);
2442 assert(image->signature == MagickCoreSignature);
2443 assert(image->cache != (Cache) NULL);
2445 assert(cache_info->signature == MagickCoreSignature);
2446 return(cache_info->virtual_pixel_method);
2472static const void *GetVirtualMetacontentFromCache(
const Image *image)
2475 *magick_restrict cache_info;
2478 id = GetOpenMPThreadId();
2481 *magick_restrict metacontent;
2483 assert(image != (
const Image *) NULL);
2484 assert(image->signature == MagickCoreSignature);
2485 assert(image->cache != (Cache) NULL);
2487 assert(cache_info->signature == MagickCoreSignature);
2488 assert(
id < (
int) cache_info->number_threads);
2489 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2490 cache_info->nexus_info[
id]);
2491 return(metacontent);
2520MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2524 *magick_restrict cache_info;
2526 assert(cache != (Cache) NULL);
2528 assert(cache_info->signature == MagickCoreSignature);
2529 if (cache_info->storage_class == UndefinedClass)
2530 return((
void *) NULL);
2531 return(nexus_info->metacontent);
2558MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2561 *magick_restrict cache_info;
2564 id = GetOpenMPThreadId();
2567 *magick_restrict metacontent;
2569 assert(image != (
const Image *) NULL);
2570 assert(image->signature == MagickCoreSignature);
2571 assert(image->cache != (Cache) NULL);
2573 assert(cache_info->signature == MagickCoreSignature);
2574 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2576 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2578 if (metacontent != (
const void *) NULL)
2579 return(metacontent);
2581 assert(
id < (
int) cache_info->number_threads);
2582 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2583 cache_info->nexus_info[
id]);
2584 return(metacontent);
2627 0, 48, 12, 60, 3, 51, 15, 63,
2628 32, 16, 44, 28, 35, 19, 47, 31,
2629 8, 56, 4, 52, 11, 59, 7, 55,
2630 40, 24, 36, 20, 43, 27, 39, 23,
2631 2, 50, 14, 62, 1, 49, 13, 61,
2632 34, 18, 46, 30, 33, 17, 45, 29,
2633 10, 58, 6, 54, 9, 57, 5, 53,
2634 42, 26, 38, 22, 41, 25, 37, 21
2637static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2642 index=x+DitherMatrix[x & 0x07]-32L;
2645 if (index >= (ssize_t) columns)
2646 return((ssize_t) columns-1L);
2650static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2655 index=y+DitherMatrix[y & 0x07]-32L;
2658 if (index >= (ssize_t) rows)
2659 return((ssize_t) rows-1L);
2663static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2667 if (x >= (ssize_t) columns)
2668 return((ssize_t) (columns-1));
2672static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2676 if (y >= (ssize_t) rows)
2677 return((ssize_t) (rows-1));
2681static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2682 const MagickOffsetType y)
2684 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2685 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2686 return(MagickFalse);
2690static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2692 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2695static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2697 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2700static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2701 const size_t extent)
2706 modulo.quotient=offset;
2710 modulo.quotient=offset/((ssize_t) extent);
2711 modulo.remainder=offset % ((ssize_t) extent);
2713 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2716 modulo.remainder+=((ssize_t) extent);
2721MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2722 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2723 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2727 *magick_restrict cache_info;
2743 *magick_restrict virtual_nexus;
2746 *magick_restrict pixels,
2748 virtual_pixel[MaxPixelChannels];
2759 *magick_restrict virtual_metacontent;
2764 assert(image != (
const Image *) NULL);
2765 assert(image->signature == MagickCoreSignature);
2766 assert(image->cache != (Cache) NULL);
2768 assert(cache_info->signature == MagickCoreSignature);
2769 if (cache_info->type == UndefinedCache)
2770 return((
const Quantum *) NULL);
2771#if defined(MAGICKCORE_OPENCL_SUPPORT)
2772 CopyOpenCLBuffer(cache_info);
2774 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2775 ((image->channels & WriteMaskChannel) != 0) ||
2776 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2777 nexus_info,exception);
2778 if (pixels == (Quantum *) NULL)
2779 return((
const Quantum *) NULL);
2780 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2781 return((
const Quantum *) NULL);
2782 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2783 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2784 return((
const Quantum *) NULL);
2785 offset+=nexus_info->region.x;
2786 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2787 nexus_info->region.width-1L;
2788 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2789 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2790 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2791 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2799 if (nexus_info->authentic_pixel_cache != MagickFalse)
2801 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2802 if (status == MagickFalse)
2803 return((
const Quantum *) NULL);
2804 if (cache_info->metacontent_extent != 0)
2806 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2807 if (status == MagickFalse)
2808 return((
const Quantum *) NULL);
2815 virtual_nexus=nexus_info->virtual_nexus;
2817 s=(
unsigned char *) nexus_info->metacontent;
2818 (void) memset(virtual_pixel,0,cache_info->number_channels*
2819 sizeof(*virtual_pixel));
2820 virtual_metacontent=(
void *) NULL;
2821 switch (virtual_pixel_method)
2823 case BackgroundVirtualPixelMethod:
2824 case BlackVirtualPixelMethod:
2825 case GrayVirtualPixelMethod:
2826 case TransparentVirtualPixelMethod:
2827 case MaskVirtualPixelMethod:
2828 case WhiteVirtualPixelMethod:
2829 case EdgeVirtualPixelMethod:
2830 case CheckerTileVirtualPixelMethod:
2831 case HorizontalTileVirtualPixelMethod:
2832 case VerticalTileVirtualPixelMethod:
2834 if (cache_info->metacontent_extent != 0)
2839 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2840 cache_info->metacontent_extent);
2841 if (virtual_metacontent == (
void *) NULL)
2843 (void) ThrowMagickException(exception,GetMagickModule(),
2844 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2845 return((
const Quantum *) NULL);
2847 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2849 switch (virtual_pixel_method)
2851 case BlackVirtualPixelMethod:
2853 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2854 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2855 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2858 case GrayVirtualPixelMethod:
2860 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2861 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2863 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2866 case TransparentVirtualPixelMethod:
2868 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2869 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2870 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2873 case MaskVirtualPixelMethod:
2874 case WhiteVirtualPixelMethod:
2876 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2877 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2878 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2883 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2885 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2887 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2889 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2891 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2901 for (v=0; v < (ssize_t) rows; v++)
2907 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2908 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2909 y_offset=EdgeY(y_offset,cache_info->rows);
2910 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2916 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2917 x_offset,(ssize_t) columns-u);
2918 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2919 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2929 length=(MagickSizeType) 1;
2930 switch (virtual_pixel_method)
2932 case EdgeVirtualPixelMethod:
2935 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2936 EdgeX(x_offset,cache_info->columns),
2937 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2939 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2942 case RandomVirtualPixelMethod:
2944 if (cache_info->random_info == (
RandomInfo *) NULL)
2945 cache_info->random_info=AcquireRandomInfo();
2946 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2947 RandomX(cache_info->random_info,cache_info->columns),
2948 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2949 virtual_nexus,exception);
2950 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2953 case DitherVirtualPixelMethod:
2955 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2956 DitherX(x_offset,cache_info->columns),
2957 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2959 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2962 case TileVirtualPixelMethod:
2964 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2965 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2966 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2967 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2969 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2972 case MirrorVirtualPixelMethod:
2974 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2975 if ((x_modulo.quotient & 0x01) == 1L)
2976 x_modulo.remainder=(ssize_t) cache_info->columns-
2977 x_modulo.remainder-1L;
2978 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2979 if ((y_modulo.quotient & 0x01) == 1L)
2980 y_modulo.remainder=(ssize_t) cache_info->rows-
2981 y_modulo.remainder-1L;
2982 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2983 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2985 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2988 case HorizontalTileEdgeVirtualPixelMethod:
2990 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2991 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2992 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
2993 virtual_nexus,exception);
2994 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2997 case VerticalTileEdgeVirtualPixelMethod:
2999 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3000 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3001 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3002 virtual_nexus,exception);
3003 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3006 case BackgroundVirtualPixelMethod:
3007 case BlackVirtualPixelMethod:
3008 case GrayVirtualPixelMethod:
3009 case TransparentVirtualPixelMethod:
3010 case MaskVirtualPixelMethod:
3011 case WhiteVirtualPixelMethod:
3014 r=virtual_metacontent;
3017 case CheckerTileVirtualPixelMethod:
3019 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3020 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3021 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3024 r=virtual_metacontent;
3027 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3028 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3030 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3033 case HorizontalTileVirtualPixelMethod:
3035 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3038 r=virtual_metacontent;
3041 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3042 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3043 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3044 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3046 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3049 case VerticalTileVirtualPixelMethod:
3051 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3054 r=virtual_metacontent;
3057 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3058 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3059 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3060 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3062 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3066 if (p == (
const Quantum *) NULL)
3068 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3070 q+=(ptrdiff_t) cache_info->number_channels;
3071 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3073 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3074 s+=(ptrdiff_t) cache_info->metacontent_extent;
3081 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3082 (
size_t) length,1UL,virtual_nexus,exception);
3083 if (p == (
const Quantum *) NULL)
3085 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3086 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3088 q+=(ptrdiff_t) cache_info->number_channels*length;
3089 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3091 (void) memcpy(s,r,(
size_t) length);
3092 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3095 if (u < (ssize_t) columns)
3101 if (virtual_metacontent != (
void *) NULL)
3102 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3103 if (v < (ssize_t) rows)
3104 return((
const Quantum *) NULL);
3142static const Quantum *GetVirtualPixelCache(
const Image *image,
3143 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3144 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3147 *magick_restrict cache_info;
3150 id = GetOpenMPThreadId();
3155 assert(image != (
const Image *) NULL);
3156 assert(image->signature == MagickCoreSignature);
3157 assert(image->cache != (Cache) NULL);
3159 assert(cache_info->signature == MagickCoreSignature);
3160 assert(
id < (
int) cache_info->number_threads);
3161 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3162 cache_info->nexus_info[
id],exception);
3189MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3192 *magick_restrict cache_info;
3195 id = GetOpenMPThreadId();
3197 assert(image != (
const Image *) NULL);
3198 assert(image->signature == MagickCoreSignature);
3199 assert(image->cache != (Cache) NULL);
3201 assert(cache_info->signature == MagickCoreSignature);
3202 if (cache_info->methods.get_virtual_pixels_handler !=
3203 (GetVirtualPixelsHandler) NULL)
3204 return(cache_info->methods.get_virtual_pixels_handler(image));
3205 assert(
id < (
int) cache_info->number_threads);
3206 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3257MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3258 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3262 *magick_restrict cache_info;
3265 id = GetOpenMPThreadId();
3270 assert(image != (
const Image *) NULL);
3271 assert(image->signature == MagickCoreSignature);
3272 assert(image->cache != (Cache) NULL);
3274 assert(cache_info->signature == MagickCoreSignature);
3275 if (cache_info->methods.get_virtual_pixel_handler !=
3276 (GetVirtualPixelHandler) NULL)
3277 return(cache_info->methods.get_virtual_pixel_handler(image,
3278 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3279 assert(
id < (
int) cache_info->number_threads);
3280 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3281 columns,rows,cache_info->nexus_info[
id],exception);
3308static const Quantum *GetVirtualPixelsCache(
const Image *image)
3311 *magick_restrict cache_info;
3314 id = GetOpenMPThreadId();
3316 assert(image != (
const Image *) NULL);
3317 assert(image->signature == MagickCoreSignature);
3318 assert(image->cache != (Cache) NULL);
3320 assert(cache_info->signature == MagickCoreSignature);
3321 assert(
id < (
int) cache_info->number_threads);
3322 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3351MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3355 *magick_restrict cache_info;
3357 assert(cache != (Cache) NULL);
3359 assert(cache_info->signature == MagickCoreSignature);
3360 if (cache_info->storage_class == UndefinedClass)
3361 return((Quantum *) NULL);
3362 return((
const Quantum *) nexus_info->pixels);
3395static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3396 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3401 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3403 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3404 gamma=PerceptibleReciprocal(gamma);
3405 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3408static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3412 *magick_restrict cache_info;
3424 if (IsEventLogging() != MagickFalse)
3425 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3426 if ((image->channels & CompositeMaskChannel) == 0)
3428 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3431 if (cache_info == (Cache) NULL)
3432 return(MagickFalse);
3433 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3434 nexus_info->region.width,nexus_info->region.height,
3435 nexus_info->virtual_nexus,exception);
3436 q=nexus_info->pixels;
3437 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3438 return(MagickFalse);
3439 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3444 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3452 alpha=(double) GetPixelCompositeMask(image,p);
3453 for (i=0; i < (ssize_t) image->number_channels; i++)
3455 PixelChannel channel = GetPixelChannelChannel(image,i);
3456 PixelTrait traits = GetPixelChannelTraits(image,channel);
3457 if ((traits & UpdatePixelTrait) == 0)
3459 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3461 p+=(ptrdiff_t) GetPixelChannels(image);
3462 q+=(ptrdiff_t) GetPixelChannels(image);
3499static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3508 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3510 if (*cache_info->cache_filename ==
'\0')
3511 file=AcquireUniqueFileResource(cache_info->cache_filename);
3517 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3522 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3523 O_BINARY | O_EXCL,S_MODE);
3525 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3531 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3534 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3539 return(MagickFalse);
3540 (void) AcquireMagickResource(FileResource,1);
3541 if (cache_info->file != -1)
3542 (void) ClosePixelCacheOnDisk(cache_info);
3543 cache_info->file=file;
3544 cache_info->disk_mode=mode;
3548static inline MagickOffsetType WritePixelCacheRegion(
3549 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3550 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3558#if !defined(MAGICKCORE_HAVE_PWRITE)
3559 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3560 return((MagickOffsetType) -1);
3562 for (i=0; i < (MagickOffsetType) length; i+=count)
3564#if !defined(MAGICKCORE_HAVE_PWRITE)
3565 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3566 (MagickSizeType) i,MagickMaxBufferExtent));
3568 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3569 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3581static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3584 *magick_restrict cache_info;
3590 if (cache_info->debug != MagickFalse)
3593 format[MagickPathExtent],
3594 message[MagickPathExtent];
3596 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3597 (void) FormatLocaleString(message,MagickPathExtent,
3598 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3599 cache_info->cache_filename,cache_info->file,format);
3600 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3602 if (length != (MagickSizeType) ((MagickOffsetType) length))
3603 return(MagickFalse);
3604 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3606 return(MagickFalse);
3607 if ((MagickSizeType) offset < length)
3613 extent=(MagickOffsetType) length-1;
3614 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3617 return(MagickFalse);
3618#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3619 if (cache_info->synchronize != MagickFalse)
3620 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3621 return(MagickFalse);
3624 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3626 return(MagickFalse);
3630static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3634 *magick_restrict cache_info,
3638 format[MagickPathExtent],
3639 message[MagickPathExtent];
3656 assert(image != (
const Image *) NULL);
3657 assert(image->signature == MagickCoreSignature);
3658 assert(image->cache != (Cache) NULL);
3659 if (IsEventLogging() != MagickFalse)
3660 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3661 if (cache_anonymous_memory < 0)
3669 cache_anonymous_memory=0;
3670 value=GetPolicyValue(
"pixel-cache-memory");
3671 if (value == (
char *) NULL)
3672 value=GetPolicyValue(
"cache:memory-map");
3673 if (LocaleCompare(value,
"anonymous") == 0)
3675#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3676 cache_anonymous_memory=1;
3678 (void) ThrowMagickException(exception,GetMagickModule(),
3679 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3680 "`%s' (policy requires anonymous memory mapping)",image->filename);
3683 value=DestroyString(value);
3685 if ((image->columns == 0) || (image->rows == 0))
3686 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3688 assert(cache_info->signature == MagickCoreSignature);
3689 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3690 ((MagickSizeType) image->rows > cache_info->height_limit))
3692 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3693 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3694 image->filename, (
double) image->columns, (
double) image->rows,
3695 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3696 return(MagickFalse);
3698 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3700 length=GetImageListLength(image);
3701 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3702 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3705 source_info=(*cache_info);
3706 source_info.file=(-1);
3707 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3708 image->filename,(
double) image->scene);
3709 cache_info->storage_class=image->storage_class;
3710 cache_info->colorspace=image->colorspace;
3711 cache_info->alpha_trait=image->alpha_trait;
3712 cache_info->channels=image->channels;
3713 cache_info->rows=image->rows;
3714 cache_info->columns=image->columns;
3715 status=ResetPixelChannelMap(image,exception);
3716 if (status == MagickFalse)
3717 return(MagickFalse);
3718 cache_info->number_channels=GetPixelChannels(image);
3719 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3720 sizeof(*image->channel_map));
3721 cache_info->metacontent_extent=image->metacontent_extent;
3722 cache_info->mode=mode;
3723 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3724 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3725 if (image->metacontent_extent != 0)
3726 packet_size+=cache_info->metacontent_extent;
3727 length=number_pixels*packet_size;
3728 columns=(size_t) (length/cache_info->rows/packet_size);
3729 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3730 ((ssize_t) cache_info->rows < 0))
3731 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3733 cache_info->length=length;
3734 if (image->ping != MagickFalse)
3736 cache_info->type=PingCache;
3739 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3740 cache_info->columns*cache_info->rows);
3741 if (cache_info->mode == PersistMode)
3743 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3744 cache_info->metacontent_extent);
3745 if ((status != MagickFalse) &&
3746 (length == (MagickSizeType) ((
size_t) length)) &&
3747 ((cache_info->type == UndefinedCache) ||
3748 (cache_info->type == MemoryCache)))
3750 status=AcquireMagickResource(MemoryResource,cache_info->length);
3751 if (status != MagickFalse)
3754 if (cache_anonymous_memory <= 0)
3756 cache_info->mapped=MagickFalse;
3757 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3758 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3762 cache_info->mapped=MagickTrue;
3763 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3764 cache_info->length);
3766 if (cache_info->pixels == (Quantum *) NULL)
3768 cache_info->mapped=source_info.mapped;
3769 cache_info->pixels=source_info.pixels;
3776 cache_info->type=MemoryCache;
3777 cache_info->metacontent=(
void *) NULL;
3778 if (cache_info->metacontent_extent != 0)
3779 cache_info->metacontent=(
void *) (cache_info->pixels+
3780 cache_info->number_channels*number_pixels);
3781 if ((source_info.storage_class != UndefinedClass) &&
3784 status=ClonePixelCacheRepository(cache_info,&source_info,
3786 RelinquishPixelCachePixels(&source_info);
3788 if (cache_info->debug != MagickFalse)
3790 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3791 MagickPathExtent,format);
3792 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3794 (void) FormatLocaleString(message,MagickPathExtent,
3795 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3796 cache_info->filename,cache_info->mapped != MagickFalse ?
3797 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3798 (
double) cache_info->rows,(
double)
3799 cache_info->number_channels,format);
3800 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3803 cache_info->storage_class=image->storage_class;
3806 if ((source_info.storage_class != UndefinedClass) &&
3808 RelinquishPixelCachePixels(&source_info);
3809 cache_info->type=UndefinedCache;
3810 return(MagickFalse);
3816 status=AcquireMagickResource(DiskResource,cache_info->length);
3817 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3819 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3827 server_info=AcquireDistributeCacheInfo(exception);
3830 status=OpenDistributePixelCache(server_info,image);
3831 if (status == MagickFalse)
3833 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3834 GetDistributeCacheHostname(server_info));
3835 server_info=DestroyDistributeCacheInfo(server_info);
3843 cache_info->type=DistributedCache;
3844 cache_info->server_info=server_info;
3845 (void) FormatLocaleString(cache_info->cache_filename,
3846 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3849 cache_info->server_info));
3850 if ((source_info.storage_class != UndefinedClass) &&
3853 status=ClonePixelCacheRepository(cache_info,&source_info,
3855 RelinquishPixelCachePixels(&source_info);
3857 if (cache_info->debug != MagickFalse)
3859 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3860 MagickPathExtent,format);
3861 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3863 (void) FormatLocaleString(message,MagickPathExtent,
3864 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3865 cache_info->filename,cache_info->cache_filename,
3867 cache_info->server_info),type,(
double) cache_info->columns,
3868 (
double) cache_info->rows,(
double)
3869 cache_info->number_channels,format);
3870 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3875 if ((source_info.storage_class != UndefinedClass) &&
3877 RelinquishPixelCachePixels(&source_info);
3878 cache_info->type=UndefinedCache;
3879 return(MagickFalse);
3884 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3885 RelinquishPixelCachePixels(&source_info);
3886 cache_info->type=UndefinedCache;
3887 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3888 "CacheResourcesExhausted",
"`%s'",image->filename);
3889 return(MagickFalse);
3894 if (status == MagickFalse)
3896 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3897 RelinquishPixelCachePixels(&source_info);
3898 cache_info->type=UndefinedCache;
3899 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3900 "CacheResourcesExhausted",
"`%s'",image->filename);
3901 return(MagickFalse);
3903 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3904 (cache_info->mode != PersistMode))
3906 (void) ClosePixelCacheOnDisk(cache_info);
3907 *cache_info->cache_filename=
'\0';
3909 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3911 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3912 RelinquishPixelCachePixels(&source_info);
3913 cache_info->type=UndefinedCache;
3914 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3916 return(MagickFalse);
3918 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3919 cache_info->length);
3920 if (status == MagickFalse)
3922 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3923 RelinquishPixelCachePixels(&source_info);
3924 cache_info->type=UndefinedCache;
3925 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3927 return(MagickFalse);
3929 cache_info->type=DiskCache;
3930 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3931 cache_info->metacontent_extent);
3932 if (length == (MagickSizeType) ((
size_t) length))
3934 status=AcquireMagickResource(MapResource,cache_info->length);
3935 if (status != MagickFalse)
3937 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3938 cache_info->offset,(
size_t) cache_info->length);
3939 if (cache_info->pixels == (Quantum *) NULL)
3941 cache_info->mapped=source_info.mapped;
3942 cache_info->pixels=source_info.pixels;
3943 RelinquishMagickResource(MapResource,cache_info->length);
3950 (void) ClosePixelCacheOnDisk(cache_info);
3951 cache_info->type=MapCache;
3952 cache_info->mapped=MagickTrue;
3953 cache_info->metacontent=(
void *) NULL;
3954 if (cache_info->metacontent_extent != 0)
3955 cache_info->metacontent=(
void *) (cache_info->pixels+
3956 cache_info->number_channels*number_pixels);
3957 if ((source_info.storage_class != UndefinedClass) &&
3960 status=ClonePixelCacheRepository(cache_info,&source_info,
3962 RelinquishPixelCachePixels(&source_info);
3964 if (cache_info->debug != MagickFalse)
3966 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3967 MagickPathExtent,format);
3968 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3970 (void) FormatLocaleString(message,MagickPathExtent,
3971 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3972 cache_info->filename,cache_info->cache_filename,
3973 cache_info->file,type,(
double) cache_info->columns,
3974 (
double) cache_info->rows,(
double)
3975 cache_info->number_channels,format);
3976 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3981 if ((source_info.storage_class != UndefinedClass) &&
3983 RelinquishPixelCachePixels(&source_info);
3984 cache_info->type=UndefinedCache;
3985 return(MagickFalse);
3992 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3994 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3995 RelinquishPixelCachePixels(&source_info);
3997 if (cache_info->debug != MagickFalse)
3999 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4000 MagickPathExtent,format);
4001 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4003 (void) FormatLocaleString(message,MagickPathExtent,
4004 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4005 cache_info->cache_filename,cache_info->file,type,(
double)
4006 cache_info->columns,(
double) cache_info->rows,(
double)
4007 cache_info->number_channels,format);
4008 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4012 cache_info->type=UndefinedCache;
4013 return(MagickFalse);
4055MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4056 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4060 *magick_restrict cache_info,
4061 *magick_restrict clone_info;
4069 assert(image != (
Image *) NULL);
4070 assert(image->signature == MagickCoreSignature);
4071 if (IsEventLogging() != MagickFalse)
4072 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4073 assert(image->cache != (
void *) NULL);
4074 assert(filename != (
const char *) NULL);
4075 assert(offset != (MagickOffsetType *) NULL);
4076 page_size=GetMagickPageSize();
4078 assert(cache_info->signature == MagickCoreSignature);
4079#if defined(MAGICKCORE_OPENCL_SUPPORT)
4080 CopyOpenCLBuffer(cache_info);
4082 if (attach != MagickFalse)
4087 if (cache_info->debug != MagickFalse)
4088 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4089 "attach persistent cache");
4090 (void) CopyMagickString(cache_info->cache_filename,filename,
4092 cache_info->type=MapCache;
4093 cache_info->offset=(*offset);
4094 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4095 return(MagickFalse);
4096 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4097 ((MagickOffsetType) cache_info->length % page_size));
4103 status=AcquireMagickResource(DiskResource,cache_info->length);
4104 if (status == MagickFalse)
4106 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4107 "CacheResourcesExhausted",
"`%s'",image->filename);
4108 return(MagickFalse);
4110 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4111 clone_info->type=DiskCache;
4112 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4113 clone_info->file=(-1);
4114 clone_info->storage_class=cache_info->storage_class;
4115 clone_info->colorspace=cache_info->colorspace;
4116 clone_info->alpha_trait=cache_info->alpha_trait;
4117 clone_info->channels=cache_info->channels;
4118 clone_info->columns=cache_info->columns;
4119 clone_info->rows=cache_info->rows;
4120 clone_info->number_channels=cache_info->number_channels;
4121 clone_info->metacontent_extent=cache_info->metacontent_extent;
4122 clone_info->mode=PersistMode;
4123 clone_info->length=cache_info->length;
4124 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4125 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4126 clone_info->offset=(*offset);
4127 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4128 if (status != MagickFalse)
4129 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4130 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4131 ((MagickOffsetType) cache_info->length % page_size));
4132 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4174MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4175 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4179 *magick_restrict cache_info;
4188 *magick_restrict pixels;
4193 assert(image != (
const Image *) NULL);
4194 assert(image->signature == MagickCoreSignature);
4195 assert(image->cache != (Cache) NULL);
4196 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4197 if (cache_info == (Cache) NULL)
4198 return((Quantum *) NULL);
4199 assert(cache_info->signature == MagickCoreSignature);
4200 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4201 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4202 (y >= (ssize_t) cache_info->rows))
4204 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4205 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4206 return((Quantum *) NULL);
4208 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4209 return((Quantum *) NULL);
4210 offset=y*(MagickOffsetType) cache_info->columns+x;
4212 return((Quantum *) NULL);
4213 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4214 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4215 (MagickOffsetType) columns-1;
4216 if ((MagickSizeType) offset >= number_pixels)
4217 return((Quantum *) NULL);
4221 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4222 ((image->channels & WriteMaskChannel) != 0) ||
4223 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4224 nexus_info,exception);
4261static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4262 const ssize_t y,
const size_t columns,
const size_t rows,
4266 *magick_restrict cache_info;
4269 id = GetOpenMPThreadId();
4272 *magick_restrict pixels;
4274 assert(image != (
const Image *) NULL);
4275 assert(image->signature == MagickCoreSignature);
4276 assert(image->cache != (Cache) NULL);
4278 assert(cache_info->signature == MagickCoreSignature);
4279 assert(
id < (
int) cache_info->number_threads);
4280 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4281 cache_info->nexus_info[
id],exception);
4341MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4342 const ssize_t y,
const size_t columns,
const size_t rows,
4346 *magick_restrict cache_info;
4349 id = GetOpenMPThreadId();
4352 *magick_restrict pixels;
4354 assert(image != (
Image *) NULL);
4355 assert(image->signature == MagickCoreSignature);
4356 assert(image->cache != (Cache) NULL);
4358 assert(cache_info->signature == MagickCoreSignature);
4359 if (cache_info->methods.queue_authentic_pixels_handler !=
4360 (QueueAuthenticPixelsHandler) NULL)
4362 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4363 columns,rows,exception);
4366 assert(
id < (
int) cache_info->number_threads);
4367 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4368 cache_info->nexus_info[
id],exception);
4401static inline MagickOffsetType ReadPixelCacheRegion(
4402 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4403 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4411#if !defined(MAGICKCORE_HAVE_PREAD)
4412 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4413 return((MagickOffsetType) -1);
4415 for (i=0; i < (MagickOffsetType) length; i+=count)
4417#if !defined(MAGICKCORE_HAVE_PREAD)
4418 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4419 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4421 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4422 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4434static MagickBooleanType ReadPixelCacheMetacontent(
4455 if (cache_info->metacontent_extent == 0)
4456 return(MagickFalse);
4457 if (nexus_info->authentic_pixel_cache != MagickFalse)
4459 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4460 return(MagickFalse);
4461 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4462 nexus_info->region.x;
4463 length=(MagickSizeType) nexus_info->region.width*
4464 cache_info->metacontent_extent;
4465 extent=length*nexus_info->region.height;
4466 rows=nexus_info->region.height;
4468 q=(
unsigned char *) nexus_info->metacontent;
4469 switch (cache_info->type)
4480 if ((cache_info->columns == nexus_info->region.width) &&
4481 (extent == (MagickSizeType) ((
size_t) extent)))
4486 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4487 cache_info->metacontent_extent;
4488 for (y=0; y < (ssize_t) rows; y++)
4490 (void) memcpy(q,p,(
size_t) length);
4491 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4492 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4501 LockSemaphoreInfo(cache_info->file_semaphore);
4502 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4504 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4505 cache_info->cache_filename);
4506 UnlockSemaphoreInfo(cache_info->file_semaphore);
4507 return(MagickFalse);
4509 if ((cache_info->columns == nexus_info->region.width) &&
4510 (extent <= MagickMaxBufferExtent))
4515 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4516 for (y=0; y < (ssize_t) rows; y++)
4518 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4519 (MagickOffsetType) extent*(MagickOffsetType)
4520 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4521 (MagickOffsetType) cache_info->metacontent_extent,length,
4522 (
unsigned char *) q);
4523 if (count != (MagickOffsetType) length)
4525 offset+=(MagickOffsetType) cache_info->columns;
4526 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4528 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4529 (void) ClosePixelCacheOnDisk(cache_info);
4530 UnlockSemaphoreInfo(cache_info->file_semaphore);
4533 case DistributedCache:
4541 LockSemaphoreInfo(cache_info->file_semaphore);
4542 region=nexus_info->region;
4543 if ((cache_info->columns != nexus_info->region.width) ||
4544 (extent > MagickMaxBufferExtent))
4551 for (y=0; y < (ssize_t) rows; y++)
4554 cache_info->server_info,®ion,length,(
unsigned char *) q);
4555 if (count != (MagickOffsetType) length)
4557 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4560 UnlockSemaphoreInfo(cache_info->file_semaphore);
4566 if (y < (ssize_t) rows)
4568 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4569 cache_info->cache_filename);
4570 return(MagickFalse);
4572 if ((cache_info->debug != MagickFalse) &&
4573 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4574 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4575 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4576 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4577 nexus_info->region.x,(
double) nexus_info->region.y);
4609static MagickBooleanType ReadPixelCachePixels(
4631 if (nexus_info->authentic_pixel_cache != MagickFalse)
4633 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4634 return(MagickFalse);
4635 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4636 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4637 return(MagickFalse);
4638 offset+=nexus_info->region.x;
4639 number_channels=cache_info->number_channels;
4640 length=(MagickSizeType) number_channels*nexus_info->region.width*
4642 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4643 return(MagickFalse);
4644 rows=nexus_info->region.height;
4646 if ((extent == 0) || ((extent/length) != rows))
4647 return(MagickFalse);
4649 q=nexus_info->pixels;
4650 switch (cache_info->type)
4661 if ((cache_info->columns == nexus_info->region.width) &&
4662 (extent == (MagickSizeType) ((
size_t) extent)))
4667 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4669 for (y=0; y < (ssize_t) rows; y++)
4671 (void) memcpy(q,p,(
size_t) length);
4672 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4673 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4682 LockSemaphoreInfo(cache_info->file_semaphore);
4683 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4685 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4686 cache_info->cache_filename);
4687 UnlockSemaphoreInfo(cache_info->file_semaphore);
4688 return(MagickFalse);
4690 if ((cache_info->columns == nexus_info->region.width) &&
4691 (extent <= MagickMaxBufferExtent))
4696 for (y=0; y < (ssize_t) rows; y++)
4698 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4699 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4700 sizeof(*q),length,(
unsigned char *) q);
4701 if (count != (MagickOffsetType) length)
4703 offset+=(MagickOffsetType) cache_info->columns;
4704 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4706 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4707 (void) ClosePixelCacheOnDisk(cache_info);
4708 UnlockSemaphoreInfo(cache_info->file_semaphore);
4711 case DistributedCache:
4719 LockSemaphoreInfo(cache_info->file_semaphore);
4720 region=nexus_info->region;
4721 if ((cache_info->columns != nexus_info->region.width) ||
4722 (extent > MagickMaxBufferExtent))
4729 for (y=0; y < (ssize_t) rows; y++)
4732 cache_info->server_info,®ion,length,(
unsigned char *) q);
4733 if (count != (MagickOffsetType) length)
4735 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4738 UnlockSemaphoreInfo(cache_info->file_semaphore);
4744 if (y < (ssize_t) rows)
4746 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4747 cache_info->cache_filename);
4748 return(MagickFalse);
4750 if ((cache_info->debug != MagickFalse) &&
4751 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4752 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4753 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4754 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4755 nexus_info->region.x,(
double) nexus_info->region.y);
4782MagickPrivate Cache ReferencePixelCache(Cache cache)
4785 *magick_restrict cache_info;
4787 assert(cache != (Cache *) NULL);
4789 assert(cache_info->signature == MagickCoreSignature);
4790 LockSemaphoreInfo(cache_info->semaphore);
4791 cache_info->reference_count++;
4792 UnlockSemaphoreInfo(cache_info->semaphore);
4818MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4821 *magick_restrict cache_info;
4823 assert(image != (
const Image *) NULL);
4824 assert(image->signature == MagickCoreSignature);
4825 assert(image->cache != (Cache) NULL);
4827 assert(cache_info->signature == MagickCoreSignature);
4828 cache_info->number_channels=GetPixelChannels(image);
4849MagickPrivate
void ResetCacheAnonymousMemory(
void)
4851 cache_anonymous_memory=0;
4883MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4884 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4892 assert(image != (
Image *) NULL);
4893 assert(image->signature == MagickCoreSignature);
4894 if (IsEventLogging() != MagickFalse)
4895 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4896 assert(image->cache != (
void *) NULL);
4897 extent=(MagickSizeType) columns*rows;
4898 if (extent > ((MagickSizeType) image->columns*image->rows))
4899 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4901 image->columns=columns;
4904 cache_info->columns=columns;
4905 cache_info->rows=rows;
4906 return(SyncImagePixelCache(image,exception));
4933MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4936 *magick_restrict cache_info;
4938 GetOneAuthenticPixelFromHandler
4939 get_one_authentic_pixel_from_handler;
4941 GetOneVirtualPixelFromHandler
4942 get_one_virtual_pixel_from_handler;
4947 assert(cache != (Cache) NULL);
4950 assert(cache_info->signature == MagickCoreSignature);
4951 if (IsEventLogging() != MagickFalse)
4952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4953 cache_info->filename);
4954 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4955 cache_info->methods.get_virtual_pixel_handler=
4956 cache_methods->get_virtual_pixel_handler;
4957 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4958 cache_info->methods.destroy_pixel_handler=
4959 cache_methods->destroy_pixel_handler;
4960 if (cache_methods->get_virtual_metacontent_from_handler !=
4961 (GetVirtualMetacontentFromHandler) NULL)
4962 cache_info->methods.get_virtual_metacontent_from_handler=
4963 cache_methods->get_virtual_metacontent_from_handler;
4964 if (cache_methods->get_authentic_pixels_handler !=
4965 (GetAuthenticPixelsHandler) NULL)
4966 cache_info->methods.get_authentic_pixels_handler=
4967 cache_methods->get_authentic_pixels_handler;
4968 if (cache_methods->queue_authentic_pixels_handler !=
4969 (QueueAuthenticPixelsHandler) NULL)
4970 cache_info->methods.queue_authentic_pixels_handler=
4971 cache_methods->queue_authentic_pixels_handler;
4972 if (cache_methods->sync_authentic_pixels_handler !=
4973 (SyncAuthenticPixelsHandler) NULL)
4974 cache_info->methods.sync_authentic_pixels_handler=
4975 cache_methods->sync_authentic_pixels_handler;
4976 if (cache_methods->get_authentic_pixels_from_handler !=
4977 (GetAuthenticPixelsFromHandler) NULL)
4978 cache_info->methods.get_authentic_pixels_from_handler=
4979 cache_methods->get_authentic_pixels_from_handler;
4980 if (cache_methods->get_authentic_metacontent_from_handler !=
4981 (GetAuthenticMetacontentFromHandler) NULL)
4982 cache_info->methods.get_authentic_metacontent_from_handler=
4983 cache_methods->get_authentic_metacontent_from_handler;
4984 get_one_virtual_pixel_from_handler=
4985 cache_info->methods.get_one_virtual_pixel_from_handler;
4986 if (get_one_virtual_pixel_from_handler !=
4987 (GetOneVirtualPixelFromHandler) NULL)
4988 cache_info->methods.get_one_virtual_pixel_from_handler=
4989 cache_methods->get_one_virtual_pixel_from_handler;
4990 get_one_authentic_pixel_from_handler=
4991 cache_methods->get_one_authentic_pixel_from_handler;
4992 if (get_one_authentic_pixel_from_handler !=
4993 (GetOneAuthenticPixelFromHandler) NULL)
4994 cache_info->methods.get_one_authentic_pixel_from_handler=
4995 cache_methods->get_one_authentic_pixel_from_handler;
5036static inline MagickBooleanType AcquireCacheNexusPixels(
5037 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5040 if (length != (MagickSizeType) ((
size_t) length))
5042 (void) ThrowMagickException(exception,GetMagickModule(),
5043 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5044 cache_info->filename);
5045 return(MagickFalse);
5047 nexus_info->length=0;
5048 nexus_info->mapped=MagickFalse;
5049 if (cache_anonymous_memory <= 0)
5051 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5053 if (nexus_info->cache != (Quantum *) NULL)
5054 (void) memset(nexus_info->cache,0,(
size_t) length);
5058 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5059 if (nexus_info->cache != (Quantum *) NULL)
5060 nexus_info->mapped=MagickTrue;
5062 if (nexus_info->cache == (Quantum *) NULL)
5064 (void) ThrowMagickException(exception,GetMagickModule(),
5065 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5066 cache_info->filename);
5067 return(MagickFalse);
5069 nexus_info->length=length;
5073static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5076 if (nexus_info->length < CACHE_LINE_SIZE)
5078 if (mode == ReadMode)
5080 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5084 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5087static Quantum *SetPixelCacheNexusPixels(
5088 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5089 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5090 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5100 assert(cache_info != (
const CacheInfo *) NULL);
5101 assert(cache_info->signature == MagickCoreSignature);
5102 if (cache_info->type == UndefinedCache)
5103 return((Quantum *) NULL);
5104 assert(nexus_info->signature == MagickCoreSignature);
5105 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5106 if ((width == 0) || (height == 0))
5108 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5109 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5110 return((Quantum *) NULL);
5112 if (((MagickSizeType) width > cache_info->width_limit) ||
5113 ((MagickSizeType) height > cache_info->height_limit))
5115 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5116 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5117 return((Quantum *) NULL);
5119 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5120 (IsValidPixelOffset(y,height) == MagickFalse))
5122 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5123 "InvalidPixel",
"`%s'",cache_info->filename);
5124 return((Quantum *) NULL);
5126 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5127 (buffered == MagickFalse))
5129 if (((x >= 0) && (y >= 0) &&
5130 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5131 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5132 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5140 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5141 return((Quantum *) NULL);
5142 offset=y*(MagickOffsetType) cache_info->columns+x;
5143 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5144 cache_info->number_channels*offset;
5145 nexus_info->metacontent=(
void *) NULL;
5146 if (cache_info->metacontent_extent != 0)
5147 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5148 offset*(MagickOffsetType) cache_info->metacontent_extent;
5149 nexus_info->region.width=width;
5150 nexus_info->region.height=height;
5151 nexus_info->region.x=x;
5152 nexus_info->region.y=y;
5153 nexus_info->authentic_pixel_cache=MagickTrue;
5154 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5155 return(nexus_info->pixels);
5161 number_pixels=(MagickSizeType) width*height;
5162 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5163 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5164 if (cache_info->metacontent_extent != 0)
5165 length+=number_pixels*cache_info->metacontent_extent;
5167 if (nexus_info->cache == (Quantum *) NULL)
5168 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5170 if (nexus_info->length < length)
5172 RelinquishCacheNexusPixels(nexus_info);
5173 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5175 if (status == MagickFalse)
5176 return((Quantum *) NULL);
5177 nexus_info->pixels=nexus_info->cache;
5178 nexus_info->metacontent=(
void *) NULL;
5179 if (cache_info->metacontent_extent != 0)
5180 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5181 cache_info->number_channels*number_pixels);
5182 nexus_info->region.width=width;
5183 nexus_info->region.height=height;
5184 nexus_info->region.x=x;
5185 nexus_info->region.y=y;
5186 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5187 MagickTrue : MagickFalse;
5188 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5189 return(nexus_info->pixels);
5222static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5226 *magick_restrict image_view;
5234 assert(image != (
Image *) NULL);
5235 assert(image->signature == MagickCoreSignature);
5236 if (IsEventLogging() != MagickFalse)
5237 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5238 assert(image->cache != (Cache) NULL);
5239 image->alpha_trait=BlendPixelTrait;
5241 image_view=AcquireVirtualCacheView(image,exception);
5242#if defined(MAGICKCORE_OPENMP_SUPPORT)
5243 #pragma omp parallel for schedule(static) shared(status) \
5244 magick_number_threads(image,image,image->rows,2)
5246 for (y=0; y < (ssize_t) image->rows; y++)
5254 if (status == MagickFalse)
5256 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5257 if (q == (Quantum *) NULL)
5262 for (x=0; x < (ssize_t) image->columns; x++)
5264 SetPixelAlpha(image,alpha,q);
5265 q+=(ptrdiff_t) GetPixelChannels(image);
5267 status=SyncCacheViewAuthenticPixels(image_view,exception);
5269 image_view=DestroyCacheView(image_view);
5273MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5274 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5277 *magick_restrict cache_info;
5282 assert(image != (
Image *) NULL);
5283 assert(image->signature == MagickCoreSignature);
5284 if (IsEventLogging() != MagickFalse)
5285 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5286 assert(image->cache != (Cache) NULL);
5288 assert(cache_info->signature == MagickCoreSignature);
5289 method=cache_info->virtual_pixel_method;
5290 cache_info->virtual_pixel_method=virtual_pixel_method;
5291 if ((image->columns != 0) && (image->rows != 0))
5292 switch (virtual_pixel_method)
5294 case BackgroundVirtualPixelMethod:
5296 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5297 ((image->alpha_trait & BlendPixelTrait) == 0))
5298 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5299 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5300 (IsGrayColorspace(image->colorspace) != MagickFalse))
5301 (void) SetImageColorspace(image,sRGBColorspace,exception);
5304 case TransparentVirtualPixelMethod:
5306 if ((image->alpha_trait & BlendPixelTrait) == 0)
5307 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5316#if defined(MAGICKCORE_OPENCL_SUPPORT)
5341static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5343 assert(cache_info != (
CacheInfo *) NULL);
5344 assert(cache_info->signature == MagickCoreSignature);
5345 if ((cache_info->type != MemoryCache) ||
5346 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5351 LockSemaphoreInfo(cache_info->semaphore);
5352 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5353 UnlockSemaphoreInfo(cache_info->semaphore);
5356MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5359 *magick_restrict cache_info;
5361 assert(image != (
const Image *) NULL);
5363 CopyOpenCLBuffer(cache_info);
5396MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5400 *magick_restrict cache_info;
5408 assert(image != (
Image *) NULL);
5409 assert(image->signature == MagickCoreSignature);
5410 if (image->cache == (Cache) NULL)
5411 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5413 assert(cache_info->signature == MagickCoreSignature);
5414 if (cache_info->type == UndefinedCache)
5415 return(MagickFalse);
5416 if (image->mask_trait != UpdatePixelTrait)
5418 if (((image->channels & WriteMaskChannel) != 0) &&
5419 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5420 return(MagickFalse);
5421 if (((image->channels & CompositeMaskChannel) != 0) &&
5422 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5423 return(MagickFalse);
5425 if (nexus_info->authentic_pixel_cache != MagickFalse)
5427 if (image->taint == MagickFalse)
5428 image->taint=MagickTrue;
5431 assert(cache_info->signature == MagickCoreSignature);
5432 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5433 if ((cache_info->metacontent_extent != 0) &&
5434 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5435 return(MagickFalse);
5436 if ((status != MagickFalse) && (image->taint == MagickFalse))
5437 image->taint=MagickTrue;
5468static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5472 *magick_restrict cache_info;
5475 id = GetOpenMPThreadId();
5480 assert(image != (
Image *) NULL);
5481 assert(image->signature == MagickCoreSignature);
5482 assert(image->cache != (Cache) NULL);
5484 assert(cache_info->signature == MagickCoreSignature);
5485 assert(
id < (
int) cache_info->number_threads);
5486 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5518MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5522 *magick_restrict cache_info;
5525 id = GetOpenMPThreadId();
5530 assert(image != (
Image *) NULL);
5531 assert(image->signature == MagickCoreSignature);
5532 assert(image->cache != (Cache) NULL);
5534 assert(cache_info->signature == MagickCoreSignature);
5535 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5537 status=cache_info->methods.sync_authentic_pixels_handler(image,
5541 assert(
id < (
int) cache_info->number_threads);
5542 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5574MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5578 *magick_restrict cache_info;
5580 assert(image != (
Image *) NULL);
5582 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5583 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5614static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5634 if (cache_info->metacontent_extent == 0)
5635 return(MagickFalse);
5636 if (nexus_info->authentic_pixel_cache != MagickFalse)
5638 if (nexus_info->metacontent == (
unsigned char *) NULL)
5639 return(MagickFalse);
5640 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5641 return(MagickFalse);
5642 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5643 nexus_info->region.x;
5644 length=(MagickSizeType) nexus_info->region.width*
5645 cache_info->metacontent_extent;
5646 extent=(MagickSizeType) length*nexus_info->region.height;
5647 rows=nexus_info->region.height;
5649 p=(
unsigned char *) nexus_info->metacontent;
5650 switch (cache_info->type)
5661 if ((cache_info->columns == nexus_info->region.width) &&
5662 (extent == (MagickSizeType) ((
size_t) extent)))
5667 q=(
unsigned char *) cache_info->metacontent+offset*
5668 (MagickOffsetType) cache_info->metacontent_extent;
5669 for (y=0; y < (ssize_t) rows; y++)
5671 (void) memcpy(q,p,(
size_t) length);
5672 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5673 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5682 LockSemaphoreInfo(cache_info->file_semaphore);
5683 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5685 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5686 cache_info->cache_filename);
5687 UnlockSemaphoreInfo(cache_info->file_semaphore);
5688 return(MagickFalse);
5690 if ((cache_info->columns == nexus_info->region.width) &&
5691 (extent <= MagickMaxBufferExtent))
5696 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5697 for (y=0; y < (ssize_t) rows; y++)
5699 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5700 (MagickOffsetType) extent*(MagickOffsetType)
5701 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5702 (MagickOffsetType) cache_info->metacontent_extent,length,
5703 (
const unsigned char *) p);
5704 if (count != (MagickOffsetType) length)
5706 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5707 offset+=(MagickOffsetType) cache_info->columns;
5709 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5710 (void) ClosePixelCacheOnDisk(cache_info);
5711 UnlockSemaphoreInfo(cache_info->file_semaphore);
5714 case DistributedCache:
5722 LockSemaphoreInfo(cache_info->file_semaphore);
5723 region=nexus_info->region;
5724 if ((cache_info->columns != nexus_info->region.width) ||
5725 (extent > MagickMaxBufferExtent))
5732 for (y=0; y < (ssize_t) rows; y++)
5735 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5736 if (count != (MagickOffsetType) length)
5738 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5741 UnlockSemaphoreInfo(cache_info->file_semaphore);
5747 if (y < (ssize_t) rows)
5749 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5750 cache_info->cache_filename);
5751 return(MagickFalse);
5753 if ((cache_info->debug != MagickFalse) &&
5754 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5755 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5756 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5757 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5758 nexus_info->region.x,(
double) nexus_info->region.y);
5790static MagickBooleanType WritePixelCachePixels(
5811 if (nexus_info->authentic_pixel_cache != MagickFalse)
5813 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5814 return(MagickFalse);
5815 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5816 nexus_info->region.x;
5817 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5819 extent=length*nexus_info->region.height;
5820 rows=nexus_info->region.height;
5822 p=nexus_info->pixels;
5823 switch (cache_info->type)
5834 if ((cache_info->columns == nexus_info->region.width) &&
5835 (extent == (MagickSizeType) ((
size_t) extent)))
5840 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5842 for (y=0; y < (ssize_t) rows; y++)
5844 (void) memcpy(q,p,(
size_t) length);
5845 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5846 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5855 LockSemaphoreInfo(cache_info->file_semaphore);
5856 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5858 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5859 cache_info->cache_filename);
5860 UnlockSemaphoreInfo(cache_info->file_semaphore);
5861 return(MagickFalse);
5863 if ((cache_info->columns == nexus_info->region.width) &&
5864 (extent <= MagickMaxBufferExtent))
5869 for (y=0; y < (ssize_t) rows; y++)
5871 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5872 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5873 sizeof(*p),length,(
const unsigned char *) p);
5874 if (count != (MagickOffsetType) length)
5876 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5877 offset+=(MagickOffsetType) cache_info->columns;
5879 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5880 (void) ClosePixelCacheOnDisk(cache_info);
5881 UnlockSemaphoreInfo(cache_info->file_semaphore);
5884 case DistributedCache:
5892 LockSemaphoreInfo(cache_info->file_semaphore);
5893 region=nexus_info->region;
5894 if ((cache_info->columns != nexus_info->region.width) ||
5895 (extent > MagickMaxBufferExtent))
5902 for (y=0; y < (ssize_t) rows; y++)
5905 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5906 if (count != (MagickOffsetType) length)
5908 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5911 UnlockSemaphoreInfo(cache_info->file_semaphore);
5917 if (y < (ssize_t) rows)
5919 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5920 cache_info->cache_filename);
5921 return(MagickFalse);
5923 if ((cache_info->debug != MagickFalse) &&
5924 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5925 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5926 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5927 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5928 nexus_info->region.x,(
double) nexus_info->region.y);