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+=(ptrdiff_t) GetPixelChannels(image);
476 q+=(ptrdiff_t) 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+=(ptrdiff_t) 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_utf8(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+=(ptrdiff_t) 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+=(ptrdiff_t) 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+=(ptrdiff_t) cache_info->number_channels*length;
3093 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3095 (void) memcpy(s,r,(
size_t) length);
3096 s+=(ptrdiff_t) 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+=(ptrdiff_t) GetPixelChannels(image);
3466 q+=(ptrdiff_t) GetPixelChannels(image);
3503static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3504 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3509 if ((count == 0) || (quantum == 0))
3511 length=count*quantum;
3512 if (quantum != (length/count))
3519 return(MagickFalse);
3522static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3531 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3533 if (*cache_info->cache_filename ==
'\0')
3534 file=AcquireUniqueFileResource(cache_info->cache_filename);
3540 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3545 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3546 O_BINARY | O_EXCL,S_MODE);
3548 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3554 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3557 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3562 return(MagickFalse);
3563 (void) AcquireMagickResource(FileResource,1);
3564 if (cache_info->file != -1)
3565 (void) ClosePixelCacheOnDisk(cache_info);
3566 cache_info->file=file;
3567 cache_info->disk_mode=mode;
3571static inline MagickOffsetType WritePixelCacheRegion(
3572 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3573 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3581#if !defined(MAGICKCORE_HAVE_PWRITE)
3582 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3583 return((MagickOffsetType) -1);
3585 for (i=0; i < (MagickOffsetType) length; i+=count)
3587#if !defined(MAGICKCORE_HAVE_PWRITE)
3588 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3589 (MagickSizeType) i,MagickMaxBufferExtent));
3591 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3592 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3604static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3607 *magick_restrict cache_info;
3613 if (cache_info->debug != MagickFalse)
3616 format[MagickPathExtent],
3617 message[MagickPathExtent];
3619 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3620 (void) FormatLocaleString(message,MagickPathExtent,
3621 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3622 cache_info->cache_filename,cache_info->file,format);
3623 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3625 if (length != (MagickSizeType) ((MagickOffsetType) length))
3626 return(MagickFalse);
3627 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3629 return(MagickFalse);
3630 if ((MagickSizeType) offset < length)
3636 extent=(MagickOffsetType) length-1;
3637 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3640 return(MagickFalse);
3641#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3642 if (cache_info->synchronize != MagickFalse)
3643 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3644 return(MagickFalse);
3647 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3649 return(MagickFalse);
3653static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3657 *magick_restrict cache_info,
3661 format[MagickPathExtent],
3662 message[MagickPathExtent];
3679 assert(image != (
const Image *) NULL);
3680 assert(image->signature == MagickCoreSignature);
3681 assert(image->cache != (Cache) NULL);
3682 if (IsEventLogging() != MagickFalse)
3683 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3684 if (cache_anonymous_memory < 0)
3692 cache_anonymous_memory=0;
3693 value=GetPolicyValue(
"pixel-cache-memory");
3694 if (value == (
char *) NULL)
3695 value=GetPolicyValue(
"cache:memory-map");
3696 if (LocaleCompare(value,
"anonymous") == 0)
3698#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3699 cache_anonymous_memory=1;
3701 (void) ThrowMagickException(exception,GetMagickModule(),
3702 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3703 "'%s' (policy requires anonymous memory mapping)",image->filename);
3706 value=DestroyString(value);
3708 if ((image->columns == 0) || (image->rows == 0))
3709 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3711 assert(cache_info->signature == MagickCoreSignature);
3712 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3713 ((MagickSizeType) image->rows > cache_info->height_limit))
3714 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3716 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3718 length=GetImageListLength(image);
3719 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3720 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3723 source_info=(*cache_info);
3724 source_info.file=(-1);
3725 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3726 image->filename,(
double) image->scene);
3727 cache_info->storage_class=image->storage_class;
3728 cache_info->colorspace=image->colorspace;
3729 cache_info->alpha_trait=image->alpha_trait;
3730 cache_info->channels=image->channels;
3731 cache_info->rows=image->rows;
3732 cache_info->columns=image->columns;
3733 status=ResetPixelChannelMap(image,exception);
3734 if (status == MagickFalse)
3735 return(MagickFalse);
3736 cache_info->number_channels=GetPixelChannels(image);
3737 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3738 sizeof(*image->channel_map));
3739 cache_info->metacontent_extent=image->metacontent_extent;
3740 cache_info->mode=mode;
3741 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3742 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3743 if (cache_info->metacontent_extent != 0)
3745 if (HeapOverflowCheckAdd(packet_size,cache_info->metacontent_extent) != MagickFalse)
3747 cache_info->storage_class=UndefinedClass;
3748 cache_info->length=0;
3749 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3752 packet_size+=cache_info->metacontent_extent;
3754 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3756 cache_info->storage_class=UndefinedClass;
3757 cache_info->length=0;
3758 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3761 columns=(size_t) (length/cache_info->rows/packet_size);
3762 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3763 ((ssize_t) cache_info->rows < 0))
3765 cache_info->storage_class=UndefinedClass;
3766 cache_info->length=0;
3767 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3770 cache_info->length=length;
3771 if (image->ping != MagickFalse)
3773 cache_info->type=PingCache;
3776 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3777 cache_info->columns*cache_info->rows);
3778 if (cache_info->mode == PersistMode)
3780 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3781 cache_info->metacontent_extent);
3782 if ((status != MagickFalse) &&
3783 (length == (MagickSizeType) ((
size_t) length)) &&
3784 ((cache_info->type == UndefinedCache) ||
3785 (cache_info->type == MemoryCache)))
3787 status=AcquireMagickResource(MemoryResource,cache_info->length);
3788 if (status != MagickFalse)
3791 if (cache_anonymous_memory <= 0)
3793 cache_info->mapped=MagickFalse;
3794 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3795 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3799 cache_info->mapped=MagickTrue;
3800 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3801 cache_info->length);
3803 if (cache_info->pixels == (Quantum *) NULL)
3805 RelinquishMagickResource(MemoryResource,cache_info->length);
3806 cache_info->mapped=source_info.mapped;
3807 cache_info->pixels=source_info.pixels;
3814 cache_info->type=MemoryCache;
3815 cache_info->metacontent=(
void *) NULL;
3816 if (cache_info->metacontent_extent != 0)
3817 cache_info->metacontent=(
void *) (cache_info->pixels+
3818 cache_info->number_channels*number_pixels);
3819 if ((source_info.storage_class != UndefinedClass) &&
3822 status=ClonePixelCacheRepository(cache_info,&source_info,
3824 RelinquishPixelCachePixels(&source_info);
3826 if (cache_info->debug != MagickFalse)
3828 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3829 MagickPathExtent,format);
3830 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3832 (void) FormatLocaleString(message,MagickPathExtent,
3833 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3834 cache_info->filename,cache_info->mapped != MagickFalse ?
3835 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3836 (double) cache_info->rows,(double)
3837 cache_info->number_channels,format);
3838 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3841 cache_info->storage_class=image->storage_class;
3844 if ((source_info.storage_class != UndefinedClass) &&
3846 RelinquishPixelCachePixels(&source_info);
3847 cache_info->type=UndefinedCache;
3848 return(MagickFalse);
3854 status=AcquireMagickResource(DiskResource,cache_info->length);
3855 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3857 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3865 server_info=AcquireDistributeCacheInfo(exception);
3868 status=OpenDistributePixelCache(server_info,image);
3869 if (status == MagickFalse)
3871 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3872 GetDistributeCacheHostname(server_info));
3873 server_info=DestroyDistributeCacheInfo(server_info);
3881 cache_info->type=DistributedCache;
3882 cache_info->server_info=server_info;
3883 (void) FormatLocaleString(cache_info->cache_filename,
3884 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3887 cache_info->server_info));
3888 if ((source_info.storage_class != UndefinedClass) &&
3891 status=ClonePixelCacheRepository(cache_info,&source_info,
3893 RelinquishPixelCachePixels(&source_info);
3895 if (cache_info->debug != MagickFalse)
3897 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3898 MagickPathExtent,format);
3899 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3901 (void) FormatLocaleString(message,MagickPathExtent,
3902 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3903 cache_info->filename,cache_info->cache_filename,
3905 cache_info->server_info),type,(double) cache_info->columns,
3906 (
double) cache_info->rows,(double)
3907 cache_info->number_channels,format);
3908 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3913 if ((source_info.storage_class != UndefinedClass) &&
3915 RelinquishPixelCachePixels(&source_info);
3916 cache_info->type=UndefinedCache;
3917 return(MagickFalse);
3922 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3923 RelinquishPixelCachePixels(&source_info);
3924 cache_info->type=UndefinedCache;
3925 (void) memset(image->channel_map,0,MaxPixelChannels*
3926 sizeof(*image->channel_map));
3927 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3928 "CacheResourcesExhausted",
"`%s'",image->filename);
3929 return(MagickFalse);
3934 if (status == MagickFalse)
3936 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3937 RelinquishPixelCachePixels(&source_info);
3938 cache_info->type=UndefinedCache;
3939 (void) memset(image->channel_map,0,MaxPixelChannels*
3940 sizeof(*image->channel_map));
3941 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3942 "CacheResourcesExhausted",
"`%s'",image->filename);
3943 return(MagickFalse);
3945 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3946 (cache_info->mode != PersistMode))
3948 (void) ClosePixelCacheOnDisk(cache_info);
3949 *cache_info->cache_filename=
'\0';
3951 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3953 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3954 RelinquishPixelCachePixels(&source_info);
3955 cache_info->type=UndefinedCache;
3956 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3958 return(MagickFalse);
3960 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3961 cache_info->length);
3962 if (status == MagickFalse)
3964 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3965 RelinquishPixelCachePixels(&source_info);
3966 cache_info->type=UndefinedCache;
3967 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3969 return(MagickFalse);
3971 cache_info->type=DiskCache;
3972 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3973 cache_info->metacontent_extent);
3974 if (length == (MagickSizeType) ((
size_t) length))
3976 status=AcquireMagickResource(MapResource,cache_info->length);
3977 if (status != MagickFalse)
3979 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3980 cache_info->offset,(
size_t) cache_info->length);
3981 if (cache_info->pixels == (Quantum *) NULL)
3983 cache_info->mapped=source_info.mapped;
3984 cache_info->pixels=source_info.pixels;
3985 RelinquishMagickResource(MapResource,cache_info->length);
3992 (void) ClosePixelCacheOnDisk(cache_info);
3993 cache_info->type=MapCache;
3994 cache_info->mapped=MagickTrue;
3995 cache_info->metacontent=(
void *) NULL;
3996 if (cache_info->metacontent_extent != 0)
3997 cache_info->metacontent=(
void *) (cache_info->pixels+
3998 cache_info->number_channels*number_pixels);
3999 if ((source_info.storage_class != UndefinedClass) &&
4002 status=ClonePixelCacheRepository(cache_info,&source_info,
4004 RelinquishPixelCachePixels(&source_info);
4006 if (cache_info->debug != MagickFalse)
4008 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
4009 MagickPathExtent,format);
4010 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4012 (void) FormatLocaleString(message,MagickPathExtent,
4013 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4014 cache_info->filename,cache_info->cache_filename,
4015 cache_info->file,type,(
double) cache_info->columns,
4016 (double) cache_info->rows,(
double)
4017 cache_info->number_channels,format);
4018 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4023 if ((source_info.storage_class != UndefinedClass) &&
4025 RelinquishPixelCachePixels(&source_info);
4026 cache_info->type=UndefinedCache;
4027 return(MagickFalse);
4034 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4036 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4037 RelinquishPixelCachePixels(&source_info);
4039 if (cache_info->debug != MagickFalse)
4041 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4042 MagickPathExtent,format);
4043 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4045 (void) FormatLocaleString(message,MagickPathExtent,
4046 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4047 cache_info->cache_filename,cache_info->file,type,(
double)
4048 cache_info->columns,(double) cache_info->rows,(
double)
4049 cache_info->number_channels,format);
4050 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4054 cache_info->type=UndefinedCache;
4055 return(MagickFalse);
4097MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4098 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4102 *magick_restrict cache_info,
4103 *magick_restrict clone_info;
4111 assert(image != (
Image *) NULL);
4112 assert(image->signature == MagickCoreSignature);
4113 if (IsEventLogging() != MagickFalse)
4114 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4115 assert(image->cache != (
void *) NULL);
4116 assert(filename != (
const char *) NULL);
4117 assert(offset != (MagickOffsetType *) NULL);
4118 page_size=GetMagickPageSize();
4120 assert(cache_info->signature == MagickCoreSignature);
4121#if defined(MAGICKCORE_OPENCL_SUPPORT)
4122 CopyOpenCLBuffer(cache_info);
4124 if (attach != MagickFalse)
4129 if (cache_info->debug != MagickFalse)
4130 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4131 "attach persistent cache");
4132 (void) CopyMagickString(cache_info->cache_filename,filename,
4134 cache_info->type=MapCache;
4135 cache_info->offset=(*offset);
4136 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4137 return(MagickFalse);
4138 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4139 ((MagickOffsetType) cache_info->length % page_size));
4145 status=AcquireMagickResource(DiskResource,cache_info->length);
4146 if (status == MagickFalse)
4148 cache_info->type=UndefinedCache;
4149 (void) memset(image->channel_map,0,MaxPixelChannels*
4150 sizeof(*image->channel_map));
4151 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4152 "CacheResourcesExhausted",
"`%s'",image->filename);
4153 return(MagickFalse);
4155 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4156 clone_info->type=DiskCache;
4157 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4158 clone_info->file=(-1);
4159 clone_info->storage_class=cache_info->storage_class;
4160 clone_info->colorspace=cache_info->colorspace;
4161 clone_info->alpha_trait=cache_info->alpha_trait;
4162 clone_info->channels=cache_info->channels;
4163 clone_info->columns=cache_info->columns;
4164 clone_info->rows=cache_info->rows;
4165 clone_info->number_channels=cache_info->number_channels;
4166 clone_info->metacontent_extent=cache_info->metacontent_extent;
4167 clone_info->mode=PersistMode;
4168 clone_info->length=cache_info->length;
4169 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4170 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4171 clone_info->offset=(*offset);
4172 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4173 if (status != MagickFalse)
4174 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4175 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4176 ((MagickOffsetType) cache_info->length % page_size));
4177 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4219MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4220 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4224 *magick_restrict cache_info;
4233 *magick_restrict pixels;
4238 assert(image != (
const Image *) NULL);
4239 assert(image->signature == MagickCoreSignature);
4240 assert(image->cache != (Cache) NULL);
4241 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4242 if (cache_info == (Cache) NULL)
4243 return((Quantum *) NULL);
4244 assert(cache_info->signature == MagickCoreSignature);
4245 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4246 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4247 (y >= (ssize_t) cache_info->rows))
4249 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4250 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4251 return((Quantum *) NULL);
4253 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4254 return((Quantum *) NULL);
4255 offset=y*(MagickOffsetType) cache_info->columns+x;
4257 return((Quantum *) NULL);
4258 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4259 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4260 (MagickOffsetType) columns-1;
4261 if ((MagickSizeType) offset >= number_pixels)
4262 return((Quantum *) NULL);
4266 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4267 ((image->channels & WriteMaskChannel) != 0) ||
4268 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4269 nexus_info,exception);
4306static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4307 const ssize_t y,
const size_t columns,
const size_t rows,
4311 *magick_restrict cache_info;
4314 id = GetOpenMPThreadId();
4317 *magick_restrict pixels;
4319 assert(image != (
const Image *) NULL);
4320 assert(image->signature == MagickCoreSignature);
4321 assert(image->cache != (Cache) NULL);
4323 assert(cache_info->signature == MagickCoreSignature);
4324 assert(
id < (
int) cache_info->number_threads);
4325 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4326 cache_info->nexus_info[
id],exception);
4386MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4387 const ssize_t y,
const size_t columns,
const size_t rows,
4391 *magick_restrict cache_info;
4394 id = GetOpenMPThreadId();
4397 *magick_restrict pixels;
4399 assert(image != (
Image *) NULL);
4400 assert(image->signature == MagickCoreSignature);
4401 assert(image->cache != (Cache) NULL);
4403 assert(cache_info->signature == MagickCoreSignature);
4404 if (cache_info->methods.queue_authentic_pixels_handler !=
4405 (QueueAuthenticPixelsHandler) NULL)
4407 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4408 columns,rows,exception);
4411 assert(
id < (
int) cache_info->number_threads);
4412 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4413 cache_info->nexus_info[
id],exception);
4446static inline MagickOffsetType ReadPixelCacheRegion(
4447 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4448 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4456#if !defined(MAGICKCORE_HAVE_PREAD)
4457 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4458 return((MagickOffsetType) -1);
4460 for (i=0; i < (MagickOffsetType) length; i+=count)
4462#if !defined(MAGICKCORE_HAVE_PREAD)
4463 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4464 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4466 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4467 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4479static MagickBooleanType ReadPixelCacheMetacontent(
4500 if (cache_info->metacontent_extent == 0)
4501 return(MagickFalse);
4502 if (nexus_info->authentic_pixel_cache != MagickFalse)
4504 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4505 return(MagickFalse);
4506 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4507 nexus_info->region.x;
4508 length=(MagickSizeType) nexus_info->region.width*
4509 cache_info->metacontent_extent;
4510 extent=length*nexus_info->region.height;
4511 rows=nexus_info->region.height;
4513 q=(
unsigned char *) nexus_info->metacontent;
4514 switch (cache_info->type)
4525 if ((cache_info->columns == nexus_info->region.width) &&
4526 (extent == (MagickSizeType) ((
size_t) extent)))
4531 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4532 cache_info->metacontent_extent;
4533 for (y=0; y < (ssize_t) rows; y++)
4535 (void) memcpy(q,p,(
size_t) length);
4536 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4537 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4546 LockSemaphoreInfo(cache_info->file_semaphore);
4547 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4549 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4550 cache_info->cache_filename);
4551 UnlockSemaphoreInfo(cache_info->file_semaphore);
4552 return(MagickFalse);
4554 if ((cache_info->columns == nexus_info->region.width) &&
4555 (extent <= MagickMaxBufferExtent))
4560 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4561 for (y=0; y < (ssize_t) rows; y++)
4563 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4564 (MagickOffsetType) extent*(MagickOffsetType)
4565 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4566 (MagickOffsetType) cache_info->metacontent_extent,length,
4567 (
unsigned char *) q);
4568 if (count != (MagickOffsetType) length)
4570 offset+=(MagickOffsetType) cache_info->columns;
4571 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4573 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4574 (void) ClosePixelCacheOnDisk(cache_info);
4575 UnlockSemaphoreInfo(cache_info->file_semaphore);
4578 case DistributedCache:
4586 LockSemaphoreInfo(cache_info->file_semaphore);
4587 region=nexus_info->region;
4588 if ((cache_info->columns != nexus_info->region.width) ||
4589 (extent > MagickMaxBufferExtent))
4596 for (y=0; y < (ssize_t) rows; y++)
4599 cache_info->server_info,®ion,length,(
unsigned char *) q);
4600 if (count != (MagickOffsetType) length)
4602 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4605 UnlockSemaphoreInfo(cache_info->file_semaphore);
4611 if (y < (ssize_t) rows)
4613 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4614 cache_info->cache_filename);
4615 return(MagickFalse);
4617 if ((cache_info->debug != MagickFalse) &&
4618 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4619 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4620 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4621 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4622 nexus_info->region.x,(
double) nexus_info->region.y);
4654static MagickBooleanType ReadPixelCachePixels(
4676 if (nexus_info->authentic_pixel_cache != MagickFalse)
4678 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4679 return(MagickFalse);
4680 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4681 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4682 return(MagickFalse);
4683 offset+=nexus_info->region.x;
4684 number_channels=cache_info->number_channels;
4685 length=(MagickSizeType) number_channels*nexus_info->region.width*
4687 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4688 return(MagickFalse);
4689 rows=nexus_info->region.height;
4691 if ((extent == 0) || ((extent/length) != rows))
4692 return(MagickFalse);
4694 q=nexus_info->pixels;
4695 switch (cache_info->type)
4706 if ((cache_info->columns == nexus_info->region.width) &&
4707 (extent == (MagickSizeType) ((
size_t) extent)))
4712 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4714 for (y=0; y < (ssize_t) rows; y++)
4716 (void) memcpy(q,p,(
size_t) length);
4717 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4718 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4727 LockSemaphoreInfo(cache_info->file_semaphore);
4728 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4730 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4731 cache_info->cache_filename);
4732 UnlockSemaphoreInfo(cache_info->file_semaphore);
4733 return(MagickFalse);
4735 if ((cache_info->columns == nexus_info->region.width) &&
4736 (extent <= MagickMaxBufferExtent))
4741 for (y=0; y < (ssize_t) rows; y++)
4743 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4744 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4745 sizeof(*q),length,(
unsigned char *) q);
4746 if (count != (MagickOffsetType) length)
4748 offset+=(MagickOffsetType) cache_info->columns;
4749 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4751 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4752 (void) ClosePixelCacheOnDisk(cache_info);
4753 UnlockSemaphoreInfo(cache_info->file_semaphore);
4756 case DistributedCache:
4764 LockSemaphoreInfo(cache_info->file_semaphore);
4765 region=nexus_info->region;
4766 if ((cache_info->columns != nexus_info->region.width) ||
4767 (extent > MagickMaxBufferExtent))
4774 for (y=0; y < (ssize_t) rows; y++)
4777 cache_info->server_info,®ion,length,(
unsigned char *) q);
4778 if (count != (MagickOffsetType) length)
4780 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4783 UnlockSemaphoreInfo(cache_info->file_semaphore);
4789 if (y < (ssize_t) rows)
4791 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4792 cache_info->cache_filename);
4793 return(MagickFalse);
4795 if ((cache_info->debug != MagickFalse) &&
4796 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4797 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4798 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4799 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4800 nexus_info->region.x,(
double) nexus_info->region.y);
4827MagickPrivate Cache ReferencePixelCache(Cache cache)
4830 *magick_restrict cache_info;
4832 assert(cache != (Cache *) NULL);
4834 assert(cache_info->signature == MagickCoreSignature);
4835 LockSemaphoreInfo(cache_info->semaphore);
4836 cache_info->reference_count++;
4837 UnlockSemaphoreInfo(cache_info->semaphore);
4863MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4866 *magick_restrict cache_info;
4868 assert(image != (
const Image *) NULL);
4869 assert(image->signature == MagickCoreSignature);
4870 assert(image->cache != (Cache) NULL);
4872 assert(cache_info->signature == MagickCoreSignature);
4873 cache_info->number_channels=GetPixelChannels(image);
4894MagickPrivate
void ResetCacheAnonymousMemory(
void)
4896 cache_anonymous_memory=0;
4928MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4929 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4937 assert(image != (
Image *) NULL);
4938 assert(image->signature == MagickCoreSignature);
4939 if (IsEventLogging() != MagickFalse)
4940 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4941 assert(image->cache != (
void *) NULL);
4942 extent=(MagickSizeType) columns*rows;
4943 if (extent > ((MagickSizeType) image->columns*image->rows))
4944 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4946 image->columns=columns;
4949 cache_info->columns=columns;
4950 cache_info->rows=rows;
4951 return(SyncImagePixelCache(image,exception));
4978MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4981 *magick_restrict cache_info;
4983 GetOneAuthenticPixelFromHandler
4984 get_one_authentic_pixel_from_handler;
4986 GetOneVirtualPixelFromHandler
4987 get_one_virtual_pixel_from_handler;
4992 assert(cache != (Cache) NULL);
4995 assert(cache_info->signature == MagickCoreSignature);
4996 if (IsEventLogging() != MagickFalse)
4997 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4998 cache_info->filename);
4999 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
5000 cache_info->methods.get_virtual_pixel_handler=
5001 cache_methods->get_virtual_pixel_handler;
5002 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
5003 cache_info->methods.destroy_pixel_handler=
5004 cache_methods->destroy_pixel_handler;
5005 if (cache_methods->get_virtual_metacontent_from_handler !=
5006 (GetVirtualMetacontentFromHandler) NULL)
5007 cache_info->methods.get_virtual_metacontent_from_handler=
5008 cache_methods->get_virtual_metacontent_from_handler;
5009 if (cache_methods->get_authentic_pixels_handler !=
5010 (GetAuthenticPixelsHandler) NULL)
5011 cache_info->methods.get_authentic_pixels_handler=
5012 cache_methods->get_authentic_pixels_handler;
5013 if (cache_methods->queue_authentic_pixels_handler !=
5014 (QueueAuthenticPixelsHandler) NULL)
5015 cache_info->methods.queue_authentic_pixels_handler=
5016 cache_methods->queue_authentic_pixels_handler;
5017 if (cache_methods->sync_authentic_pixels_handler !=
5018 (SyncAuthenticPixelsHandler) NULL)
5019 cache_info->methods.sync_authentic_pixels_handler=
5020 cache_methods->sync_authentic_pixels_handler;
5021 if (cache_methods->get_authentic_pixels_from_handler !=
5022 (GetAuthenticPixelsFromHandler) NULL)
5023 cache_info->methods.get_authentic_pixels_from_handler=
5024 cache_methods->get_authentic_pixels_from_handler;
5025 if (cache_methods->get_authentic_metacontent_from_handler !=
5026 (GetAuthenticMetacontentFromHandler) NULL)
5027 cache_info->methods.get_authentic_metacontent_from_handler=
5028 cache_methods->get_authentic_metacontent_from_handler;
5029 get_one_virtual_pixel_from_handler=
5030 cache_info->methods.get_one_virtual_pixel_from_handler;
5031 if (get_one_virtual_pixel_from_handler !=
5032 (GetOneVirtualPixelFromHandler) NULL)
5033 cache_info->methods.get_one_virtual_pixel_from_handler=
5034 cache_methods->get_one_virtual_pixel_from_handler;
5035 get_one_authentic_pixel_from_handler=
5036 cache_methods->get_one_authentic_pixel_from_handler;
5037 if (get_one_authentic_pixel_from_handler !=
5038 (GetOneAuthenticPixelFromHandler) NULL)
5039 cache_info->methods.get_one_authentic_pixel_from_handler=
5040 cache_methods->get_one_authentic_pixel_from_handler;
5081static inline MagickBooleanType AcquireCacheNexusPixels(
5082 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5085 if (length != (MagickSizeType) ((
size_t) length))
5087 (void) ThrowMagickException(exception,GetMagickModule(),
5088 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5089 cache_info->filename);
5090 return(MagickFalse);
5092 nexus_info->length=0;
5093 nexus_info->mapped=MagickFalse;
5094 if (cache_anonymous_memory <= 0)
5096 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5098 if (nexus_info->cache != (Quantum *) NULL)
5099 (
void) memset(nexus_info->cache,0,(
size_t) length);
5103 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5104 if (nexus_info->cache != (Quantum *) NULL)
5105 nexus_info->mapped=MagickTrue;
5107 if (nexus_info->cache == (Quantum *) NULL)
5109 (void) ThrowMagickException(exception,GetMagickModule(),
5110 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5111 cache_info->filename);
5112 return(MagickFalse);
5114 nexus_info->length=length;
5118static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5121 if (nexus_info->length < CACHE_LINE_SIZE)
5123 if (mode == ReadMode)
5125 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5129 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5132static Quantum *SetPixelCacheNexusPixels(
5133 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5134 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5135 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5145 assert(cache_info != (
const CacheInfo *) NULL);
5146 assert(cache_info->signature == MagickCoreSignature);
5147 if (cache_info->type == UndefinedCache)
5148 return((Quantum *) NULL);
5149 assert(nexus_info->signature == MagickCoreSignature);
5150 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5151 if ((width == 0) || (height == 0))
5153 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5154 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5155 return((Quantum *) NULL);
5157 if (((MagickSizeType) width > cache_info->width_limit) ||
5158 ((MagickSizeType) height > cache_info->height_limit))
5160 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5161 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5162 return((Quantum *) NULL);
5164 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5165 (IsValidPixelOffset(y,height) == MagickFalse))
5167 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5168 "InvalidPixel",
"`%s'",cache_info->filename);
5169 return((Quantum *) NULL);
5171 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5172 (buffered == MagickFalse))
5174 if (((x >= 0) && (y >= 0) &&
5175 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5176 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5177 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5185 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5186 return((Quantum *) NULL);
5187 offset=y*(MagickOffsetType) cache_info->columns+x;
5188 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5189 cache_info->number_channels*offset;
5190 nexus_info->metacontent=(
void *) NULL;
5191 if (cache_info->metacontent_extent != 0)
5192 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5193 offset*(MagickOffsetType) cache_info->metacontent_extent;
5194 nexus_info->region.width=width;
5195 nexus_info->region.height=height;
5196 nexus_info->region.x=x;
5197 nexus_info->region.y=y;
5198 nexus_info->authentic_pixel_cache=MagickTrue;
5199 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5200 return(nexus_info->pixels);
5206 if (CacheOverflowSanityCheckGetSize((MagickSizeType) width,height,&number_pixels) != MagickFalse)
5208 (void) ThrowMagickException(exception,GetMagickModule(),
5209 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5210 cache_info->filename);
5211 return((Quantum *) NULL);
5218 packets=MagickMax(number_pixels,MagickMax(cache_info->columns,
5220 if ((CacheOverflowSanityCheckGetSize(packets,cache_info->number_channels,&length) != MagickFalse) ||
5221 (CacheOverflowSanityCheckGetSize(length,
sizeof(*nexus_info->pixels),&length) != MagickFalse))
5223 (void) ThrowMagickException(exception,GetMagickModule(),
5224 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5225 cache_info->filename);
5226 return((Quantum *) NULL);
5228 if (cache_info->metacontent_extent != 0)
5230 if ((CacheOverflowSanityCheckGetSize(number_pixels,cache_info->metacontent_extent,&extent) != MagickFalse) ||
5231 (extent > (MagickSizeType) (~((MagickSizeType) 0))-length))
5233 (void) ThrowMagickException(exception,GetMagickModule(),
5234 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
5235 cache_info->filename);
5236 return((Quantum *) NULL);
5242 if (nexus_info->cache == (Quantum *) NULL)
5243 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5245 if (nexus_info->length < length)
5247 RelinquishCacheNexusPixels(nexus_info);
5248 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5250 if (status == MagickFalse)
5251 return((Quantum *) NULL);
5252 nexus_info->pixels=nexus_info->cache;
5253 nexus_info->metacontent=(
void *) NULL;
5254 if (cache_info->metacontent_extent != 0)
5255 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5256 cache_info->number_channels*number_pixels);
5257 nexus_info->region.width=width;
5258 nexus_info->region.height=height;
5259 nexus_info->region.x=x;
5260 nexus_info->region.y=y;
5261 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5262 MagickTrue : MagickFalse;
5263 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5264 return(nexus_info->pixels);
5297static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5301 *magick_restrict image_view;
5309 assert(image != (
Image *) NULL);
5310 assert(image->signature == MagickCoreSignature);
5311 if (IsEventLogging() != MagickFalse)
5312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5313 assert(image->cache != (Cache) NULL);
5314 image->alpha_trait=BlendPixelTrait;
5316 image_view=AcquireVirtualCacheView(image,exception);
5317#if defined(MAGICKCORE_OPENMP_SUPPORT)
5318 #pragma omp parallel for schedule(static) shared(status) \
5319 magick_number_threads(image,image,image->rows,2)
5321 for (y=0; y < (ssize_t) image->rows; y++)
5329 if (status == MagickFalse)
5331 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5332 if (q == (Quantum *) NULL)
5337 for (x=0; x < (ssize_t) image->columns; x++)
5339 SetPixelAlpha(image,alpha,q);
5340 q+=(ptrdiff_t) GetPixelChannels(image);
5342 status=SyncCacheViewAuthenticPixels(image_view,exception);
5344 image_view=DestroyCacheView(image_view);
5348MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5349 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5352 *magick_restrict cache_info;
5357 assert(image != (
Image *) NULL);
5358 assert(image->signature == MagickCoreSignature);
5359 if (IsEventLogging() != MagickFalse)
5360 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5361 assert(image->cache != (Cache) NULL);
5363 assert(cache_info->signature == MagickCoreSignature);
5364 method=cache_info->virtual_pixel_method;
5365 cache_info->virtual_pixel_method=virtual_pixel_method;
5366 if ((image->columns != 0) && (image->rows != 0))
5367 switch (virtual_pixel_method)
5369 case BackgroundVirtualPixelMethod:
5371 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5372 ((image->alpha_trait & BlendPixelTrait) == 0))
5373 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5374 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5375 (IsGrayColorspace(image->colorspace) != MagickFalse))
5376 (void) SetImageColorspace(image,sRGBColorspace,exception);
5379 case TransparentVirtualPixelMethod:
5381 if ((image->alpha_trait & BlendPixelTrait) == 0)
5382 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5391#if defined(MAGICKCORE_OPENCL_SUPPORT)
5416static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5418 assert(cache_info != (
CacheInfo *) NULL);
5419 assert(cache_info->signature == MagickCoreSignature);
5420 if ((cache_info->type != MemoryCache) ||
5421 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5426 LockSemaphoreInfo(cache_info->semaphore);
5427 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5428 UnlockSemaphoreInfo(cache_info->semaphore);
5431MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5434 *magick_restrict cache_info;
5436 assert(image != (
const Image *) NULL);
5438 CopyOpenCLBuffer(cache_info);
5471MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5475 *magick_restrict cache_info;
5483 assert(image != (
Image *) NULL);
5484 assert(image->signature == MagickCoreSignature);
5485 if (image->cache == (Cache) NULL)
5486 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5488 assert(cache_info->signature == MagickCoreSignature);
5489 if (cache_info->type == UndefinedCache)
5490 return(MagickFalse);
5491 if (image->mask_trait != UpdatePixelTrait)
5493 if (((image->channels & WriteMaskChannel) != 0) &&
5494 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5495 return(MagickFalse);
5496 if (((image->channels & CompositeMaskChannel) != 0) &&
5497 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5498 return(MagickFalse);
5500 if (nexus_info->authentic_pixel_cache != MagickFalse)
5502 if (image->taint == MagickFalse)
5503 image->taint=MagickTrue;
5506 assert(cache_info->signature == MagickCoreSignature);
5507 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5508 if ((cache_info->metacontent_extent != 0) &&
5509 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5510 return(MagickFalse);
5511 if ((status != MagickFalse) && (image->taint == MagickFalse))
5512 image->taint=MagickTrue;
5543static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5547 *magick_restrict cache_info;
5550 id = GetOpenMPThreadId();
5555 assert(image != (
Image *) NULL);
5556 assert(image->signature == MagickCoreSignature);
5557 assert(image->cache != (Cache) NULL);
5559 assert(cache_info->signature == MagickCoreSignature);
5560 assert(
id < (
int) cache_info->number_threads);
5561 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5593MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5597 *magick_restrict cache_info;
5600 id = GetOpenMPThreadId();
5605 assert(image != (
Image *) NULL);
5606 assert(image->signature == MagickCoreSignature);
5607 assert(image->cache != (Cache) NULL);
5609 assert(cache_info->signature == MagickCoreSignature);
5610 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5612 status=cache_info->methods.sync_authentic_pixels_handler(image,
5616 assert(
id < (
int) cache_info->number_threads);
5617 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5649MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5653 *magick_restrict cache_info;
5655 assert(image != (
Image *) NULL);
5657 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5658 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5689static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5709 if (cache_info->metacontent_extent == 0)
5710 return(MagickFalse);
5711 if (nexus_info->authentic_pixel_cache != MagickFalse)
5713 if (nexus_info->metacontent == (
unsigned char *) NULL)
5714 return(MagickFalse);
5715 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5716 return(MagickFalse);
5717 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5718 nexus_info->region.x;
5719 length=(MagickSizeType) nexus_info->region.width*
5720 cache_info->metacontent_extent;
5721 extent=(MagickSizeType) length*nexus_info->region.height;
5722 rows=nexus_info->region.height;
5724 p=(
unsigned char *) nexus_info->metacontent;
5725 switch (cache_info->type)
5736 if ((cache_info->columns == nexus_info->region.width) &&
5737 (extent == (MagickSizeType) ((
size_t) extent)))
5742 q=(
unsigned char *) cache_info->metacontent+offset*
5743 (MagickOffsetType) cache_info->metacontent_extent;
5744 for (y=0; y < (ssize_t) rows; y++)
5746 (void) memcpy(q,p,(
size_t) length);
5747 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5748 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5757 LockSemaphoreInfo(cache_info->file_semaphore);
5758 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5760 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5761 cache_info->cache_filename);
5762 UnlockSemaphoreInfo(cache_info->file_semaphore);
5763 return(MagickFalse);
5765 if ((cache_info->columns == nexus_info->region.width) &&
5766 (extent <= MagickMaxBufferExtent))
5771 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5772 for (y=0; y < (ssize_t) rows; y++)
5774 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5775 (MagickOffsetType) extent*(MagickOffsetType)
5776 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5777 (MagickOffsetType) cache_info->metacontent_extent,length,
5778 (
const unsigned char *) p);
5779 if (count != (MagickOffsetType) length)
5781 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5782 offset+=(MagickOffsetType) cache_info->columns;
5784 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5785 (void) ClosePixelCacheOnDisk(cache_info);
5786 UnlockSemaphoreInfo(cache_info->file_semaphore);
5789 case DistributedCache:
5797 LockSemaphoreInfo(cache_info->file_semaphore);
5798 region=nexus_info->region;
5799 if ((cache_info->columns != nexus_info->region.width) ||
5800 (extent > MagickMaxBufferExtent))
5807 for (y=0; y < (ssize_t) rows; y++)
5810 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5811 if (count != (MagickOffsetType) length)
5813 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5816 UnlockSemaphoreInfo(cache_info->file_semaphore);
5822 if (y < (ssize_t) rows)
5824 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5825 cache_info->cache_filename);
5826 return(MagickFalse);
5828 if ((cache_info->debug != MagickFalse) &&
5829 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5830 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5831 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5832 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5833 nexus_info->region.x,(
double) nexus_info->region.y);
5865static MagickBooleanType WritePixelCachePixels(
5886 if (nexus_info->authentic_pixel_cache != MagickFalse)
5888 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5889 return(MagickFalse);
5890 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5891 nexus_info->region.x;
5892 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5894 extent=length*nexus_info->region.height;
5895 rows=nexus_info->region.height;
5897 p=nexus_info->pixels;
5898 switch (cache_info->type)
5909 if ((cache_info->columns == nexus_info->region.width) &&
5910 (extent == (MagickSizeType) ((
size_t) extent)))
5915 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5917 for (y=0; y < (ssize_t) rows; y++)
5919 (void) memcpy(q,p,(
size_t) length);
5920 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5921 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5930 LockSemaphoreInfo(cache_info->file_semaphore);
5931 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5933 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5934 cache_info->cache_filename);
5935 UnlockSemaphoreInfo(cache_info->file_semaphore);
5936 return(MagickFalse);
5938 if ((cache_info->columns == nexus_info->region.width) &&
5939 (extent <= MagickMaxBufferExtent))
5944 for (y=0; y < (ssize_t) rows; y++)
5946 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5947 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5948 sizeof(*p),length,(
const unsigned char *) p);
5949 if (count != (MagickOffsetType) length)
5951 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5952 offset+=(MagickOffsetType) cache_info->columns;
5954 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5955 (void) ClosePixelCacheOnDisk(cache_info);
5956 UnlockSemaphoreInfo(cache_info->file_semaphore);
5959 case DistributedCache:
5967 LockSemaphoreInfo(cache_info->file_semaphore);
5968 region=nexus_info->region;
5969 if ((cache_info->columns != nexus_info->region.width) ||
5970 (extent > MagickMaxBufferExtent))
5977 for (y=0; y < (ssize_t) rows; y++)
5980 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5981 if (count != (MagickOffsetType) length)
5983 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5986 UnlockSemaphoreInfo(cache_info->file_semaphore);
5992 if (y < (ssize_t) rows)
5994 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5995 cache_info->cache_filename);
5996 return(MagickFalse);
5998 if ((cache_info->debug != MagickFalse) &&
5999 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
6000 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
6001 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
6002 nexus_info->region.width,(
double) nexus_info->region.height,(double)
6003 nexus_info->region.x,(
double) nexus_info->region.y);