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 (image->metacontent_extent != 0)
3744 packet_size+=cache_info->metacontent_extent;
3745 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3747 cache_info->storage_class=UndefinedClass;
3748 cache_info->length=0;
3749 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3752 columns=(size_t) (length/cache_info->rows/packet_size);
3753 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3754 ((ssize_t) cache_info->rows < 0))
3756 cache_info->storage_class=UndefinedClass;
3757 cache_info->length=0;
3758 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3761 cache_info->length=length;
3762 if (image->ping != MagickFalse)
3764 cache_info->type=PingCache;
3767 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3768 cache_info->columns*cache_info->rows);
3769 if (cache_info->mode == PersistMode)
3771 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3772 cache_info->metacontent_extent);
3773 if ((status != MagickFalse) &&
3774 (length == (MagickSizeType) ((
size_t) length)) &&
3775 ((cache_info->type == UndefinedCache) ||
3776 (cache_info->type == MemoryCache)))
3778 status=AcquireMagickResource(MemoryResource,cache_info->length);
3779 if (status != MagickFalse)
3782 if (cache_anonymous_memory <= 0)
3784 cache_info->mapped=MagickFalse;
3785 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3786 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3790 cache_info->mapped=MagickTrue;
3791 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3792 cache_info->length);
3794 if (cache_info->pixels == (Quantum *) NULL)
3796 cache_info->mapped=source_info.mapped;
3797 cache_info->pixels=source_info.pixels;
3804 cache_info->type=MemoryCache;
3805 cache_info->metacontent=(
void *) NULL;
3806 if (cache_info->metacontent_extent != 0)
3807 cache_info->metacontent=(
void *) (cache_info->pixels+
3808 cache_info->number_channels*number_pixels);
3809 if ((source_info.storage_class != UndefinedClass) &&
3812 status=ClonePixelCacheRepository(cache_info,&source_info,
3814 RelinquishPixelCachePixels(&source_info);
3816 if (cache_info->debug != MagickFalse)
3818 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3819 MagickPathExtent,format);
3820 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3822 (void) FormatLocaleString(message,MagickPathExtent,
3823 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3824 cache_info->filename,cache_info->mapped != MagickFalse ?
3825 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3826 (double) cache_info->rows,(double)
3827 cache_info->number_channels,format);
3828 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3831 cache_info->storage_class=image->storage_class;
3834 if ((source_info.storage_class != UndefinedClass) &&
3836 RelinquishPixelCachePixels(&source_info);
3837 cache_info->type=UndefinedCache;
3838 return(MagickFalse);
3844 status=AcquireMagickResource(DiskResource,cache_info->length);
3845 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3847 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3855 server_info=AcquireDistributeCacheInfo(exception);
3858 status=OpenDistributePixelCache(server_info,image);
3859 if (status == MagickFalse)
3861 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3862 GetDistributeCacheHostname(server_info));
3863 server_info=DestroyDistributeCacheInfo(server_info);
3871 cache_info->type=DistributedCache;
3872 cache_info->server_info=server_info;
3873 (void) FormatLocaleString(cache_info->cache_filename,
3874 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3877 cache_info->server_info));
3878 if ((source_info.storage_class != UndefinedClass) &&
3881 status=ClonePixelCacheRepository(cache_info,&source_info,
3883 RelinquishPixelCachePixels(&source_info);
3885 if (cache_info->debug != MagickFalse)
3887 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3888 MagickPathExtent,format);
3889 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3891 (void) FormatLocaleString(message,MagickPathExtent,
3892 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3893 cache_info->filename,cache_info->cache_filename,
3895 cache_info->server_info),type,(double) cache_info->columns,
3896 (
double) cache_info->rows,(double)
3897 cache_info->number_channels,format);
3898 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3903 if ((source_info.storage_class != UndefinedClass) &&
3905 RelinquishPixelCachePixels(&source_info);
3906 cache_info->type=UndefinedCache;
3907 return(MagickFalse);
3912 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3913 RelinquishPixelCachePixels(&source_info);
3914 cache_info->type=UndefinedCache;
3915 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3916 "CacheResourcesExhausted",
"`%s'",image->filename);
3917 return(MagickFalse);
3922 if (status == MagickFalse)
3924 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3925 RelinquishPixelCachePixels(&source_info);
3926 cache_info->type=UndefinedCache;
3927 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3928 "CacheResourcesExhausted",
"`%s'",image->filename);
3929 return(MagickFalse);
3931 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3932 (cache_info->mode != PersistMode))
3934 (void) ClosePixelCacheOnDisk(cache_info);
3935 *cache_info->cache_filename=
'\0';
3937 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3939 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3940 RelinquishPixelCachePixels(&source_info);
3941 cache_info->type=UndefinedCache;
3942 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3944 return(MagickFalse);
3946 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3947 cache_info->length);
3948 if (status == MagickFalse)
3950 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3951 RelinquishPixelCachePixels(&source_info);
3952 cache_info->type=UndefinedCache;
3953 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3955 return(MagickFalse);
3957 cache_info->type=DiskCache;
3958 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3959 cache_info->metacontent_extent);
3960 if (length == (MagickSizeType) ((
size_t) length))
3962 status=AcquireMagickResource(MapResource,cache_info->length);
3963 if (status != MagickFalse)
3965 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3966 cache_info->offset,(
size_t) cache_info->length);
3967 if (cache_info->pixels == (Quantum *) NULL)
3969 cache_info->mapped=source_info.mapped;
3970 cache_info->pixels=source_info.pixels;
3971 RelinquishMagickResource(MapResource,cache_info->length);
3978 (void) ClosePixelCacheOnDisk(cache_info);
3979 cache_info->type=MapCache;
3980 cache_info->mapped=MagickTrue;
3981 cache_info->metacontent=(
void *) NULL;
3982 if (cache_info->metacontent_extent != 0)
3983 cache_info->metacontent=(
void *) (cache_info->pixels+
3984 cache_info->number_channels*number_pixels);
3985 if ((source_info.storage_class != UndefinedClass) &&
3988 status=ClonePixelCacheRepository(cache_info,&source_info,
3990 RelinquishPixelCachePixels(&source_info);
3992 if (cache_info->debug != MagickFalse)
3994 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3995 MagickPathExtent,format);
3996 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3998 (void) FormatLocaleString(message,MagickPathExtent,
3999 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
4000 cache_info->filename,cache_info->cache_filename,
4001 cache_info->file,type,(
double) cache_info->columns,
4002 (double) cache_info->rows,(
double)
4003 cache_info->number_channels,format);
4004 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4009 if ((source_info.storage_class != UndefinedClass) &&
4011 RelinquishPixelCachePixels(&source_info);
4012 cache_info->type=UndefinedCache;
4013 return(MagickFalse);
4020 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4022 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4023 RelinquishPixelCachePixels(&source_info);
4025 if (cache_info->debug != MagickFalse)
4027 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4028 MagickPathExtent,format);
4029 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4031 (void) FormatLocaleString(message,MagickPathExtent,
4032 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4033 cache_info->cache_filename,cache_info->file,type,(
double)
4034 cache_info->columns,(double) cache_info->rows,(
double)
4035 cache_info->number_channels,format);
4036 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4040 cache_info->type=UndefinedCache;
4041 return(MagickFalse);
4083MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4084 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4088 *magick_restrict cache_info,
4089 *magick_restrict clone_info;
4097 assert(image != (
Image *) NULL);
4098 assert(image->signature == MagickCoreSignature);
4099 if (IsEventLogging() != MagickFalse)
4100 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4101 assert(image->cache != (
void *) NULL);
4102 assert(filename != (
const char *) NULL);
4103 assert(offset != (MagickOffsetType *) NULL);
4104 page_size=GetMagickPageSize();
4106 assert(cache_info->signature == MagickCoreSignature);
4107#if defined(MAGICKCORE_OPENCL_SUPPORT)
4108 CopyOpenCLBuffer(cache_info);
4110 if (attach != MagickFalse)
4115 if (cache_info->debug != MagickFalse)
4116 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4117 "attach persistent cache");
4118 (void) CopyMagickString(cache_info->cache_filename,filename,
4120 cache_info->type=MapCache;
4121 cache_info->offset=(*offset);
4122 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4123 return(MagickFalse);
4124 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4125 ((MagickOffsetType) cache_info->length % page_size));
4131 status=AcquireMagickResource(DiskResource,cache_info->length);
4132 if (status == MagickFalse)
4134 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4135 "CacheResourcesExhausted",
"`%s'",image->filename);
4136 return(MagickFalse);
4138 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4139 clone_info->type=DiskCache;
4140 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4141 clone_info->file=(-1);
4142 clone_info->storage_class=cache_info->storage_class;
4143 clone_info->colorspace=cache_info->colorspace;
4144 clone_info->alpha_trait=cache_info->alpha_trait;
4145 clone_info->channels=cache_info->channels;
4146 clone_info->columns=cache_info->columns;
4147 clone_info->rows=cache_info->rows;
4148 clone_info->number_channels=cache_info->number_channels;
4149 clone_info->metacontent_extent=cache_info->metacontent_extent;
4150 clone_info->mode=PersistMode;
4151 clone_info->length=cache_info->length;
4152 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4153 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4154 clone_info->offset=(*offset);
4155 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4156 if (status != MagickFalse)
4157 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4158 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4159 ((MagickOffsetType) cache_info->length % page_size));
4160 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4202MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4203 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4207 *magick_restrict cache_info;
4216 *magick_restrict pixels;
4221 assert(image != (
const Image *) NULL);
4222 assert(image->signature == MagickCoreSignature);
4223 assert(image->cache != (Cache) NULL);
4224 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4225 if (cache_info == (Cache) NULL)
4226 return((Quantum *) NULL);
4227 assert(cache_info->signature == MagickCoreSignature);
4228 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4229 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4230 (y >= (ssize_t) cache_info->rows))
4232 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4233 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4234 return((Quantum *) NULL);
4236 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4237 return((Quantum *) NULL);
4238 offset=y*(MagickOffsetType) cache_info->columns+x;
4240 return((Quantum *) NULL);
4241 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4242 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4243 (MagickOffsetType) columns-1;
4244 if ((MagickSizeType) offset >= number_pixels)
4245 return((Quantum *) NULL);
4249 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4250 ((image->channels & WriteMaskChannel) != 0) ||
4251 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4252 nexus_info,exception);
4289static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4290 const ssize_t y,
const size_t columns,
const size_t rows,
4294 *magick_restrict cache_info;
4297 id = GetOpenMPThreadId();
4300 *magick_restrict pixels;
4302 assert(image != (
const Image *) NULL);
4303 assert(image->signature == MagickCoreSignature);
4304 assert(image->cache != (Cache) NULL);
4306 assert(cache_info->signature == MagickCoreSignature);
4307 assert(
id < (
int) cache_info->number_threads);
4308 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4309 cache_info->nexus_info[
id],exception);
4369MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4370 const ssize_t y,
const size_t columns,
const size_t rows,
4374 *magick_restrict cache_info;
4377 id = GetOpenMPThreadId();
4380 *magick_restrict pixels;
4382 assert(image != (
Image *) NULL);
4383 assert(image->signature == MagickCoreSignature);
4384 assert(image->cache != (Cache) NULL);
4386 assert(cache_info->signature == MagickCoreSignature);
4387 if (cache_info->methods.queue_authentic_pixels_handler !=
4388 (QueueAuthenticPixelsHandler) NULL)
4390 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4391 columns,rows,exception);
4394 assert(
id < (
int) cache_info->number_threads);
4395 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4396 cache_info->nexus_info[
id],exception);
4429static inline MagickOffsetType ReadPixelCacheRegion(
4430 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4431 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4439#if !defined(MAGICKCORE_HAVE_PREAD)
4440 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4441 return((MagickOffsetType) -1);
4443 for (i=0; i < (MagickOffsetType) length; i+=count)
4445#if !defined(MAGICKCORE_HAVE_PREAD)
4446 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4447 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4449 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4450 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4462static MagickBooleanType ReadPixelCacheMetacontent(
4483 if (cache_info->metacontent_extent == 0)
4484 return(MagickFalse);
4485 if (nexus_info->authentic_pixel_cache != MagickFalse)
4487 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4488 return(MagickFalse);
4489 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4490 nexus_info->region.x;
4491 length=(MagickSizeType) nexus_info->region.width*
4492 cache_info->metacontent_extent;
4493 extent=length*nexus_info->region.height;
4494 rows=nexus_info->region.height;
4496 q=(
unsigned char *) nexus_info->metacontent;
4497 switch (cache_info->type)
4508 if ((cache_info->columns == nexus_info->region.width) &&
4509 (extent == (MagickSizeType) ((
size_t) extent)))
4514 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4515 cache_info->metacontent_extent;
4516 for (y=0; y < (ssize_t) rows; y++)
4518 (void) memcpy(q,p,(
size_t) length);
4519 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4520 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4529 LockSemaphoreInfo(cache_info->file_semaphore);
4530 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4532 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4533 cache_info->cache_filename);
4534 UnlockSemaphoreInfo(cache_info->file_semaphore);
4535 return(MagickFalse);
4537 if ((cache_info->columns == nexus_info->region.width) &&
4538 (extent <= MagickMaxBufferExtent))
4543 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4544 for (y=0; y < (ssize_t) rows; y++)
4546 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4547 (MagickOffsetType) extent*(MagickOffsetType)
4548 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4549 (MagickOffsetType) cache_info->metacontent_extent,length,
4550 (
unsigned char *) q);
4551 if (count != (MagickOffsetType) length)
4553 offset+=(MagickOffsetType) cache_info->columns;
4554 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4556 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4557 (void) ClosePixelCacheOnDisk(cache_info);
4558 UnlockSemaphoreInfo(cache_info->file_semaphore);
4561 case DistributedCache:
4569 LockSemaphoreInfo(cache_info->file_semaphore);
4570 region=nexus_info->region;
4571 if ((cache_info->columns != nexus_info->region.width) ||
4572 (extent > MagickMaxBufferExtent))
4579 for (y=0; y < (ssize_t) rows; y++)
4582 cache_info->server_info,®ion,length,(
unsigned char *) q);
4583 if (count != (MagickOffsetType) length)
4585 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4588 UnlockSemaphoreInfo(cache_info->file_semaphore);
4594 if (y < (ssize_t) rows)
4596 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4597 cache_info->cache_filename);
4598 return(MagickFalse);
4600 if ((cache_info->debug != MagickFalse) &&
4601 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4602 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4603 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4604 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4605 nexus_info->region.x,(
double) nexus_info->region.y);
4637static MagickBooleanType ReadPixelCachePixels(
4659 if (nexus_info->authentic_pixel_cache != MagickFalse)
4661 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4662 return(MagickFalse);
4663 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4664 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4665 return(MagickFalse);
4666 offset+=nexus_info->region.x;
4667 number_channels=cache_info->number_channels;
4668 length=(MagickSizeType) number_channels*nexus_info->region.width*
4670 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4671 return(MagickFalse);
4672 rows=nexus_info->region.height;
4674 if ((extent == 0) || ((extent/length) != rows))
4675 return(MagickFalse);
4677 q=nexus_info->pixels;
4678 switch (cache_info->type)
4689 if ((cache_info->columns == nexus_info->region.width) &&
4690 (extent == (MagickSizeType) ((
size_t) extent)))
4695 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4697 for (y=0; y < (ssize_t) rows; y++)
4699 (void) memcpy(q,p,(
size_t) length);
4700 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4701 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4710 LockSemaphoreInfo(cache_info->file_semaphore);
4711 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4713 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4714 cache_info->cache_filename);
4715 UnlockSemaphoreInfo(cache_info->file_semaphore);
4716 return(MagickFalse);
4718 if ((cache_info->columns == nexus_info->region.width) &&
4719 (extent <= MagickMaxBufferExtent))
4724 for (y=0; y < (ssize_t) rows; y++)
4726 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4727 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4728 sizeof(*q),length,(
unsigned char *) q);
4729 if (count != (MagickOffsetType) length)
4731 offset+=(MagickOffsetType) cache_info->columns;
4732 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4734 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4735 (void) ClosePixelCacheOnDisk(cache_info);
4736 UnlockSemaphoreInfo(cache_info->file_semaphore);
4739 case DistributedCache:
4747 LockSemaphoreInfo(cache_info->file_semaphore);
4748 region=nexus_info->region;
4749 if ((cache_info->columns != nexus_info->region.width) ||
4750 (extent > MagickMaxBufferExtent))
4757 for (y=0; y < (ssize_t) rows; y++)
4760 cache_info->server_info,®ion,length,(
unsigned char *) q);
4761 if (count != (MagickOffsetType) length)
4763 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4766 UnlockSemaphoreInfo(cache_info->file_semaphore);
4772 if (y < (ssize_t) rows)
4774 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4775 cache_info->cache_filename);
4776 return(MagickFalse);
4778 if ((cache_info->debug != MagickFalse) &&
4779 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4780 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4781 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4782 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4783 nexus_info->region.x,(
double) nexus_info->region.y);
4810MagickPrivate Cache ReferencePixelCache(Cache cache)
4813 *magick_restrict cache_info;
4815 assert(cache != (Cache *) NULL);
4817 assert(cache_info->signature == MagickCoreSignature);
4818 LockSemaphoreInfo(cache_info->semaphore);
4819 cache_info->reference_count++;
4820 UnlockSemaphoreInfo(cache_info->semaphore);
4846MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4849 *magick_restrict cache_info;
4851 assert(image != (
const Image *) NULL);
4852 assert(image->signature == MagickCoreSignature);
4853 assert(image->cache != (Cache) NULL);
4855 assert(cache_info->signature == MagickCoreSignature);
4856 cache_info->number_channels=GetPixelChannels(image);
4877MagickPrivate
void ResetCacheAnonymousMemory(
void)
4879 cache_anonymous_memory=0;
4911MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4912 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4920 assert(image != (
Image *) NULL);
4921 assert(image->signature == MagickCoreSignature);
4922 if (IsEventLogging() != MagickFalse)
4923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4924 assert(image->cache != (
void *) NULL);
4925 extent=(MagickSizeType) columns*rows;
4926 if (extent > ((MagickSizeType) image->columns*image->rows))
4927 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4929 image->columns=columns;
4932 cache_info->columns=columns;
4933 cache_info->rows=rows;
4934 return(SyncImagePixelCache(image,exception));
4961MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4964 *magick_restrict cache_info;
4966 GetOneAuthenticPixelFromHandler
4967 get_one_authentic_pixel_from_handler;
4969 GetOneVirtualPixelFromHandler
4970 get_one_virtual_pixel_from_handler;
4975 assert(cache != (Cache) NULL);
4978 assert(cache_info->signature == MagickCoreSignature);
4979 if (IsEventLogging() != MagickFalse)
4980 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4981 cache_info->filename);
4982 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4983 cache_info->methods.get_virtual_pixel_handler=
4984 cache_methods->get_virtual_pixel_handler;
4985 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4986 cache_info->methods.destroy_pixel_handler=
4987 cache_methods->destroy_pixel_handler;
4988 if (cache_methods->get_virtual_metacontent_from_handler !=
4989 (GetVirtualMetacontentFromHandler) NULL)
4990 cache_info->methods.get_virtual_metacontent_from_handler=
4991 cache_methods->get_virtual_metacontent_from_handler;
4992 if (cache_methods->get_authentic_pixels_handler !=
4993 (GetAuthenticPixelsHandler) NULL)
4994 cache_info->methods.get_authentic_pixels_handler=
4995 cache_methods->get_authentic_pixels_handler;
4996 if (cache_methods->queue_authentic_pixels_handler !=
4997 (QueueAuthenticPixelsHandler) NULL)
4998 cache_info->methods.queue_authentic_pixels_handler=
4999 cache_methods->queue_authentic_pixels_handler;
5000 if (cache_methods->sync_authentic_pixels_handler !=
5001 (SyncAuthenticPixelsHandler) NULL)
5002 cache_info->methods.sync_authentic_pixels_handler=
5003 cache_methods->sync_authentic_pixels_handler;
5004 if (cache_methods->get_authentic_pixels_from_handler !=
5005 (GetAuthenticPixelsFromHandler) NULL)
5006 cache_info->methods.get_authentic_pixels_from_handler=
5007 cache_methods->get_authentic_pixels_from_handler;
5008 if (cache_methods->get_authentic_metacontent_from_handler !=
5009 (GetAuthenticMetacontentFromHandler) NULL)
5010 cache_info->methods.get_authentic_metacontent_from_handler=
5011 cache_methods->get_authentic_metacontent_from_handler;
5012 get_one_virtual_pixel_from_handler=
5013 cache_info->methods.get_one_virtual_pixel_from_handler;
5014 if (get_one_virtual_pixel_from_handler !=
5015 (GetOneVirtualPixelFromHandler) NULL)
5016 cache_info->methods.get_one_virtual_pixel_from_handler=
5017 cache_methods->get_one_virtual_pixel_from_handler;
5018 get_one_authentic_pixel_from_handler=
5019 cache_methods->get_one_authentic_pixel_from_handler;
5020 if (get_one_authentic_pixel_from_handler !=
5021 (GetOneAuthenticPixelFromHandler) NULL)
5022 cache_info->methods.get_one_authentic_pixel_from_handler=
5023 cache_methods->get_one_authentic_pixel_from_handler;
5064static inline MagickBooleanType AcquireCacheNexusPixels(
5065 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5068 if (length != (MagickSizeType) ((
size_t) length))
5070 (void) ThrowMagickException(exception,GetMagickModule(),
5071 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5072 cache_info->filename);
5073 return(MagickFalse);
5075 nexus_info->length=0;
5076 nexus_info->mapped=MagickFalse;
5077 if (cache_anonymous_memory <= 0)
5079 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5081 if (nexus_info->cache != (Quantum *) NULL)
5082 (
void) memset(nexus_info->cache,0,(
size_t) length);
5086 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5087 if (nexus_info->cache != (Quantum *) NULL)
5088 nexus_info->mapped=MagickTrue;
5090 if (nexus_info->cache == (Quantum *) NULL)
5092 (void) ThrowMagickException(exception,GetMagickModule(),
5093 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5094 cache_info->filename);
5095 return(MagickFalse);
5097 nexus_info->length=length;
5101static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5104 if (nexus_info->length < CACHE_LINE_SIZE)
5106 if (mode == ReadMode)
5108 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5112 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5115static Quantum *SetPixelCacheNexusPixels(
5116 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5117 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5118 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5128 assert(cache_info != (
const CacheInfo *) NULL);
5129 assert(cache_info->signature == MagickCoreSignature);
5130 if (cache_info->type == UndefinedCache)
5131 return((Quantum *) NULL);
5132 assert(nexus_info->signature == MagickCoreSignature);
5133 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5134 if ((width == 0) || (height == 0))
5136 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5137 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5138 return((Quantum *) NULL);
5140 if (((MagickSizeType) width > cache_info->width_limit) ||
5141 ((MagickSizeType) height > cache_info->height_limit))
5143 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5144 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5145 return((Quantum *) NULL);
5147 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5148 (IsValidPixelOffset(y,height) == MagickFalse))
5150 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5151 "InvalidPixel",
"`%s'",cache_info->filename);
5152 return((Quantum *) NULL);
5154 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5155 (buffered == MagickFalse))
5157 if (((x >= 0) && (y >= 0) &&
5158 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5159 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5160 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5168 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5169 return((Quantum *) NULL);
5170 offset=y*(MagickOffsetType) cache_info->columns+x;
5171 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5172 cache_info->number_channels*offset;
5173 nexus_info->metacontent=(
void *) NULL;
5174 if (cache_info->metacontent_extent != 0)
5175 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5176 offset*(MagickOffsetType) cache_info->metacontent_extent;
5177 nexus_info->region.width=width;
5178 nexus_info->region.height=height;
5179 nexus_info->region.x=x;
5180 nexus_info->region.y=y;
5181 nexus_info->authentic_pixel_cache=MagickTrue;
5182 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5183 return(nexus_info->pixels);
5189 number_pixels=(MagickSizeType) width*height;
5190 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5191 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5192 if (cache_info->metacontent_extent != 0)
5193 length+=number_pixels*cache_info->metacontent_extent;
5195 if (nexus_info->cache == (Quantum *) NULL)
5196 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5198 if (nexus_info->length < length)
5200 RelinquishCacheNexusPixels(nexus_info);
5201 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5203 if (status == MagickFalse)
5204 return((Quantum *) NULL);
5205 nexus_info->pixels=nexus_info->cache;
5206 nexus_info->metacontent=(
void *) NULL;
5207 if (cache_info->metacontent_extent != 0)
5208 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5209 cache_info->number_channels*number_pixels);
5210 nexus_info->region.width=width;
5211 nexus_info->region.height=height;
5212 nexus_info->region.x=x;
5213 nexus_info->region.y=y;
5214 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5215 MagickTrue : MagickFalse;
5216 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5217 return(nexus_info->pixels);
5250static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5254 *magick_restrict image_view;
5262 assert(image != (
Image *) NULL);
5263 assert(image->signature == MagickCoreSignature);
5264 if (IsEventLogging() != MagickFalse)
5265 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5266 assert(image->cache != (Cache) NULL);
5267 image->alpha_trait=BlendPixelTrait;
5269 image_view=AcquireVirtualCacheView(image,exception);
5270#if defined(MAGICKCORE_OPENMP_SUPPORT)
5271 #pragma omp parallel for schedule(static) shared(status) \
5272 magick_number_threads(image,image,image->rows,2)
5274 for (y=0; y < (ssize_t) image->rows; y++)
5282 if (status == MagickFalse)
5284 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5285 if (q == (Quantum *) NULL)
5290 for (x=0; x < (ssize_t) image->columns; x++)
5292 SetPixelAlpha(image,alpha,q);
5293 q+=(ptrdiff_t) GetPixelChannels(image);
5295 status=SyncCacheViewAuthenticPixels(image_view,exception);
5297 image_view=DestroyCacheView(image_view);
5301MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5302 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5305 *magick_restrict cache_info;
5310 assert(image != (
Image *) NULL);
5311 assert(image->signature == MagickCoreSignature);
5312 if (IsEventLogging() != MagickFalse)
5313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5314 assert(image->cache != (Cache) NULL);
5316 assert(cache_info->signature == MagickCoreSignature);
5317 method=cache_info->virtual_pixel_method;
5318 cache_info->virtual_pixel_method=virtual_pixel_method;
5319 if ((image->columns != 0) && (image->rows != 0))
5320 switch (virtual_pixel_method)
5322 case BackgroundVirtualPixelMethod:
5324 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5325 ((image->alpha_trait & BlendPixelTrait) == 0))
5326 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5327 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5328 (IsGrayColorspace(image->colorspace) != MagickFalse))
5329 (void) SetImageColorspace(image,sRGBColorspace,exception);
5332 case TransparentVirtualPixelMethod:
5334 if ((image->alpha_trait & BlendPixelTrait) == 0)
5335 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5344#if defined(MAGICKCORE_OPENCL_SUPPORT)
5369static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5371 assert(cache_info != (
CacheInfo *) NULL);
5372 assert(cache_info->signature == MagickCoreSignature);
5373 if ((cache_info->type != MemoryCache) ||
5374 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5379 LockSemaphoreInfo(cache_info->semaphore);
5380 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5381 UnlockSemaphoreInfo(cache_info->semaphore);
5384MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5387 *magick_restrict cache_info;
5389 assert(image != (
const Image *) NULL);
5391 CopyOpenCLBuffer(cache_info);
5424MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5428 *magick_restrict cache_info;
5436 assert(image != (
Image *) NULL);
5437 assert(image->signature == MagickCoreSignature);
5438 if (image->cache == (Cache) NULL)
5439 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5441 assert(cache_info->signature == MagickCoreSignature);
5442 if (cache_info->type == UndefinedCache)
5443 return(MagickFalse);
5444 if (image->mask_trait != UpdatePixelTrait)
5446 if (((image->channels & WriteMaskChannel) != 0) &&
5447 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5448 return(MagickFalse);
5449 if (((image->channels & CompositeMaskChannel) != 0) &&
5450 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5451 return(MagickFalse);
5453 if (nexus_info->authentic_pixel_cache != MagickFalse)
5455 if (image->taint == MagickFalse)
5456 image->taint=MagickTrue;
5459 assert(cache_info->signature == MagickCoreSignature);
5460 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5461 if ((cache_info->metacontent_extent != 0) &&
5462 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5463 return(MagickFalse);
5464 if ((status != MagickFalse) && (image->taint == MagickFalse))
5465 image->taint=MagickTrue;
5496static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5500 *magick_restrict cache_info;
5503 id = GetOpenMPThreadId();
5508 assert(image != (
Image *) NULL);
5509 assert(image->signature == MagickCoreSignature);
5510 assert(image->cache != (Cache) NULL);
5512 assert(cache_info->signature == MagickCoreSignature);
5513 assert(
id < (
int) cache_info->number_threads);
5514 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5546MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5550 *magick_restrict cache_info;
5553 id = GetOpenMPThreadId();
5558 assert(image != (
Image *) NULL);
5559 assert(image->signature == MagickCoreSignature);
5560 assert(image->cache != (Cache) NULL);
5562 assert(cache_info->signature == MagickCoreSignature);
5563 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5565 status=cache_info->methods.sync_authentic_pixels_handler(image,
5569 assert(
id < (
int) cache_info->number_threads);
5570 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5602MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5606 *magick_restrict cache_info;
5608 assert(image != (
Image *) NULL);
5610 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5611 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5642static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5662 if (cache_info->metacontent_extent == 0)
5663 return(MagickFalse);
5664 if (nexus_info->authentic_pixel_cache != MagickFalse)
5666 if (nexus_info->metacontent == (
unsigned char *) NULL)
5667 return(MagickFalse);
5668 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5669 return(MagickFalse);
5670 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5671 nexus_info->region.x;
5672 length=(MagickSizeType) nexus_info->region.width*
5673 cache_info->metacontent_extent;
5674 extent=(MagickSizeType) length*nexus_info->region.height;
5675 rows=nexus_info->region.height;
5677 p=(
unsigned char *) nexus_info->metacontent;
5678 switch (cache_info->type)
5689 if ((cache_info->columns == nexus_info->region.width) &&
5690 (extent == (MagickSizeType) ((
size_t) extent)))
5695 q=(
unsigned char *) cache_info->metacontent+offset*
5696 (MagickOffsetType) cache_info->metacontent_extent;
5697 for (y=0; y < (ssize_t) rows; y++)
5699 (void) memcpy(q,p,(
size_t) length);
5700 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5701 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5710 LockSemaphoreInfo(cache_info->file_semaphore);
5711 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5713 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5714 cache_info->cache_filename);
5715 UnlockSemaphoreInfo(cache_info->file_semaphore);
5716 return(MagickFalse);
5718 if ((cache_info->columns == nexus_info->region.width) &&
5719 (extent <= MagickMaxBufferExtent))
5724 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5725 for (y=0; y < (ssize_t) rows; y++)
5727 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5728 (MagickOffsetType) extent*(MagickOffsetType)
5729 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5730 (MagickOffsetType) cache_info->metacontent_extent,length,
5731 (
const unsigned char *) p);
5732 if (count != (MagickOffsetType) length)
5734 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5735 offset+=(MagickOffsetType) cache_info->columns;
5737 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5738 (void) ClosePixelCacheOnDisk(cache_info);
5739 UnlockSemaphoreInfo(cache_info->file_semaphore);
5742 case DistributedCache:
5750 LockSemaphoreInfo(cache_info->file_semaphore);
5751 region=nexus_info->region;
5752 if ((cache_info->columns != nexus_info->region.width) ||
5753 (extent > MagickMaxBufferExtent))
5760 for (y=0; y < (ssize_t) rows; y++)
5763 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5764 if (count != (MagickOffsetType) length)
5766 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5769 UnlockSemaphoreInfo(cache_info->file_semaphore);
5775 if (y < (ssize_t) rows)
5777 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5778 cache_info->cache_filename);
5779 return(MagickFalse);
5781 if ((cache_info->debug != MagickFalse) &&
5782 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5783 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5784 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5785 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5786 nexus_info->region.x,(
double) nexus_info->region.y);
5818static MagickBooleanType WritePixelCachePixels(
5839 if (nexus_info->authentic_pixel_cache != MagickFalse)
5841 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5842 return(MagickFalse);
5843 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5844 nexus_info->region.x;
5845 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5847 extent=length*nexus_info->region.height;
5848 rows=nexus_info->region.height;
5850 p=nexus_info->pixels;
5851 switch (cache_info->type)
5862 if ((cache_info->columns == nexus_info->region.width) &&
5863 (extent == (MagickSizeType) ((
size_t) extent)))
5868 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5870 for (y=0; y < (ssize_t) rows; y++)
5872 (void) memcpy(q,p,(
size_t) length);
5873 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5874 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5883 LockSemaphoreInfo(cache_info->file_semaphore);
5884 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5886 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5887 cache_info->cache_filename);
5888 UnlockSemaphoreInfo(cache_info->file_semaphore);
5889 return(MagickFalse);
5891 if ((cache_info->columns == nexus_info->region.width) &&
5892 (extent <= MagickMaxBufferExtent))
5897 for (y=0; y < (ssize_t) rows; y++)
5899 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5900 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5901 sizeof(*p),length,(
const unsigned char *) p);
5902 if (count != (MagickOffsetType) length)
5904 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5905 offset+=(MagickOffsetType) cache_info->columns;
5907 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5908 (void) ClosePixelCacheOnDisk(cache_info);
5909 UnlockSemaphoreInfo(cache_info->file_semaphore);
5912 case DistributedCache:
5920 LockSemaphoreInfo(cache_info->file_semaphore);
5921 region=nexus_info->region;
5922 if ((cache_info->columns != nexus_info->region.width) ||
5923 (extent > MagickMaxBufferExtent))
5930 for (y=0; y < (ssize_t) rows; y++)
5933 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5934 if (count != (MagickOffsetType) length)
5936 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5939 UnlockSemaphoreInfo(cache_info->file_semaphore);
5945 if (y < (ssize_t) rows)
5947 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5948 cache_info->cache_filename);
5949 return(MagickFalse);
5951 if ((cache_info->debug != MagickFalse) &&
5952 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5953 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5954 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5955 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5956 nexus_info->region.x,(
double) nexus_info->region.y);