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 (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
207 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
208 if (cache_info->number_threads == 0)
209 cache_info->number_threads=1;
210 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
211 if (cache_info->nexus_info == (
NexusInfo **) NULL)
212 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
213 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
214 if (value != (
const char *) NULL)
216 cache_info->synchronize=IsStringTrue(value);
217 value=DestroyString(value);
219 value=GetPolicyValue(
"cache:synchronize");
220 if (value != (
const char *) NULL)
222 cache_info->synchronize=IsStringTrue(value);
223 value=DestroyString(value);
225 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
226 (MagickSizeType) MAGICK_SSIZE_MAX);
227 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
228 (MagickSizeType) MAGICK_SSIZE_MAX);
229 cache_info->semaphore=AcquireSemaphoreInfo();
230 cache_info->reference_count=1;
231 cache_info->file_semaphore=AcquireSemaphoreInfo();
232 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
234 cache_info->signature=MagickCoreSignature;
235 return((Cache ) cache_info);
260MagickPrivate
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
263 **magick_restrict nexus_info;
268 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
269 number_threads,
sizeof(*nexus_info)));
271 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
272 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
273 2*
sizeof(**nexus_info));
275 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
276 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
277 for (i=0; i < (ssize_t) (2*number_threads); i++)
279 nexus_info[i]=(*nexus_info+i);
280 if (i < (ssize_t) number_threads)
281 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
282 nexus_info[i]->signature=MagickCoreSignature;
315MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
319 *magick_restrict cache_info;
321 assert(image != (
const Image *) NULL);
322 assert(image->signature == MagickCoreSignature);
324 assert(exception->signature == MagickCoreSignature);
325 assert(image->cache != (Cache) NULL);
328 assert(cache_info->signature == MagickCoreSignature);
330 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
331 return((
void *) NULL);
332 *length=(size_t) cache_info->length;
333 return(cache_info->pixels);
354MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
357 cache_semaphore=AcquireSemaphoreInfo();
379MagickPrivate
void CacheComponentTerminus(
void)
382 ActivateSemaphoreInfo(&cache_semaphore);
384 RelinquishSemaphoreInfo(&cache_semaphore);
416static MagickBooleanType ClipPixelCacheNexus(
Image *image,
420 *magick_restrict cache_info;
432 if (IsEventLogging() != MagickFalse)
433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
434 if ((image->channels & WriteMaskChannel) == 0)
436 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
439 if (cache_info == (Cache) NULL)
441 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
442 nexus_info->region.width,nexus_info->region.height,
443 nexus_info->virtual_nexus,exception);
444 q=nexus_info->pixels;
445 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
447 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
452 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
460 mask_alpha=QuantumScale*(double) GetPixelWriteMask(image,p);
461 if (fabs(mask_alpha) >= MagickEpsilon)
463 for (i=0; i < (ssize_t) image->number_channels; i++)
465 PixelChannel channel = GetPixelChannelChannel(image,i);
466 PixelTrait traits = GetPixelChannelTraits(image,channel);
467 if ((traits & UpdatePixelTrait) == 0)
469 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha*(
double)
470 GetPixelAlpha(image,p),(
double) q[i],(
double)
471 GetPixelAlpha(image,q)));
473 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
475 p+=GetPixelChannels(image);
476 q+=GetPixelChannels(image);
504MagickPrivate Cache ClonePixelCache(
const Cache cache)
507 *magick_restrict clone_info;
510 *magick_restrict cache_info;
512 assert(cache != NULL);
514 assert(cache_info->signature == MagickCoreSignature);
515 if (IsEventLogging() != MagickFalse)
516 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
517 cache_info->filename);
518 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
519 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
520 return((Cache ) clone_info);
548MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
551 *magick_restrict cache_info,
552 *magick_restrict source_info;
554 assert(clone != (Cache) NULL);
556 assert(source_info->signature == MagickCoreSignature);
557 if (IsEventLogging() != MagickFalse)
558 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
559 source_info->filename);
560 assert(cache != (Cache) NULL);
562 assert(cache_info->signature == MagickCoreSignature);
563 source_info->methods=cache_info->methods;
595static MagickBooleanType ClonePixelCacheOnDisk(
616 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
617 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
619 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
620 (lseek(clone_info->file,0,SEEK_SET) < 0))
622 quantum=(size_t) MagickMaxBufferExtent;
623 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
625#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
626 if (cache_info->length < 0x7ffff000)
628 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
629 (
size_t) cache_info->length);
630 if (count == (ssize_t) cache_info->length)
632 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
633 (lseek(clone_info->file,0,SEEK_SET) < 0))
637 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
639 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
640 if (buffer == (
unsigned char *) NULL)
641 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
643 while ((count=read(cache_info->file,buffer,quantum)) > 0)
648 number_bytes=write(clone_info->file,buffer,(
size_t) count);
649 if (number_bytes != count)
651 extent+=(size_t) number_bytes;
653 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
654 if (extent != cache_info->length)
659static MagickBooleanType ClonePixelCacheRepository(
663#define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
664#define cache_number_threads(source,destination,chunk,multithreaded) \
665 num_threads((multithreaded) == 0 ? 1 : \
666 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
667 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
668 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
669 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
676 **magick_restrict cache_nexus,
677 **magick_restrict clone_nexus;
685 assert(cache_info != (
CacheInfo *) NULL);
686 assert(clone_info != (
CacheInfo *) NULL);
688 if (cache_info->type == PingCache)
690 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
691 if ((cache_info->storage_class == clone_info->storage_class) &&
692 (cache_info->colorspace == clone_info->colorspace) &&
693 (cache_info->alpha_trait == clone_info->alpha_trait) &&
694 (cache_info->channels == clone_info->channels) &&
695 (cache_info->columns == clone_info->columns) &&
696 (cache_info->rows == clone_info->rows) &&
697 (cache_info->number_channels == clone_info->number_channels) &&
698 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
699 (cache_info->metacontent_extent == clone_info->metacontent_extent))
704 if (((cache_info->type == MemoryCache) ||
705 (cache_info->type == MapCache)) &&
706 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
708 (void) memcpy(clone_info->pixels,cache_info->pixels,
709 cache_info->number_channels*cache_info->columns*cache_info->rows*
710 sizeof(*cache_info->pixels));
711 if ((cache_info->metacontent_extent != 0) &&
712 (clone_info->metacontent_extent != 0))
713 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
714 cache_info->columns*cache_info->rows*
715 clone_info->metacontent_extent*
sizeof(
unsigned char));
718 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
719 return(ClonePixelCacheOnDisk(cache_info,clone_info));
724 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
725 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
726 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
727 optimize=(cache_info->number_channels == clone_info->number_channels) &&
728 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
729 MagickTrue : MagickFalse;
730 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
731 clone_info->number_channels*clone_info->columns);
733#if defined(MAGICKCORE_OPENMP_SUPPORT)
734 #pragma omp parallel for schedule(static) shared(status) \
735 cache_number_threads(cache_info,clone_info,(int) cache_info->rows,4)
737 for (y=0; y < (ssize_t) cache_info->rows; y++)
740 id = GetOpenMPThreadId();
748 if (status == MagickFalse)
750 if (y >= (ssize_t) clone_info->rows)
752 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
753 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
754 if (pixels == (Quantum *) NULL)
756 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
757 if (status == MagickFalse)
759 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
760 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
761 if (pixels == (Quantum *) NULL)
763 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
764 if (optimize != MagickFalse)
765 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
778 p=cache_nexus[id]->pixels;
779 q=clone_nexus[id]->pixels;
780 for (x=0; x < (ssize_t) cache_info->columns; x++)
785 if (x == (ssize_t) clone_info->columns)
787 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
795 channel=clone_info->channel_map[i].channel;
796 traits=cache_info->channel_map[channel].traits;
797 if (traits != UndefinedPixelTrait)
798 *q=*(p+cache_info->channel_map[channel].offset);
801 p+=cache_info->number_channels;
804 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
806 if ((cache_info->metacontent_extent != 0) &&
807 (clone_info->metacontent_extent != 0))
812 length=(size_t) MagickMin(cache_info->metacontent_extent,
813 clone_info->metacontent_extent);
814#if defined(MAGICKCORE_OPENMP_SUPPORT)
815 #pragma omp parallel for schedule(static) shared(status) \
816 cache_number_threads(cache_info,clone_info,(int) cache_info->rows,4)
818 for (y=0; y < (ssize_t) cache_info->rows; y++)
821 id = GetOpenMPThreadId();
826 if (status == MagickFalse)
828 if (y >= (ssize_t) clone_info->rows)
830 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
831 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
832 if (pixels == (Quantum *) NULL)
834 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
835 if (status == MagickFalse)
837 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
838 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
839 if (pixels == (Quantum *) NULL)
841 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
842 (cache_nexus[
id]->metacontent != (
void *) NULL))
843 (void) memcpy(clone_nexus[
id]->metacontent,
844 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
845 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
848 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
849 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
850 if (cache_info->debug != MagickFalse)
853 message[MagickPathExtent];
855 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
856 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
857 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
858 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
885static void DestroyImagePixelCache(
Image *image)
887 assert(image != (
Image *) NULL);
888 assert(image->signature == MagickCoreSignature);
889 if (IsEventLogging() != MagickFalse)
890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
891 if (image->cache != (
void *) NULL)
892 image->cache=DestroyPixelCache(image->cache);
917MagickExport
void DestroyImagePixels(
Image *image)
920 *magick_restrict cache_info;
922 assert(image != (
const Image *) NULL);
923 assert(image->signature == MagickCoreSignature);
924 if (IsEventLogging() != MagickFalse)
925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
926 assert(image->cache != (Cache) NULL);
928 assert(cache_info->signature == MagickCoreSignature);
929 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
931 cache_info->methods.destroy_pixel_handler(image);
934 image->cache=DestroyPixelCache(image->cache);
960static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
966 if (cache_info->file != -1)
968 status=close(cache_info->file);
969 cache_info->file=(-1);
970 RelinquishMagickResource(FileResource,1);
972 return(status == -1 ? MagickFalse : MagickTrue);
975static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
977 switch (cache_info->type)
981 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
982#if defined(MAGICKCORE_OPENCL_SUPPORT)
983 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
985 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
987 cache_info->pixels=(Quantum *) NULL;
991 if (cache_info->mapped == MagickFalse)
992 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
996 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
997 cache_info->pixels=(Quantum *) NULL;
999 RelinquishMagickResource(MemoryResource,cache_info->length);
1004 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1005 cache_info->pixels=(Quantum *) NULL;
1006 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1007 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1008 *cache_info->cache_filename=
'\0';
1009 RelinquishMagickResource(MapResource,cache_info->length);
1014 if (cache_info->file != -1)
1015 (void) ClosePixelCacheOnDisk(cache_info);
1016 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1017 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1018 *cache_info->cache_filename=
'\0';
1019 RelinquishMagickResource(DiskResource,cache_info->length);
1022 case DistributedCache:
1024 *cache_info->cache_filename=
'\0';
1026 cache_info->server_info);
1032 cache_info->type=UndefinedCache;
1033 cache_info->mapped=MagickFalse;
1034 cache_info->metacontent=(
void *) NULL;
1037MagickPrivate Cache DestroyPixelCache(Cache cache)
1040 *magick_restrict cache_info;
1042 assert(cache != (Cache) NULL);
1044 assert(cache_info->signature == MagickCoreSignature);
1045 if (IsEventLogging() != MagickFalse)
1046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1047 cache_info->filename);
1048 LockSemaphoreInfo(cache_info->semaphore);
1049 cache_info->reference_count--;
1050 if (cache_info->reference_count != 0)
1052 UnlockSemaphoreInfo(cache_info->semaphore);
1053 return((Cache) NULL);
1055 UnlockSemaphoreInfo(cache_info->semaphore);
1056 if (cache_info->debug != MagickFalse)
1059 message[MagickPathExtent];
1061 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1062 cache_info->filename);
1063 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1065 RelinquishPixelCachePixels(cache_info);
1068 cache_info->server_info);
1069 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1070 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1071 cache_info->number_threads);
1072 if (cache_info->random_info != (
RandomInfo *) NULL)
1073 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1075 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1077 RelinquishSemaphoreInfo(&cache_info->semaphore);
1078 cache_info->signature=(~MagickCoreSignature);
1079 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1110static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1112 if (nexus_info->mapped == MagickFalse)
1113 (void) RelinquishAlignedMemory(nexus_info->cache);
1115 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1116 nexus_info->cache=(Quantum *) NULL;
1117 nexus_info->pixels=(Quantum *) NULL;
1118 nexus_info->metacontent=(
void *) NULL;
1119 nexus_info->length=0;
1120 nexus_info->mapped=MagickFalse;
1124 const size_t number_threads)
1129 assert(nexus_info != (
NexusInfo **) NULL);
1130 for (i=0; i < (ssize_t) (2*number_threads); i++)
1132 if (nexus_info[i]->cache != (Quantum *) NULL)
1133 RelinquishCacheNexusPixels(nexus_info[i]);
1134 nexus_info[i]->signature=(~MagickCoreSignature);
1136 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1137 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1166MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1169 *magick_restrict cache_info;
1172 id = GetOpenMPThreadId();
1174 assert(image != (
const Image *) NULL);
1175 assert(image->signature == MagickCoreSignature);
1176 assert(image->cache != (Cache) NULL);
1178 assert(cache_info->signature == MagickCoreSignature);
1179 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1180 (GetAuthenticMetacontentFromHandler) NULL)
1185 metacontent=cache_info->methods.
1186 get_authentic_metacontent_from_handler(image);
1187 return(metacontent);
1189 assert(
id < (
int) cache_info->number_threads);
1190 return(cache_info->nexus_info[
id]->metacontent);
1217static void *GetAuthenticMetacontentFromCache(
const Image *image)
1220 *magick_restrict cache_info;
1223 id = GetOpenMPThreadId();
1225 assert(image != (
const Image *) NULL);
1226 assert(image->signature == MagickCoreSignature);
1227 assert(image->cache != (Cache) NULL);
1229 assert(cache_info->signature == MagickCoreSignature);
1230 assert(
id < (
int) cache_info->number_threads);
1231 return(cache_info->nexus_info[
id]->metacontent);
1234#if defined(MAGICKCORE_OPENCL_SUPPORT)
1263MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1267 *magick_restrict cache_info;
1269 assert(image != (
const Image *) NULL);
1270 assert(device != (
const MagickCLDevice) NULL);
1272 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1274 SyncImagePixelCache((
Image *) image,exception);
1277 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1278 return((cl_mem) NULL);
1279 LockSemaphoreInfo(cache_info->semaphore);
1280 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1281 (cache_info->opencl->device->context != device->context))
1282 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1283 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1285 assert(cache_info->pixels != (Quantum *) NULL);
1286 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1287 cache_info->length);
1289 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1290 RetainOpenCLMemObject(cache_info->opencl->buffer);
1291 UnlockSemaphoreInfo(cache_info->semaphore);
1292 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1293 return((cl_mem) NULL);
1294 assert(cache_info->opencl->pixels == cache_info->pixels);
1295 return(cache_info->opencl->buffer);
1334MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1335 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1339 *magick_restrict cache_info;
1342 *magick_restrict pixels;
1347 assert(image != (
Image *) NULL);
1348 assert(image->signature == MagickCoreSignature);
1349 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1350 nexus_info,exception);
1351 if (pixels == (Quantum *) NULL)
1352 return((Quantum *) NULL);
1354 assert(cache_info->signature == MagickCoreSignature);
1355 if (nexus_info->authentic_pixel_cache != MagickFalse)
1357 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1358 return((Quantum *) NULL);
1359 if (cache_info->metacontent_extent != 0)
1360 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1361 return((Quantum *) NULL);
1388static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1391 *magick_restrict cache_info;
1394 id = GetOpenMPThreadId();
1396 assert(image != (
const Image *) NULL);
1397 assert(image->signature == MagickCoreSignature);
1398 assert(image->cache != (Cache) NULL);
1400 assert(cache_info->signature == MagickCoreSignature);
1401 assert(
id < (
int) cache_info->number_threads);
1402 return(cache_info->nexus_info[
id]->pixels);
1429MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1432 *magick_restrict cache_info;
1435 id = GetOpenMPThreadId();
1437 assert(image != (
const Image *) NULL);
1438 assert(image->signature == MagickCoreSignature);
1439 assert(image->cache != (Cache) NULL);
1441 assert(cache_info->signature == MagickCoreSignature);
1442 if (cache_info->methods.get_authentic_pixels_from_handler !=
1443 (GetAuthenticPixelsFromHandler) NULL)
1444 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1445 assert(
id < (
int) cache_info->number_threads);
1446 return(cache_info->nexus_info[
id]->pixels);
1494MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1495 const ssize_t y,
const size_t columns,
const size_t rows,
1499 *magick_restrict cache_info;
1502 id = GetOpenMPThreadId();
1507 assert(image != (
Image *) NULL);
1508 assert(image->signature == MagickCoreSignature);
1509 assert(image->cache != (Cache) NULL);
1511 assert(cache_info->signature == MagickCoreSignature);
1512 if (cache_info->methods.get_authentic_pixels_handler !=
1513 (GetAuthenticPixelsHandler) NULL)
1515 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1519 assert(
id < (
int) cache_info->number_threads);
1520 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1521 cache_info->nexus_info[
id],exception);
1556static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1557 const ssize_t y,
const size_t columns,
const size_t rows,
1561 *magick_restrict cache_info;
1564 id = GetOpenMPThreadId();
1567 *magick_restrict pixels;
1569 assert(image != (
const Image *) NULL);
1570 assert(image->signature == MagickCoreSignature);
1571 assert(image->cache != (Cache) NULL);
1573 if (cache_info == (Cache) NULL)
1574 return((Quantum *) NULL);
1575 assert(cache_info->signature == MagickCoreSignature);
1576 assert(
id < (
int) cache_info->number_threads);
1577 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1578 cache_info->nexus_info[
id],exception);
1605MagickExport MagickSizeType GetImageExtent(
const Image *image)
1608 *magick_restrict cache_info;
1611 id = GetOpenMPThreadId();
1613 assert(image != (
Image *) NULL);
1614 assert(image->signature == MagickCoreSignature);
1615 if (IsEventLogging() != MagickFalse)
1616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1617 assert(image->cache != (Cache) NULL);
1619 assert(cache_info->signature == MagickCoreSignature);
1620 assert(
id < (
int) cache_info->number_threads);
1621 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1654static inline MagickBooleanType ValidatePixelCacheMorphology(
1655 const Image *magick_restrict image)
1658 *magick_restrict cache_info;
1668 p=image->channel_map;
1669 q=cache_info->channel_map;
1670 if ((image->storage_class != cache_info->storage_class) ||
1671 (image->colorspace != cache_info->colorspace) ||
1672 (image->alpha_trait != cache_info->alpha_trait) ||
1673 (image->channels != cache_info->channels) ||
1674 (image->columns != cache_info->columns) ||
1675 (image->rows != cache_info->rows) ||
1676 (image->number_channels != cache_info->number_channels) ||
1677 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1678 (image->metacontent_extent != cache_info->metacontent_extent) ||
1679 (cache_info->nexus_info == (
NexusInfo **) NULL))
1680 return(MagickFalse);
1684static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1688 *magick_restrict cache_info;
1692 status = MagickTrue;
1694 static MagickSizeType
1695 cpu_throttle = MagickResourceInfinity,
1698 if (IsImageTTLExpired(image) != MagickFalse)
1703 (void) ThrowMagickException(exception,GetMagickModule(),
1704 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1705 return((Cache) NULL);
1707 if (cpu_throttle == MagickResourceInfinity)
1708 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1709 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1710 MagickDelay(cpu_throttle);
1711 LockSemaphoreInfo(image->semaphore);
1712 assert(image->cache != (Cache) NULL);
1714#if defined(MAGICKCORE_OPENCL_SUPPORT)
1715 CopyOpenCLBuffer(cache_info);
1717 destroy=MagickFalse;
1718 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1720 LockSemaphoreInfo(cache_info->semaphore);
1721 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1732 clone_image=(*image);
1733 clone_image.semaphore=AcquireSemaphoreInfo();
1734 clone_image.reference_count=1;
1735 clone_image.cache=ClonePixelCache(cache_info);
1736 clone_info=(
CacheInfo *) clone_image.cache;
1737 status=OpenPixelCache(&clone_image,IOMode,exception);
1738 if (status == MagickFalse)
1739 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1742 if (clone != MagickFalse)
1743 status=ClonePixelCacheRepository(clone_info,cache_info,
1745 if (status == MagickFalse)
1746 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1750 image->cache=clone_info;
1753 RelinquishSemaphoreInfo(&clone_image.semaphore);
1755 UnlockSemaphoreInfo(cache_info->semaphore);
1757 if (destroy != MagickFalse)
1758 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1759 if (status != MagickFalse)
1764 if (image->type != UndefinedType)
1765 image->type=UndefinedType;
1766 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1768 status=OpenPixelCache(image,IOMode,exception);
1770 if (cache_info->file != -1)
1771 (void) ClosePixelCacheOnDisk(cache_info);
1774 UnlockSemaphoreInfo(image->semaphore);
1775 if (status == MagickFalse)
1776 return((Cache) NULL);
1777 return(image->cache);
1803MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1806 *magick_restrict cache_info;
1808 assert(image != (
Image *) NULL);
1809 assert(image->signature == MagickCoreSignature);
1810 assert(image->cache != (Cache) NULL);
1812 assert(cache_info->signature == MagickCoreSignature);
1813 return(cache_info->type);
1847static inline MagickBooleanType CopyPixel(
const Image *image,
1848 const Quantum *source,Quantum *destination)
1853 if (source == (
const Quantum *) NULL)
1855 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1856 destination[GreenPixelChannel]=ClampToQuantum(
1857 image->background_color.green);
1858 destination[BluePixelChannel]=ClampToQuantum(
1859 image->background_color.blue);
1860 destination[BlackPixelChannel]=ClampToQuantum(
1861 image->background_color.black);
1862 destination[AlphaPixelChannel]=ClampToQuantum(
1863 image->background_color.alpha);
1864 return(MagickFalse);
1866 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1868 PixelChannel channel = GetPixelChannelChannel(image,i);
1869 destination[channel]=source[i];
1874MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1875 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1878 *magick_restrict cache_info;
1883 assert(image != (
Image *) NULL);
1884 assert(image->signature == MagickCoreSignature);
1885 assert(image->cache != (Cache) NULL);
1887 assert(cache_info->signature == MagickCoreSignature);
1888 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1889 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1890 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1891 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1892 return(CopyPixel(image,q,pixel));
1926static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
1927 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1930 *magick_restrict cache_info;
1933 id = GetOpenMPThreadId();
1938 assert(image != (
const Image *) NULL);
1939 assert(image->signature == MagickCoreSignature);
1940 assert(image->cache != (Cache) NULL);
1942 assert(cache_info->signature == MagickCoreSignature);
1943 assert(
id < (
int) cache_info->number_threads);
1944 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1945 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
1947 return(CopyPixel(image,q,pixel));
1981MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
1982 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1985 *magick_restrict cache_info;
1988 id = GetOpenMPThreadId();
1993 assert(image != (
const Image *) NULL);
1994 assert(image->signature == MagickCoreSignature);
1995 assert(image->cache != (Cache) NULL);
1997 assert(cache_info->signature == MagickCoreSignature);
1998 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1999 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2000 (GetOneVirtualPixelFromHandler) NULL)
2001 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2002 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2003 assert(
id < (
int) cache_info->number_threads);
2004 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2005 1UL,1UL,cache_info->nexus_info[
id],exception);
2006 return(CopyPixel(image,p,pixel));
2043static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2044 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2048 *magick_restrict cache_info;
2051 id = GetOpenMPThreadId();
2056 assert(image != (
const Image *) NULL);
2057 assert(image->signature == MagickCoreSignature);
2058 assert(image->cache != (Cache) NULL);
2060 assert(cache_info->signature == MagickCoreSignature);
2061 assert(
id < (
int) cache_info->number_threads);
2062 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2063 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2064 cache_info->nexus_info[
id],exception);
2065 return(CopyPixel(image,p,pixel));
2102MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2103 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2107 *magick_restrict cache_info;
2110 id = GetOpenMPThreadId();
2115 assert(image != (
const Image *) NULL);
2116 assert(image->signature == MagickCoreSignature);
2117 assert(image->cache != (Cache) NULL);
2119 assert(cache_info->signature == MagickCoreSignature);
2120 assert(
id < (
int) cache_info->number_threads);
2121 GetPixelInfo(image,pixel);
2122 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2123 cache_info->nexus_info[
id],exception);
2124 if (p == (
const Quantum *) NULL)
2125 return(MagickFalse);
2126 GetPixelInfoPixel(image,p,pixel);
2152MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2155 *magick_restrict cache_info;
2157 assert(cache != (Cache) NULL);
2159 assert(cache_info->signature == MagickCoreSignature);
2160 if (IsEventLogging() != MagickFalse)
2161 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2162 cache_info->filename);
2163 return(cache_info->colorspace);
2189MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2192 *magick_restrict cache_info;
2194 assert(image != (
const Image *) NULL);
2195 assert(image->signature == MagickCoreSignature);
2196 assert(image->cache != (Cache) NULL);
2198 assert(cache_info->signature == MagickCoreSignature);
2199 return(cache_info->cache_filename);
2224MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2227 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2228 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2229 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2230 cache_methods->get_virtual_metacontent_from_handler=
2231 GetVirtualMetacontentFromCache;
2232 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2233 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2234 cache_methods->get_authentic_metacontent_from_handler=
2235 GetAuthenticMetacontentFromCache;
2236 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2237 cache_methods->get_one_authentic_pixel_from_handler=
2238 GetOneAuthenticPixelFromCache;
2239 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2240 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2241 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2269MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2273 *magick_restrict cache_info;
2278 assert(cache != NULL);
2280 assert(cache_info->signature == MagickCoreSignature);
2281 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2283 return((MagickSizeType) cache_info->columns*cache_info->rows);
2314MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2318 *magick_restrict cache_info;
2320 assert(image != (
const Image *) NULL);
2321 assert(image->signature == MagickCoreSignature);
2322 assert(image->cache != (Cache) NULL);
2323 assert(length != (MagickSizeType *) NULL);
2324 magick_unreferenced(exception);
2326 assert(cache_info->signature == MagickCoreSignature);
2327 *length=cache_info->length;
2328 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2329 return((
void *) NULL);
2330 return((
void *) cache_info->pixels);
2357MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2360 *magick_restrict cache_info;
2362 assert(cache != (Cache) NULL);
2364 assert(cache_info->signature == MagickCoreSignature);
2365 if (IsEventLogging() != MagickFalse)
2366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2367 cache_info->filename);
2368 return(cache_info->storage_class);
2398MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2402 *magick_restrict cache_info;
2404 assert(image != (
Image *) NULL);
2405 assert(image->signature == MagickCoreSignature);
2406 if (IsEventLogging() != MagickFalse)
2407 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2409 assert(cache_info->signature == MagickCoreSignature);
2410 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2411 if (GetImagePixelCacheType(image) == DiskCache)
2412 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2440MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2443 *magick_restrict cache_info;
2445 assert(image != (
Image *) NULL);
2446 assert(image->signature == MagickCoreSignature);
2447 assert(image->cache != (Cache) NULL);
2449 assert(cache_info->signature == MagickCoreSignature);
2450 return(cache_info->virtual_pixel_method);
2476static const void *GetVirtualMetacontentFromCache(
const Image *image)
2479 *magick_restrict cache_info;
2482 id = GetOpenMPThreadId();
2485 *magick_restrict metacontent;
2487 assert(image != (
const Image *) NULL);
2488 assert(image->signature == MagickCoreSignature);
2489 assert(image->cache != (Cache) NULL);
2491 assert(cache_info->signature == MagickCoreSignature);
2492 assert(
id < (
int) cache_info->number_threads);
2493 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2494 cache_info->nexus_info[
id]);
2495 return(metacontent);
2524MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2528 *magick_restrict cache_info;
2530 assert(cache != (Cache) NULL);
2532 assert(cache_info->signature == MagickCoreSignature);
2533 if (cache_info->storage_class == UndefinedClass)
2534 return((
void *) NULL);
2535 return(nexus_info->metacontent);
2562MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2565 *magick_restrict cache_info;
2568 id = GetOpenMPThreadId();
2571 *magick_restrict metacontent;
2573 assert(image != (
const Image *) NULL);
2574 assert(image->signature == MagickCoreSignature);
2575 assert(image->cache != (Cache) NULL);
2577 assert(cache_info->signature == MagickCoreSignature);
2578 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2580 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2582 if (metacontent != (
const void *) NULL)
2583 return(metacontent);
2585 assert(
id < (
int) cache_info->number_threads);
2586 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2587 cache_info->nexus_info[
id]);
2588 return(metacontent);
2631 0, 48, 12, 60, 3, 51, 15, 63,
2632 32, 16, 44, 28, 35, 19, 47, 31,
2633 8, 56, 4, 52, 11, 59, 7, 55,
2634 40, 24, 36, 20, 43, 27, 39, 23,
2635 2, 50, 14, 62, 1, 49, 13, 61,
2636 34, 18, 46, 30, 33, 17, 45, 29,
2637 10, 58, 6, 54, 9, 57, 5, 53,
2638 42, 26, 38, 22, 41, 25, 37, 21
2641static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2646 index=x+DitherMatrix[x & 0x07]-32L;
2649 if (index >= (ssize_t) columns)
2650 return((ssize_t) columns-1L);
2654static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2659 index=y+DitherMatrix[y & 0x07]-32L;
2662 if (index >= (ssize_t) rows)
2663 return((ssize_t) rows-1L);
2667static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2671 if (x >= (ssize_t) columns)
2672 return((ssize_t) (columns-1));
2676static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2680 if (y >= (ssize_t) rows)
2681 return((ssize_t) (rows-1));
2685static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2688 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2689 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2690 return(MagickFalse);
2694static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2696 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2699static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2701 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2704static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2705 const size_t extent)
2710 modulo.quotient=offset;
2714 modulo.quotient=offset/((ssize_t) extent);
2715 modulo.remainder=offset % ((ssize_t) extent);
2717 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2720 modulo.remainder+=((ssize_t) extent);
2725MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2726 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2727 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2731 *magick_restrict cache_info;
2747 *magick_restrict virtual_nexus;
2750 *magick_restrict pixels,
2752 virtual_pixel[MaxPixelChannels];
2763 *magick_restrict virtual_metacontent;
2768 assert(image != (
const Image *) NULL);
2769 assert(image->signature == MagickCoreSignature);
2770 assert(image->cache != (Cache) NULL);
2772 assert(cache_info->signature == MagickCoreSignature);
2773 if (cache_info->type == UndefinedCache)
2774 return((
const Quantum *) NULL);
2775#if defined(MAGICKCORE_OPENCL_SUPPORT)
2776 CopyOpenCLBuffer(cache_info);
2778 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2779 ((image->channels & WriteMaskChannel) != 0) ||
2780 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2781 nexus_info,exception);
2782 if (pixels == (Quantum *) NULL)
2783 return((
const Quantum *) NULL);
2784 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2785 return((
const Quantum *) NULL);
2786 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2787 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
2788 return((
const Quantum *) NULL);
2789 offset+=nexus_info->region.x;
2790 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2791 nexus_info->region.width-1L;
2792 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2793 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2794 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2795 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2803 if (nexus_info->authentic_pixel_cache != MagickFalse)
2805 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2806 if (status == MagickFalse)
2807 return((
const Quantum *) NULL);
2808 if (cache_info->metacontent_extent != 0)
2810 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2811 if (status == MagickFalse)
2812 return((
const Quantum *) NULL);
2819 virtual_nexus=nexus_info->virtual_nexus;
2821 s=(
unsigned char *) nexus_info->metacontent;
2822 (void) memset(virtual_pixel,0,cache_info->number_channels*
2823 sizeof(*virtual_pixel));
2824 virtual_metacontent=(
void *) NULL;
2825 switch (virtual_pixel_method)
2827 case BackgroundVirtualPixelMethod:
2828 case BlackVirtualPixelMethod:
2829 case GrayVirtualPixelMethod:
2830 case TransparentVirtualPixelMethod:
2831 case MaskVirtualPixelMethod:
2832 case WhiteVirtualPixelMethod:
2833 case EdgeVirtualPixelMethod:
2834 case CheckerTileVirtualPixelMethod:
2835 case HorizontalTileVirtualPixelMethod:
2836 case VerticalTileVirtualPixelMethod:
2838 if (cache_info->metacontent_extent != 0)
2843 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2844 cache_info->metacontent_extent);
2845 if (virtual_metacontent == (
void *) NULL)
2847 (void) ThrowMagickException(exception,GetMagickModule(),
2848 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2849 return((
const Quantum *) NULL);
2851 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2853 switch (virtual_pixel_method)
2855 case BlackVirtualPixelMethod:
2857 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2858 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2859 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2862 case GrayVirtualPixelMethod:
2864 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2865 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2867 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2870 case TransparentVirtualPixelMethod:
2872 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2873 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2874 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2877 case MaskVirtualPixelMethod:
2878 case WhiteVirtualPixelMethod:
2880 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2881 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2882 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2887 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2889 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2891 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2893 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2895 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2905 for (v=0; v < (ssize_t) rows; v++)
2911 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2912 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2913 y_offset=EdgeY(y_offset,cache_info->rows);
2914 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2920 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2921 x_offset,(ssize_t) columns-u);
2922 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2923 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2933 length=(MagickSizeType) 1;
2934 switch (virtual_pixel_method)
2936 case EdgeVirtualPixelMethod:
2939 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2940 EdgeX(x_offset,cache_info->columns),
2941 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2943 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2946 case RandomVirtualPixelMethod:
2948 if (cache_info->random_info == (
RandomInfo *) NULL)
2949 cache_info->random_info=AcquireRandomInfo();
2950 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2951 RandomX(cache_info->random_info,cache_info->columns),
2952 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2953 virtual_nexus,exception);
2954 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2957 case DitherVirtualPixelMethod:
2959 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2960 DitherX(x_offset,cache_info->columns),
2961 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2963 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2966 case TileVirtualPixelMethod:
2968 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2969 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2970 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2971 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2973 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2976 case MirrorVirtualPixelMethod:
2978 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2979 if ((x_modulo.quotient & 0x01) == 1L)
2980 x_modulo.remainder=(ssize_t) cache_info->columns-
2981 x_modulo.remainder-1L;
2982 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2983 if ((y_modulo.quotient & 0x01) == 1L)
2984 y_modulo.remainder=(ssize_t) cache_info->rows-
2985 y_modulo.remainder-1L;
2986 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2987 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2989 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2992 case HorizontalTileEdgeVirtualPixelMethod:
2994 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2995 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2996 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
2997 virtual_nexus,exception);
2998 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3001 case VerticalTileEdgeVirtualPixelMethod:
3003 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3004 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3005 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3006 virtual_nexus,exception);
3007 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3010 case BackgroundVirtualPixelMethod:
3011 case BlackVirtualPixelMethod:
3012 case GrayVirtualPixelMethod:
3013 case TransparentVirtualPixelMethod:
3014 case MaskVirtualPixelMethod:
3015 case WhiteVirtualPixelMethod:
3018 r=virtual_metacontent;
3021 case CheckerTileVirtualPixelMethod:
3023 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3024 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3025 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3028 r=virtual_metacontent;
3031 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3032 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3034 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3037 case HorizontalTileVirtualPixelMethod:
3039 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3042 r=virtual_metacontent;
3045 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3046 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3047 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3048 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3050 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3053 case VerticalTileVirtualPixelMethod:
3055 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3058 r=virtual_metacontent;
3061 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3062 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3063 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3064 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3066 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3070 if (p == (
const Quantum *) NULL)
3072 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3074 q+=cache_info->number_channels;
3075 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3077 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3078 s+=cache_info->metacontent_extent;
3085 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3086 (
size_t) length,1UL,virtual_nexus,exception);
3087 if (p == (
const Quantum *) NULL)
3089 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3090 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3092 q+=cache_info->number_channels*length;
3093 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3095 (void) memcpy(s,r,(
size_t) length);
3096 s+=length*cache_info->metacontent_extent;
3099 if (u < (ssize_t) columns)
3105 if (virtual_metacontent != (
void *) NULL)
3106 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3107 if (v < (ssize_t) rows)
3108 return((
const Quantum *) NULL);
3146static const Quantum *GetVirtualPixelCache(
const Image *image,
3147 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3148 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3151 *magick_restrict cache_info;
3154 id = GetOpenMPThreadId();
3159 assert(image != (
const Image *) NULL);
3160 assert(image->signature == MagickCoreSignature);
3161 assert(image->cache != (Cache) NULL);
3163 assert(cache_info->signature == MagickCoreSignature);
3164 assert(
id < (
int) cache_info->number_threads);
3165 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3166 cache_info->nexus_info[
id],exception);
3193MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3196 *magick_restrict cache_info;
3199 id = GetOpenMPThreadId();
3201 assert(image != (
const Image *) NULL);
3202 assert(image->signature == MagickCoreSignature);
3203 assert(image->cache != (Cache) NULL);
3205 assert(cache_info->signature == MagickCoreSignature);
3206 if (cache_info->methods.get_virtual_pixels_handler !=
3207 (GetVirtualPixelsHandler) NULL)
3208 return(cache_info->methods.get_virtual_pixels_handler(image));
3209 assert(
id < (
int) cache_info->number_threads);
3210 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3261MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3262 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3266 *magick_restrict cache_info;
3269 id = GetOpenMPThreadId();
3274 assert(image != (
const Image *) NULL);
3275 assert(image->signature == MagickCoreSignature);
3276 assert(image->cache != (Cache) NULL);
3278 assert(cache_info->signature == MagickCoreSignature);
3279 if (cache_info->methods.get_virtual_pixel_handler !=
3280 (GetVirtualPixelHandler) NULL)
3281 return(cache_info->methods.get_virtual_pixel_handler(image,
3282 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3283 assert(
id < (
int) cache_info->number_threads);
3284 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3285 columns,rows,cache_info->nexus_info[
id],exception);
3312static const Quantum *GetVirtualPixelsCache(
const Image *image)
3315 *magick_restrict cache_info;
3318 id = GetOpenMPThreadId();
3320 assert(image != (
const Image *) NULL);
3321 assert(image->signature == MagickCoreSignature);
3322 assert(image->cache != (Cache) NULL);
3324 assert(cache_info->signature == MagickCoreSignature);
3325 assert(
id < (
int) cache_info->number_threads);
3326 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3355MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3359 *magick_restrict cache_info;
3361 assert(cache != (Cache) NULL);
3363 assert(cache_info->signature == MagickCoreSignature);
3364 if (cache_info->storage_class == UndefinedClass)
3365 return((Quantum *) NULL);
3366 return((
const Quantum *) nexus_info->pixels);
3399static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3400 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3405 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3407 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3408 gamma=PerceptibleReciprocal(gamma);
3409 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3412static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3416 *magick_restrict cache_info;
3428 if (IsEventLogging() != MagickFalse)
3429 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3430 if ((image->channels & CompositeMaskChannel) == 0)
3432 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3435 if (cache_info == (Cache) NULL)
3436 return(MagickFalse);
3437 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3438 nexus_info->region.width,nexus_info->region.height,
3439 nexus_info->virtual_nexus,exception);
3440 q=nexus_info->pixels;
3441 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3442 return(MagickFalse);
3443 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3448 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3456 alpha=(double) GetPixelCompositeMask(image,p);
3457 for (i=0; i < (ssize_t) image->number_channels; i++)
3459 PixelChannel channel = GetPixelChannelChannel(image,i);
3460 PixelTrait traits = GetPixelChannelTraits(image,channel);
3461 if ((traits & UpdatePixelTrait) == 0)
3463 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3465 p+=GetPixelChannels(image);
3466 q+=GetPixelChannels(image);
3503static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3512 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3514 if (*cache_info->cache_filename ==
'\0')
3515 file=AcquireUniqueFileResource(cache_info->cache_filename);
3521 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3526 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3527 O_BINARY | O_EXCL,S_MODE);
3529 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3535 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3538 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3543 return(MagickFalse);
3544 (void) AcquireMagickResource(FileResource,1);
3545 if (cache_info->file != -1)
3546 (void) ClosePixelCacheOnDisk(cache_info);
3547 cache_info->file=file;
3548 cache_info->disk_mode=mode;
3552static inline MagickOffsetType WritePixelCacheRegion(
3553 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3554 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3562#if !defined(MAGICKCORE_HAVE_PWRITE)
3563 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3564 return((MagickOffsetType) -1);
3566 for (i=0; i < (MagickOffsetType) length; i+=count)
3568#if !defined(MAGICKCORE_HAVE_PWRITE)
3569 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3570 (MagickSizeType) i,MAGICK_SSIZE_MAX));
3572 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3573 (MagickSizeType) i,MAGICK_SSIZE_MAX),offset+i);
3585static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3588 *magick_restrict cache_info;
3594 if (cache_info->debug != MagickFalse)
3597 format[MagickPathExtent],
3598 message[MagickPathExtent];
3600 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3601 (void) FormatLocaleString(message,MagickPathExtent,
3602 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3603 cache_info->cache_filename,cache_info->file,format);
3604 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3606 if (length != (MagickSizeType) ((MagickOffsetType) length))
3607 return(MagickFalse);
3608 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3610 return(MagickFalse);
3611 if ((MagickSizeType) offset < length)
3617 extent=(MagickOffsetType) length-1;
3618 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3621 return(MagickFalse);
3622#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3623 if (cache_info->synchronize != MagickFalse)
3624 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3625 return(MagickFalse);
3628 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3630 return(MagickFalse);
3634static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3638 *magick_restrict cache_info,
3642 format[MagickPathExtent],
3643 message[MagickPathExtent];
3660 assert(image != (
const Image *) NULL);
3661 assert(image->signature == MagickCoreSignature);
3662 assert(image->cache != (Cache) NULL);
3663 if (IsEventLogging() != MagickFalse)
3664 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3665 if (cache_anonymous_memory < 0)
3673 cache_anonymous_memory=0;
3674 value=GetPolicyValue(
"pixel-cache-memory");
3675 if (value == (
char *) NULL)
3676 value=GetPolicyValue(
"cache:memory-map");
3677 if (LocaleCompare(value,
"anonymous") == 0)
3679#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3680 cache_anonymous_memory=1;
3682 (void) ThrowMagickException(exception,GetMagickModule(),
3683 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3684 "'%s' (policy requires anonymous memory mapping)",image->filename);
3687 value=DestroyString(value);
3689 if ((image->columns == 0) || (image->rows == 0))
3690 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3692 assert(cache_info->signature == MagickCoreSignature);
3693 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3694 ((MagickSizeType) image->rows > cache_info->height_limit))
3695 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3697 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3699 length=GetImageListLength(image);
3700 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3701 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3704 source_info=(*cache_info);
3705 source_info.file=(-1);
3706 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3707 image->filename,(
double) image->scene);
3708 cache_info->storage_class=image->storage_class;
3709 cache_info->colorspace=image->colorspace;
3710 cache_info->alpha_trait=image->alpha_trait;
3711 cache_info->channels=image->channels;
3712 cache_info->rows=image->rows;
3713 cache_info->columns=image->columns;
3714 status=ResetPixelChannelMap(image,exception);
3715 if (status == MagickFalse)
3716 return(MagickFalse);
3717 cache_info->number_channels=GetPixelChannels(image);
3718 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3719 sizeof(*image->channel_map));
3720 cache_info->metacontent_extent=image->metacontent_extent;
3721 cache_info->mode=mode;
3722 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3723 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3724 if (image->metacontent_extent != 0)
3725 packet_size+=cache_info->metacontent_extent;
3726 length=number_pixels*packet_size;
3727 columns=(size_t) (length/cache_info->rows/packet_size);
3728 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3729 ((ssize_t) cache_info->rows < 0))
3730 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3732 cache_info->length=length;
3733 if (image->ping != MagickFalse)
3735 cache_info->type=PingCache;
3738 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3739 cache_info->columns*cache_info->rows);
3740 if (cache_info->mode == PersistMode)
3742 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3743 cache_info->metacontent_extent);
3744 if ((status != MagickFalse) &&
3745 (length == (MagickSizeType) ((
size_t) length)) &&
3746 ((cache_info->type == UndefinedCache) ||
3747 (cache_info->type == MemoryCache)))
3749 status=AcquireMagickResource(MemoryResource,cache_info->length);
3750 if (status != MagickFalse)
3753 if (cache_anonymous_memory <= 0)
3755 cache_info->mapped=MagickFalse;
3756 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3757 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3761 cache_info->mapped=MagickTrue;
3762 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3763 cache_info->length);
3765 if (cache_info->pixels == (Quantum *) NULL)
3767 cache_info->mapped=source_info.mapped;
3768 cache_info->pixels=source_info.pixels;
3775 cache_info->type=MemoryCache;
3776 cache_info->metacontent=(
void *) NULL;
3777 if (cache_info->metacontent_extent != 0)
3778 cache_info->metacontent=(
void *) (cache_info->pixels+
3779 cache_info->number_channels*number_pixels);
3780 if ((source_info.storage_class != UndefinedClass) &&
3783 status=ClonePixelCacheRepository(cache_info,&source_info,
3785 RelinquishPixelCachePixels(&source_info);
3787 if (cache_info->debug != MagickFalse)
3789 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3790 MagickPathExtent,format);
3791 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3793 (void) FormatLocaleString(message,MagickPathExtent,
3794 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3795 cache_info->filename,cache_info->mapped != MagickFalse ?
3796 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3797 (double) cache_info->rows,(double)
3798 cache_info->number_channels,format);
3799 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3802 cache_info->storage_class=image->storage_class;
3805 cache_info->type=UndefinedCache;
3806 return(MagickFalse);
3812 status=AcquireMagickResource(DiskResource,cache_info->length);
3813 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3815 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3823 server_info=AcquireDistributeCacheInfo(exception);
3826 status=OpenDistributePixelCache(server_info,image);
3827 if (status == MagickFalse)
3829 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3830 GetDistributeCacheHostname(server_info));
3831 server_info=DestroyDistributeCacheInfo(server_info);
3839 cache_info->type=DistributedCache;
3840 cache_info->server_info=server_info;
3841 (void) FormatLocaleString(cache_info->cache_filename,
3842 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3845 cache_info->server_info));
3846 if ((source_info.storage_class != UndefinedClass) &&
3849 status=ClonePixelCacheRepository(cache_info,&source_info,
3851 RelinquishPixelCachePixels(&source_info);
3853 if (cache_info->debug != MagickFalse)
3855 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3856 MagickPathExtent,format);
3857 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3859 (void) FormatLocaleString(message,MagickPathExtent,
3860 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3861 cache_info->filename,cache_info->cache_filename,
3863 cache_info->server_info),type,(double) cache_info->columns,
3864 (
double) cache_info->rows,(double)
3865 cache_info->number_channels,format);
3866 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3871 cache_info->type=UndefinedCache;
3872 return(MagickFalse);
3877 cache_info->type=UndefinedCache;
3878 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3879 "CacheResourcesExhausted",
"`%s'",image->filename);
3880 return(MagickFalse);
3885 if (status == MagickFalse)
3887 cache_info->type=UndefinedCache;
3888 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3889 "CacheResourcesExhausted",
"`%s'",image->filename);
3890 return(MagickFalse);
3892 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3893 (cache_info->mode != PersistMode))
3895 (void) ClosePixelCacheOnDisk(cache_info);
3896 *cache_info->cache_filename=
'\0';
3898 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3900 cache_info->type=UndefinedCache;
3901 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3903 return(MagickFalse);
3905 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3906 cache_info->length);
3907 if (status == MagickFalse)
3909 cache_info->type=UndefinedCache;
3910 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3912 return(MagickFalse);
3914 cache_info->type=DiskCache;
3915 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3916 cache_info->metacontent_extent);
3917 if (length == (MagickSizeType) ((
size_t) length))
3919 status=AcquireMagickResource(MapResource,cache_info->length);
3920 if (status != MagickFalse)
3922 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3923 cache_info->offset,(
size_t) cache_info->length);
3924 if (cache_info->pixels == (Quantum *) NULL)
3926 cache_info->mapped=source_info.mapped;
3927 cache_info->pixels=source_info.pixels;
3928 RelinquishMagickResource(MapResource,cache_info->length);
3935 (void) ClosePixelCacheOnDisk(cache_info);
3936 cache_info->type=MapCache;
3937 cache_info->mapped=MagickTrue;
3938 cache_info->metacontent=(
void *) NULL;
3939 if (cache_info->metacontent_extent != 0)
3940 cache_info->metacontent=(
void *) (cache_info->pixels+
3941 cache_info->number_channels*number_pixels);
3942 if ((source_info.storage_class != UndefinedClass) &&
3945 status=ClonePixelCacheRepository(cache_info,&source_info,
3947 RelinquishPixelCachePixels(&source_info);
3949 if (cache_info->debug != MagickFalse)
3951 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3952 MagickPathExtent,format);
3953 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3955 (void) FormatLocaleString(message,MagickPathExtent,
3956 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3957 cache_info->filename,cache_info->cache_filename,
3958 cache_info->file,type,(
double) cache_info->columns,
3959 (double) cache_info->rows,(
double)
3960 cache_info->number_channels,format);
3961 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3966 cache_info->type=UndefinedCache;
3967 return(MagickFalse);
3974 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3976 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3977 RelinquishPixelCachePixels(&source_info);
3979 if (cache_info->debug != MagickFalse)
3981 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3982 MagickPathExtent,format);
3983 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3985 (void) FormatLocaleString(message,MagickPathExtent,
3986 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
3987 cache_info->cache_filename,cache_info->file,type,(
double)
3988 cache_info->columns,(double) cache_info->rows,(
double)
3989 cache_info->number_channels,format);
3990 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3994 cache_info->type=UndefinedCache;
3995 return(MagickFalse);
4037MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4038 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4042 *magick_restrict cache_info,
4043 *magick_restrict clone_info;
4051 assert(image != (
Image *) NULL);
4052 assert(image->signature == MagickCoreSignature);
4053 if (IsEventLogging() != MagickFalse)
4054 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4055 assert(image->cache != (
void *) NULL);
4056 assert(filename != (
const char *) NULL);
4057 assert(offset != (MagickOffsetType *) NULL);
4058 page_size=GetMagickPageSize();
4060 assert(cache_info->signature == MagickCoreSignature);
4061#if defined(MAGICKCORE_OPENCL_SUPPORT)
4062 CopyOpenCLBuffer(cache_info);
4064 if (attach != MagickFalse)
4069 if (cache_info->debug != MagickFalse)
4070 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4071 "attach persistent cache");
4072 (void) CopyMagickString(cache_info->cache_filename,filename,
4074 cache_info->type=MapCache;
4075 cache_info->offset=(*offset);
4076 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4077 return(MagickFalse);
4078 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4079 ((MagickOffsetType) cache_info->length % page_size));
4085 status=AcquireMagickResource(DiskResource,cache_info->length);
4086 if (status == MagickFalse)
4088 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4089 "CacheResourcesExhausted",
"`%s'",image->filename);
4090 return(MagickFalse);
4092 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4093 clone_info->type=DiskCache;
4094 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4095 clone_info->file=(-1);
4096 clone_info->storage_class=cache_info->storage_class;
4097 clone_info->colorspace=cache_info->colorspace;
4098 clone_info->alpha_trait=cache_info->alpha_trait;
4099 clone_info->channels=cache_info->channels;
4100 clone_info->columns=cache_info->columns;
4101 clone_info->rows=cache_info->rows;
4102 clone_info->number_channels=cache_info->number_channels;
4103 clone_info->metacontent_extent=cache_info->metacontent_extent;
4104 clone_info->mode=PersistMode;
4105 clone_info->length=cache_info->length;
4106 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4107 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4108 clone_info->offset=(*offset);
4109 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4110 if (status != MagickFalse)
4111 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4112 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4113 ((MagickOffsetType) cache_info->length % page_size));
4114 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4156MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4157 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4161 *magick_restrict cache_info;
4170 *magick_restrict pixels;
4175 assert(image != (
const Image *) NULL);
4176 assert(image->signature == MagickCoreSignature);
4177 assert(image->cache != (Cache) NULL);
4178 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4179 if (cache_info == (Cache) NULL)
4180 return((Quantum *) NULL);
4181 assert(cache_info->signature == MagickCoreSignature);
4182 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4183 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4184 (y >= (ssize_t) cache_info->rows))
4186 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4187 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4188 return((Quantum *) NULL);
4190 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4191 return((Quantum *) NULL);
4192 offset=y*(MagickOffsetType) cache_info->columns+x;
4194 return((Quantum *) NULL);
4195 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4196 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4197 (MagickOffsetType) columns-1;
4198 if ((MagickSizeType) offset >= number_pixels)
4199 return((Quantum *) NULL);
4203 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4204 ((image->channels & WriteMaskChannel) != 0) ||
4205 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4206 nexus_info,exception);
4243static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4244 const ssize_t y,
const size_t columns,
const size_t rows,
4248 *magick_restrict cache_info;
4251 id = GetOpenMPThreadId();
4254 *magick_restrict pixels;
4256 assert(image != (
const Image *) NULL);
4257 assert(image->signature == MagickCoreSignature);
4258 assert(image->cache != (Cache) NULL);
4260 assert(cache_info->signature == MagickCoreSignature);
4261 assert(
id < (
int) cache_info->number_threads);
4262 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4263 cache_info->nexus_info[
id],exception);
4323MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4324 const ssize_t y,
const size_t columns,
const size_t rows,
4328 *magick_restrict cache_info;
4331 id = GetOpenMPThreadId();
4334 *magick_restrict pixels;
4336 assert(image != (
Image *) NULL);
4337 assert(image->signature == MagickCoreSignature);
4338 assert(image->cache != (Cache) NULL);
4340 assert(cache_info->signature == MagickCoreSignature);
4341 if (cache_info->methods.queue_authentic_pixels_handler !=
4342 (QueueAuthenticPixelsHandler) NULL)
4344 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4345 columns,rows,exception);
4348 assert(
id < (
int) cache_info->number_threads);
4349 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4350 cache_info->nexus_info[
id],exception);
4383static inline MagickOffsetType ReadPixelCacheRegion(
4384 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4385 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4393#if !defined(MAGICKCORE_HAVE_PREAD)
4394 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4395 return((MagickOffsetType) -1);
4397 for (i=0; i < (MagickOffsetType) length; i+=count)
4399#if !defined(MAGICKCORE_HAVE_PREAD)
4400 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4401 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX));
4403 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4404 (MagickSizeType) i,(
size_t) MAGICK_SSIZE_MAX),offset+i);
4416static MagickBooleanType ReadPixelCacheMetacontent(
4437 if (cache_info->metacontent_extent == 0)
4438 return(MagickFalse);
4439 if (nexus_info->authentic_pixel_cache != MagickFalse)
4441 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4442 return(MagickFalse);
4443 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4444 nexus_info->region.x;
4445 length=(MagickSizeType) nexus_info->region.width*
4446 cache_info->metacontent_extent;
4447 extent=length*nexus_info->region.height;
4448 rows=nexus_info->region.height;
4450 q=(
unsigned char *) nexus_info->metacontent;
4451 switch (cache_info->type)
4462 if ((cache_info->columns == nexus_info->region.width) &&
4463 (extent == (MagickSizeType) ((
size_t) extent)))
4468 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4469 cache_info->metacontent_extent;
4470 for (y=0; y < (ssize_t) rows; y++)
4472 (void) memcpy(q,p,(
size_t) length);
4473 p+=cache_info->metacontent_extent*cache_info->columns;
4474 q+=cache_info->metacontent_extent*nexus_info->region.width;
4483 LockSemaphoreInfo(cache_info->file_semaphore);
4484 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4486 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4487 cache_info->cache_filename);
4488 UnlockSemaphoreInfo(cache_info->file_semaphore);
4489 return(MagickFalse);
4491 if ((cache_info->columns == nexus_info->region.width) &&
4492 (extent <= MagickMaxBufferExtent))
4497 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4498 for (y=0; y < (ssize_t) rows; y++)
4500 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4501 (MagickOffsetType) extent*(MagickOffsetType)
4502 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4503 (MagickOffsetType) cache_info->metacontent_extent,length,
4504 (
unsigned char *) q);
4505 if (count != (MagickOffsetType) length)
4507 offset+=(MagickOffsetType) cache_info->columns;
4508 q+=cache_info->metacontent_extent*nexus_info->region.width;
4510 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4511 (void) ClosePixelCacheOnDisk(cache_info);
4512 UnlockSemaphoreInfo(cache_info->file_semaphore);
4515 case DistributedCache:
4523 LockSemaphoreInfo(cache_info->file_semaphore);
4524 region=nexus_info->region;
4525 if ((cache_info->columns != nexus_info->region.width) ||
4526 (extent > MagickMaxBufferExtent))
4533 for (y=0; y < (ssize_t) rows; y++)
4536 cache_info->server_info,®ion,length,(
unsigned char *) q);
4537 if (count != (MagickOffsetType) length)
4539 q+=cache_info->metacontent_extent*nexus_info->region.width;
4542 UnlockSemaphoreInfo(cache_info->file_semaphore);
4548 if (y < (ssize_t) rows)
4550 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4551 cache_info->cache_filename);
4552 return(MagickFalse);
4554 if ((cache_info->debug != MagickFalse) &&
4555 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4556 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4557 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4558 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4559 nexus_info->region.x,(
double) nexus_info->region.y);
4591static MagickBooleanType ReadPixelCachePixels(
4613 if (nexus_info->authentic_pixel_cache != MagickFalse)
4615 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4616 return(MagickFalse);
4617 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4618 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4619 return(MagickFalse);
4620 offset+=nexus_info->region.x;
4621 number_channels=cache_info->number_channels;
4622 length=(MagickSizeType) number_channels*nexus_info->region.width*
4624 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4625 return(MagickFalse);
4626 rows=nexus_info->region.height;
4628 if ((extent == 0) || ((extent/length) != rows))
4629 return(MagickFalse);
4631 q=nexus_info->pixels;
4632 switch (cache_info->type)
4643 if ((cache_info->columns == nexus_info->region.width) &&
4644 (extent == (MagickSizeType) ((
size_t) extent)))
4649 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4651 for (y=0; y < (ssize_t) rows; y++)
4653 (void) memcpy(q,p,(
size_t) length);
4654 p+=cache_info->number_channels*cache_info->columns;
4655 q+=cache_info->number_channels*nexus_info->region.width;
4664 LockSemaphoreInfo(cache_info->file_semaphore);
4665 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4667 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4668 cache_info->cache_filename);
4669 UnlockSemaphoreInfo(cache_info->file_semaphore);
4670 return(MagickFalse);
4672 if ((cache_info->columns == nexus_info->region.width) &&
4673 (extent <= MagickMaxBufferExtent))
4678 for (y=0; y < (ssize_t) rows; y++)
4680 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4681 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4682 sizeof(*q),length,(
unsigned char *) q);
4683 if (count != (MagickOffsetType) length)
4685 offset+=(MagickOffsetType) cache_info->columns;
4686 q+=cache_info->number_channels*nexus_info->region.width;
4688 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4689 (void) ClosePixelCacheOnDisk(cache_info);
4690 UnlockSemaphoreInfo(cache_info->file_semaphore);
4693 case DistributedCache:
4701 LockSemaphoreInfo(cache_info->file_semaphore);
4702 region=nexus_info->region;
4703 if ((cache_info->columns != nexus_info->region.width) ||
4704 (extent > MagickMaxBufferExtent))
4711 for (y=0; y < (ssize_t) rows; y++)
4714 cache_info->server_info,®ion,length,(
unsigned char *) q);
4715 if (count != (MagickOffsetType) length)
4717 q+=cache_info->number_channels*nexus_info->region.width;
4720 UnlockSemaphoreInfo(cache_info->file_semaphore);
4726 if (y < (ssize_t) rows)
4728 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4729 cache_info->cache_filename);
4730 return(MagickFalse);
4732 if ((cache_info->debug != MagickFalse) &&
4733 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4734 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4735 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4736 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4737 nexus_info->region.x,(
double) nexus_info->region.y);
4764MagickPrivate Cache ReferencePixelCache(Cache cache)
4767 *magick_restrict cache_info;
4769 assert(cache != (Cache *) NULL);
4771 assert(cache_info->signature == MagickCoreSignature);
4772 LockSemaphoreInfo(cache_info->semaphore);
4773 cache_info->reference_count++;
4774 UnlockSemaphoreInfo(cache_info->semaphore);
4800MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4803 *magick_restrict cache_info;
4805 assert(image != (
const Image *) NULL);
4806 assert(image->signature == MagickCoreSignature);
4807 assert(image->cache != (Cache) NULL);
4809 assert(cache_info->signature == MagickCoreSignature);
4810 cache_info->number_channels=GetPixelChannels(image);
4831MagickPrivate
void ResetCacheAnonymousMemory(
void)
4833 cache_anonymous_memory=0;
4865MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4866 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4874 assert(image != (
Image *) NULL);
4875 assert(image->signature == MagickCoreSignature);
4876 if (IsEventLogging() != MagickFalse)
4877 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4878 assert(image->cache != (
void *) NULL);
4879 extent=(MagickSizeType) columns*rows;
4880 if (extent > ((MagickSizeType) image->columns*image->rows))
4881 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4883 image->columns=columns;
4886 cache_info->columns=columns;
4887 cache_info->rows=rows;
4888 return(SyncImagePixelCache(image,exception));
4915MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4918 *magick_restrict cache_info;
4920 GetOneAuthenticPixelFromHandler
4921 get_one_authentic_pixel_from_handler;
4923 GetOneVirtualPixelFromHandler
4924 get_one_virtual_pixel_from_handler;
4929 assert(cache != (Cache) NULL);
4932 assert(cache_info->signature == MagickCoreSignature);
4933 if (IsEventLogging() != MagickFalse)
4934 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4935 cache_info->filename);
4936 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4937 cache_info->methods.get_virtual_pixel_handler=
4938 cache_methods->get_virtual_pixel_handler;
4939 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4940 cache_info->methods.destroy_pixel_handler=
4941 cache_methods->destroy_pixel_handler;
4942 if (cache_methods->get_virtual_metacontent_from_handler !=
4943 (GetVirtualMetacontentFromHandler) NULL)
4944 cache_info->methods.get_virtual_metacontent_from_handler=
4945 cache_methods->get_virtual_metacontent_from_handler;
4946 if (cache_methods->get_authentic_pixels_handler !=
4947 (GetAuthenticPixelsHandler) NULL)
4948 cache_info->methods.get_authentic_pixels_handler=
4949 cache_methods->get_authentic_pixels_handler;
4950 if (cache_methods->queue_authentic_pixels_handler !=
4951 (QueueAuthenticPixelsHandler) NULL)
4952 cache_info->methods.queue_authentic_pixels_handler=
4953 cache_methods->queue_authentic_pixels_handler;
4954 if (cache_methods->sync_authentic_pixels_handler !=
4955 (SyncAuthenticPixelsHandler) NULL)
4956 cache_info->methods.sync_authentic_pixels_handler=
4957 cache_methods->sync_authentic_pixels_handler;
4958 if (cache_methods->get_authentic_pixels_from_handler !=
4959 (GetAuthenticPixelsFromHandler) NULL)
4960 cache_info->methods.get_authentic_pixels_from_handler=
4961 cache_methods->get_authentic_pixels_from_handler;
4962 if (cache_methods->get_authentic_metacontent_from_handler !=
4963 (GetAuthenticMetacontentFromHandler) NULL)
4964 cache_info->methods.get_authentic_metacontent_from_handler=
4965 cache_methods->get_authentic_metacontent_from_handler;
4966 get_one_virtual_pixel_from_handler=
4967 cache_info->methods.get_one_virtual_pixel_from_handler;
4968 if (get_one_virtual_pixel_from_handler !=
4969 (GetOneVirtualPixelFromHandler) NULL)
4970 cache_info->methods.get_one_virtual_pixel_from_handler=
4971 cache_methods->get_one_virtual_pixel_from_handler;
4972 get_one_authentic_pixel_from_handler=
4973 cache_methods->get_one_authentic_pixel_from_handler;
4974 if (get_one_authentic_pixel_from_handler !=
4975 (GetOneAuthenticPixelFromHandler) NULL)
4976 cache_info->methods.get_one_authentic_pixel_from_handler=
4977 cache_methods->get_one_authentic_pixel_from_handler;
5018static inline MagickBooleanType AcquireCacheNexusPixels(
5019 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5022 if (length != (MagickSizeType) ((
size_t) length))
5024 (void) ThrowMagickException(exception,GetMagickModule(),
5025 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5026 cache_info->filename);
5027 return(MagickFalse);
5029 nexus_info->length=0;
5030 nexus_info->mapped=MagickFalse;
5031 if (cache_anonymous_memory <= 0)
5033 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5035 if (nexus_info->cache != (Quantum *) NULL)
5036 (
void) memset(nexus_info->cache,0,(
size_t) length);
5040 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5041 if (nexus_info->cache != (Quantum *) NULL)
5042 nexus_info->mapped=MagickTrue;
5044 if (nexus_info->cache == (Quantum *) NULL)
5046 (void) ThrowMagickException(exception,GetMagickModule(),
5047 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5048 cache_info->filename);
5049 return(MagickFalse);
5051 nexus_info->length=length;
5055static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5058 if (nexus_info->length < CACHE_LINE_SIZE)
5060 if (mode == ReadMode)
5062 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5066 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5069static Quantum *SetPixelCacheNexusPixels(
5070 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5071 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5072 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5082 assert(cache_info != (
const CacheInfo *) NULL);
5083 assert(cache_info->signature == MagickCoreSignature);
5084 if (cache_info->type == UndefinedCache)
5085 return((Quantum *) NULL);
5086 assert(nexus_info->signature == MagickCoreSignature);
5087 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5088 if ((width == 0) || (height == 0))
5090 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5091 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5092 return((Quantum *) NULL);
5094 if (((MagickSizeType) width > cache_info->width_limit) ||
5095 ((MagickSizeType) height > cache_info->height_limit))
5097 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5098 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5099 return((Quantum *) NULL);
5101 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5102 (IsValidPixelOffset(y,height) == MagickFalse))
5104 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5105 "InvalidPixel",
"`%s'",cache_info->filename);
5106 return((Quantum *) NULL);
5108 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5109 (buffered == MagickFalse))
5111 if (((x >= 0) && (y >= 0) &&
5112 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5113 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5114 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5122 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5123 return((Quantum *) NULL);
5124 offset=y*(MagickOffsetType) cache_info->columns+x;
5125 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5126 cache_info->number_channels*offset;
5127 nexus_info->metacontent=(
void *) NULL;
5128 if (cache_info->metacontent_extent != 0)
5129 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5130 offset*(MagickOffsetType) cache_info->metacontent_extent;
5131 nexus_info->region.width=width;
5132 nexus_info->region.height=height;
5133 nexus_info->region.x=x;
5134 nexus_info->region.y=y;
5135 nexus_info->authentic_pixel_cache=MagickTrue;
5136 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5137 return(nexus_info->pixels);
5143 number_pixels=(MagickSizeType) width*height;
5144 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5145 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5146 if (cache_info->metacontent_extent != 0)
5147 length+=number_pixels*cache_info->metacontent_extent;
5149 if (nexus_info->cache == (Quantum *) NULL)
5150 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5152 if (nexus_info->length < length)
5154 RelinquishCacheNexusPixels(nexus_info);
5155 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5157 if (status == MagickFalse)
5158 return((Quantum *) NULL);
5159 nexus_info->pixels=nexus_info->cache;
5160 nexus_info->metacontent=(
void *) NULL;
5161 if (cache_info->metacontent_extent != 0)
5162 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5163 cache_info->number_channels*number_pixels);
5164 nexus_info->region.width=width;
5165 nexus_info->region.height=height;
5166 nexus_info->region.x=x;
5167 nexus_info->region.y=y;
5168 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5169 MagickTrue : MagickFalse;
5170 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5171 return(nexus_info->pixels);
5204static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5208 *magick_restrict image_view;
5216 assert(image != (
Image *) NULL);
5217 assert(image->signature == MagickCoreSignature);
5218 if (IsEventLogging() != MagickFalse)
5219 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5220 assert(image->cache != (Cache) NULL);
5221 image->alpha_trait=BlendPixelTrait;
5223 image_view=AcquireVirtualCacheView(image,exception);
5224#if defined(MAGICKCORE_OPENMP_SUPPORT)
5225 #pragma omp parallel for schedule(static) shared(status) \
5226 magick_number_threads(image,image,image->rows,2)
5228 for (y=0; y < (ssize_t) image->rows; y++)
5236 if (status == MagickFalse)
5238 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5239 if (q == (Quantum *) NULL)
5244 for (x=0; x < (ssize_t) image->columns; x++)
5246 SetPixelAlpha(image,alpha,q);
5247 q+=GetPixelChannels(image);
5249 status=SyncCacheViewAuthenticPixels(image_view,exception);
5251 image_view=DestroyCacheView(image_view);
5255MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5256 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5259 *magick_restrict cache_info;
5264 assert(image != (
Image *) NULL);
5265 assert(image->signature == MagickCoreSignature);
5266 if (IsEventLogging() != MagickFalse)
5267 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5268 assert(image->cache != (Cache) NULL);
5270 assert(cache_info->signature == MagickCoreSignature);
5271 method=cache_info->virtual_pixel_method;
5272 cache_info->virtual_pixel_method=virtual_pixel_method;
5273 if ((image->columns != 0) && (image->rows != 0))
5274 switch (virtual_pixel_method)
5276 case BackgroundVirtualPixelMethod:
5278 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5279 ((image->alpha_trait & BlendPixelTrait) == 0))
5280 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5281 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5282 (IsGrayColorspace(image->colorspace) != MagickFalse))
5283 (void) SetImageColorspace(image,sRGBColorspace,exception);
5286 case TransparentVirtualPixelMethod:
5288 if ((image->alpha_trait & BlendPixelTrait) == 0)
5289 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5298#if defined(MAGICKCORE_OPENCL_SUPPORT)
5323static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5325 assert(cache_info != (
CacheInfo *) NULL);
5326 assert(cache_info->signature == MagickCoreSignature);
5327 if ((cache_info->type != MemoryCache) ||
5328 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5333 LockSemaphoreInfo(cache_info->semaphore);
5334 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5335 UnlockSemaphoreInfo(cache_info->semaphore);
5338MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5341 *magick_restrict cache_info;
5343 assert(image != (
const Image *) NULL);
5345 CopyOpenCLBuffer(cache_info);
5378MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5382 *magick_restrict cache_info;
5390 assert(image != (
Image *) NULL);
5391 assert(image->signature == MagickCoreSignature);
5392 if (image->cache == (Cache) NULL)
5393 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5395 assert(cache_info->signature == MagickCoreSignature);
5396 if (cache_info->type == UndefinedCache)
5397 return(MagickFalse);
5398 if (image->mask_trait != UpdatePixelTrait)
5400 if (((image->channels & WriteMaskChannel) != 0) &&
5401 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5402 return(MagickFalse);
5403 if (((image->channels & CompositeMaskChannel) != 0) &&
5404 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5405 return(MagickFalse);
5407 if (nexus_info->authentic_pixel_cache != MagickFalse)
5409 if (image->taint == MagickFalse)
5410 image->taint=MagickTrue;
5413 assert(cache_info->signature == MagickCoreSignature);
5414 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5415 if ((cache_info->metacontent_extent != 0) &&
5416 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5417 return(MagickFalse);
5418 if ((status != MagickFalse) && (image->taint == MagickFalse))
5419 image->taint=MagickTrue;
5450static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5454 *magick_restrict cache_info;
5457 id = GetOpenMPThreadId();
5462 assert(image != (
Image *) NULL);
5463 assert(image->signature == MagickCoreSignature);
5464 assert(image->cache != (Cache) NULL);
5466 assert(cache_info->signature == MagickCoreSignature);
5467 assert(
id < (
int) cache_info->number_threads);
5468 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5500MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5504 *magick_restrict cache_info;
5507 id = GetOpenMPThreadId();
5512 assert(image != (
Image *) NULL);
5513 assert(image->signature == MagickCoreSignature);
5514 assert(image->cache != (Cache) NULL);
5516 assert(cache_info->signature == MagickCoreSignature);
5517 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5519 status=cache_info->methods.sync_authentic_pixels_handler(image,
5523 assert(
id < (
int) cache_info->number_threads);
5524 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5556MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5560 *magick_restrict cache_info;
5562 assert(image != (
Image *) NULL);
5564 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5565 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5596static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5616 if (cache_info->metacontent_extent == 0)
5617 return(MagickFalse);
5618 if (nexus_info->authentic_pixel_cache != MagickFalse)
5620 if (nexus_info->metacontent == (
unsigned char *) NULL)
5621 return(MagickFalse);
5622 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5623 return(MagickFalse);
5624 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5625 nexus_info->region.x;
5626 length=(MagickSizeType) nexus_info->region.width*
5627 cache_info->metacontent_extent;
5628 extent=(MagickSizeType) length*nexus_info->region.height;
5629 rows=nexus_info->region.height;
5631 p=(
unsigned char *) nexus_info->metacontent;
5632 switch (cache_info->type)
5643 if ((cache_info->columns == nexus_info->region.width) &&
5644 (extent == (MagickSizeType) ((
size_t) extent)))
5649 q=(
unsigned char *) cache_info->metacontent+offset*
5650 (MagickOffsetType) cache_info->metacontent_extent;
5651 for (y=0; y < (ssize_t) rows; y++)
5653 (void) memcpy(q,p,(
size_t) length);
5654 p+=nexus_info->region.width*cache_info->metacontent_extent;
5655 q+=cache_info->columns*cache_info->metacontent_extent;
5664 LockSemaphoreInfo(cache_info->file_semaphore);
5665 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5667 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5668 cache_info->cache_filename);
5669 UnlockSemaphoreInfo(cache_info->file_semaphore);
5670 return(MagickFalse);
5672 if ((cache_info->columns == nexus_info->region.width) &&
5673 (extent <= MagickMaxBufferExtent))
5678 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5679 for (y=0; y < (ssize_t) rows; y++)
5681 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5682 (MagickOffsetType) extent*(MagickOffsetType)
5683 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5684 (MagickOffsetType) cache_info->metacontent_extent,length,
5685 (
const unsigned char *) p);
5686 if (count != (MagickOffsetType) length)
5688 p+=cache_info->metacontent_extent*nexus_info->region.width;
5689 offset+=(MagickOffsetType) cache_info->columns;
5691 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5692 (void) ClosePixelCacheOnDisk(cache_info);
5693 UnlockSemaphoreInfo(cache_info->file_semaphore);
5696 case DistributedCache:
5704 LockSemaphoreInfo(cache_info->file_semaphore);
5705 region=nexus_info->region;
5706 if ((cache_info->columns != nexus_info->region.width) ||
5707 (extent > MagickMaxBufferExtent))
5714 for (y=0; y < (ssize_t) rows; y++)
5717 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5718 if (count != (MagickOffsetType) length)
5720 p+=cache_info->metacontent_extent*nexus_info->region.width;
5723 UnlockSemaphoreInfo(cache_info->file_semaphore);
5729 if (y < (ssize_t) rows)
5731 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5732 cache_info->cache_filename);
5733 return(MagickFalse);
5735 if ((cache_info->debug != MagickFalse) &&
5736 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5737 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5738 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5739 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5740 nexus_info->region.x,(
double) nexus_info->region.y);
5772static MagickBooleanType WritePixelCachePixels(
5793 if (nexus_info->authentic_pixel_cache != MagickFalse)
5795 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5796 return(MagickFalse);
5797 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5798 nexus_info->region.x;
5799 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5801 extent=length*nexus_info->region.height;
5802 rows=nexus_info->region.height;
5804 p=nexus_info->pixels;
5805 switch (cache_info->type)
5816 if ((cache_info->columns == nexus_info->region.width) &&
5817 (extent == (MagickSizeType) ((
size_t) extent)))
5822 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5824 for (y=0; y < (ssize_t) rows; y++)
5826 (void) memcpy(q,p,(
size_t) length);
5827 p+=cache_info->number_channels*nexus_info->region.width;
5828 q+=cache_info->number_channels*cache_info->columns;
5837 LockSemaphoreInfo(cache_info->file_semaphore);
5838 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5840 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5841 cache_info->cache_filename);
5842 UnlockSemaphoreInfo(cache_info->file_semaphore);
5843 return(MagickFalse);
5845 if ((cache_info->columns == nexus_info->region.width) &&
5846 (extent <= MagickMaxBufferExtent))
5851 for (y=0; y < (ssize_t) rows; y++)
5853 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5854 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5855 sizeof(*p),length,(
const unsigned char *) p);
5856 if (count != (MagickOffsetType) length)
5858 p+=cache_info->number_channels*nexus_info->region.width;
5859 offset+=(MagickOffsetType) cache_info->columns;
5861 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5862 (void) ClosePixelCacheOnDisk(cache_info);
5863 UnlockSemaphoreInfo(cache_info->file_semaphore);
5866 case DistributedCache:
5874 LockSemaphoreInfo(cache_info->file_semaphore);
5875 region=nexus_info->region;
5876 if ((cache_info->columns != nexus_info->region.width) ||
5877 (extent > MagickMaxBufferExtent))
5884 for (y=0; y < (ssize_t) rows; y++)
5887 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5888 if (count != (MagickOffsetType) length)
5890 p+=cache_info->number_channels*nexus_info->region.width;
5893 UnlockSemaphoreInfo(cache_info->file_semaphore);
5899 if (y < (ssize_t) rows)
5901 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5902 cache_info->cache_filename);
5903 return(MagickFalse);
5905 if ((cache_info->debug != MagickFalse) &&
5906 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5907 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5908 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5909 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5910 nexus_info->region.x,(
double) nexus_info->region.y);