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(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 MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3512 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3514 if (*cache_info->cache_filename ==
'\0')
3515 file=AcquireUniqueFileResource(cache_info->cache_filename);
3521 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3526 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3527 O_BINARY | O_EXCL,S_MODE);
3529 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3535 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3538 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3543 return(MagickFalse);
3544 (void) AcquireMagickResource(FileResource,1);
3545 if (cache_info->file != -1)
3546 (void) ClosePixelCacheOnDisk(cache_info);
3547 cache_info->file=file;
3548 cache_info->disk_mode=mode;
3552static inline MagickOffsetType WritePixelCacheRegion(
3553 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3554 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3562#if !defined(MAGICKCORE_HAVE_PWRITE)
3563 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3564 return((MagickOffsetType) -1);
3566 for (i=0; i < (MagickOffsetType) length; i+=count)
3568#if !defined(MAGICKCORE_HAVE_PWRITE)
3569 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3570 (MagickSizeType) i,MagickMaxBufferExtent));
3572 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3573 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3585static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3588 *magick_restrict cache_info;
3594 if (cache_info->debug != MagickFalse)
3597 format[MagickPathExtent],
3598 message[MagickPathExtent];
3600 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3601 (void) FormatLocaleString(message,MagickPathExtent,
3602 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3603 cache_info->cache_filename,cache_info->file,format);
3604 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3606 if (length != (MagickSizeType) ((MagickOffsetType) length))
3607 return(MagickFalse);
3608 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3610 return(MagickFalse);
3611 if ((MagickSizeType) offset < length)
3617 extent=(MagickOffsetType) length-1;
3618 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3621 return(MagickFalse);
3622#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3623 if (cache_info->synchronize != MagickFalse)
3624 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3625 return(MagickFalse);
3628 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3630 return(MagickFalse);
3634static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3638 *magick_restrict cache_info,
3642 format[MagickPathExtent],
3643 message[MagickPathExtent];
3660 assert(image != (
const Image *) NULL);
3661 assert(image->signature == MagickCoreSignature);
3662 assert(image->cache != (Cache) NULL);
3663 if (IsEventLogging() != MagickFalse)
3664 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3665 if (cache_anonymous_memory < 0)
3673 cache_anonymous_memory=0;
3674 value=GetPolicyValue(
"pixel-cache-memory");
3675 if (value == (
char *) NULL)
3676 value=GetPolicyValue(
"cache:memory-map");
3677 if (LocaleCompare(value,
"anonymous") == 0)
3679#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3680 cache_anonymous_memory=1;
3682 (void) ThrowMagickException(exception,GetMagickModule(),
3683 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3684 "'%s' (policy requires anonymous memory mapping)",image->filename);
3687 value=DestroyString(value);
3689 if ((image->columns == 0) || (image->rows == 0))
3690 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3692 assert(cache_info->signature == MagickCoreSignature);
3693 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3694 ((MagickSizeType) image->rows > cache_info->height_limit))
3695 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3697 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3699 length=GetImageListLength(image);
3700 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3701 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3704 source_info=(*cache_info);
3705 source_info.file=(-1);
3706 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3707 image->filename,(
double) image->scene);
3708 cache_info->storage_class=image->storage_class;
3709 cache_info->colorspace=image->colorspace;
3710 cache_info->alpha_trait=image->alpha_trait;
3711 cache_info->channels=image->channels;
3712 cache_info->rows=image->rows;
3713 cache_info->columns=image->columns;
3714 status=ResetPixelChannelMap(image,exception);
3715 if (status == MagickFalse)
3716 return(MagickFalse);
3717 cache_info->number_channels=GetPixelChannels(image);
3718 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3719 sizeof(*image->channel_map));
3720 cache_info->metacontent_extent=image->metacontent_extent;
3721 cache_info->mode=mode;
3722 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3723 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3724 if (image->metacontent_extent != 0)
3725 packet_size+=cache_info->metacontent_extent;
3726 length=number_pixels*packet_size;
3727 columns=(size_t) (length/cache_info->rows/packet_size);
3728 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3729 ((ssize_t) cache_info->rows < 0))
3730 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3732 cache_info->length=length;
3733 if (image->ping != MagickFalse)
3735 cache_info->type=PingCache;
3738 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3739 cache_info->columns*cache_info->rows);
3740 if (cache_info->mode == PersistMode)
3742 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3743 cache_info->metacontent_extent);
3744 if ((status != MagickFalse) &&
3745 (length == (MagickSizeType) ((
size_t) length)) &&
3746 ((cache_info->type == UndefinedCache) ||
3747 (cache_info->type == MemoryCache)))
3749 status=AcquireMagickResource(MemoryResource,cache_info->length);
3750 if (status != MagickFalse)
3753 if (cache_anonymous_memory <= 0)
3755 cache_info->mapped=MagickFalse;
3756 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3757 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3761 cache_info->mapped=MagickTrue;
3762 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3763 cache_info->length);
3765 if (cache_info->pixels == (Quantum *) NULL)
3767 cache_info->mapped=source_info.mapped;
3768 cache_info->pixels=source_info.pixels;
3775 cache_info->type=MemoryCache;
3776 cache_info->metacontent=(
void *) NULL;
3777 if (cache_info->metacontent_extent != 0)
3778 cache_info->metacontent=(
void *) (cache_info->pixels+
3779 cache_info->number_channels*number_pixels);
3780 if ((source_info.storage_class != UndefinedClass) &&
3783 status=ClonePixelCacheRepository(cache_info,&source_info,
3785 RelinquishPixelCachePixels(&source_info);
3787 if (cache_info->debug != MagickFalse)
3789 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3790 MagickPathExtent,format);
3791 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3793 (void) FormatLocaleString(message,MagickPathExtent,
3794 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3795 cache_info->filename,cache_info->mapped != MagickFalse ?
3796 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3797 (
double) cache_info->rows,(
double)
3798 cache_info->number_channels,format);
3799 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3802 cache_info->storage_class=image->storage_class;
3805 if ((source_info.storage_class != UndefinedClass) &&
3807 RelinquishPixelCachePixels(&source_info);
3808 cache_info->type=UndefinedCache;
3809 return(MagickFalse);
3815 status=AcquireMagickResource(DiskResource,cache_info->length);
3816 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3818 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3826 server_info=AcquireDistributeCacheInfo(exception);
3829 status=OpenDistributePixelCache(server_info,image);
3830 if (status == MagickFalse)
3832 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3833 GetDistributeCacheHostname(server_info));
3834 server_info=DestroyDistributeCacheInfo(server_info);
3842 cache_info->type=DistributedCache;
3843 cache_info->server_info=server_info;
3844 (void) FormatLocaleString(cache_info->cache_filename,
3845 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3848 cache_info->server_info));
3849 if ((source_info.storage_class != UndefinedClass) &&
3852 status=ClonePixelCacheRepository(cache_info,&source_info,
3854 RelinquishPixelCachePixels(&source_info);
3856 if (cache_info->debug != MagickFalse)
3858 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3859 MagickPathExtent,format);
3860 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3862 (void) FormatLocaleString(message,MagickPathExtent,
3863 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3864 cache_info->filename,cache_info->cache_filename,
3866 cache_info->server_info),type,(
double) cache_info->columns,
3867 (
double) cache_info->rows,(
double)
3868 cache_info->number_channels,format);
3869 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3874 if ((source_info.storage_class != UndefinedClass) &&
3876 RelinquishPixelCachePixels(&source_info);
3877 cache_info->type=UndefinedCache;
3878 return(MagickFalse);
3883 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3884 RelinquishPixelCachePixels(&source_info);
3885 cache_info->type=UndefinedCache;
3886 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3887 "CacheResourcesExhausted",
"`%s'",image->filename);
3888 return(MagickFalse);
3893 if (status == MagickFalse)
3895 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3896 RelinquishPixelCachePixels(&source_info);
3897 cache_info->type=UndefinedCache;
3898 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3899 "CacheResourcesExhausted",
"`%s'",image->filename);
3900 return(MagickFalse);
3902 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3903 (cache_info->mode != PersistMode))
3905 (void) ClosePixelCacheOnDisk(cache_info);
3906 *cache_info->cache_filename=
'\0';
3908 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3910 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3911 RelinquishPixelCachePixels(&source_info);
3912 cache_info->type=UndefinedCache;
3913 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3915 return(MagickFalse);
3917 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3918 cache_info->length);
3919 if (status == MagickFalse)
3921 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3922 RelinquishPixelCachePixels(&source_info);
3923 cache_info->type=UndefinedCache;
3924 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3926 return(MagickFalse);
3928 cache_info->type=DiskCache;
3929 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3930 cache_info->metacontent_extent);
3931 if (length == (MagickSizeType) ((
size_t) length))
3933 status=AcquireMagickResource(MapResource,cache_info->length);
3934 if (status != MagickFalse)
3936 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3937 cache_info->offset,(
size_t) cache_info->length);
3938 if (cache_info->pixels == (Quantum *) NULL)
3940 cache_info->mapped=source_info.mapped;
3941 cache_info->pixels=source_info.pixels;
3942 RelinquishMagickResource(MapResource,cache_info->length);
3949 (void) ClosePixelCacheOnDisk(cache_info);
3950 cache_info->type=MapCache;
3951 cache_info->mapped=MagickTrue;
3952 cache_info->metacontent=(
void *) NULL;
3953 if (cache_info->metacontent_extent != 0)
3954 cache_info->metacontent=(
void *) (cache_info->pixels+
3955 cache_info->number_channels*number_pixels);
3956 if ((source_info.storage_class != UndefinedClass) &&
3959 status=ClonePixelCacheRepository(cache_info,&source_info,
3961 RelinquishPixelCachePixels(&source_info);
3963 if (cache_info->debug != MagickFalse)
3965 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3966 MagickPathExtent,format);
3967 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3969 (void) FormatLocaleString(message,MagickPathExtent,
3970 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3971 cache_info->filename,cache_info->cache_filename,
3972 cache_info->file,type,(
double) cache_info->columns,
3973 (
double) cache_info->rows,(
double)
3974 cache_info->number_channels,format);
3975 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3980 if ((source_info.storage_class != UndefinedClass) &&
3982 RelinquishPixelCachePixels(&source_info);
3983 cache_info->type=UndefinedCache;
3984 return(MagickFalse);
3991 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3993 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3994 RelinquishPixelCachePixels(&source_info);
3996 if (cache_info->debug != MagickFalse)
3998 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3999 MagickPathExtent,format);
4000 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4002 (void) FormatLocaleString(message,MagickPathExtent,
4003 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4004 cache_info->cache_filename,cache_info->file,type,(
double)
4005 cache_info->columns,(
double) cache_info->rows,(
double)
4006 cache_info->number_channels,format);
4007 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4011 cache_info->type=UndefinedCache;
4012 return(MagickFalse);
4054MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4055 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4059 *magick_restrict cache_info,
4060 *magick_restrict clone_info;
4068 assert(image != (
Image *) NULL);
4069 assert(image->signature == MagickCoreSignature);
4070 if (IsEventLogging() != MagickFalse)
4071 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4072 assert(image->cache != (
void *) NULL);
4073 assert(filename != (
const char *) NULL);
4074 assert(offset != (MagickOffsetType *) NULL);
4075 page_size=GetMagickPageSize();
4077 assert(cache_info->signature == MagickCoreSignature);
4078#if defined(MAGICKCORE_OPENCL_SUPPORT)
4079 CopyOpenCLBuffer(cache_info);
4081 if (attach != MagickFalse)
4086 if (cache_info->debug != MagickFalse)
4087 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4088 "attach persistent cache");
4089 (void) CopyMagickString(cache_info->cache_filename,filename,
4091 cache_info->type=MapCache;
4092 cache_info->offset=(*offset);
4093 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4094 return(MagickFalse);
4095 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4096 ((MagickOffsetType) cache_info->length % page_size));
4102 status=AcquireMagickResource(DiskResource,cache_info->length);
4103 if (status == MagickFalse)
4105 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4106 "CacheResourcesExhausted",
"`%s'",image->filename);
4107 return(MagickFalse);
4109 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4110 clone_info->type=DiskCache;
4111 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4112 clone_info->file=(-1);
4113 clone_info->storage_class=cache_info->storage_class;
4114 clone_info->colorspace=cache_info->colorspace;
4115 clone_info->alpha_trait=cache_info->alpha_trait;
4116 clone_info->channels=cache_info->channels;
4117 clone_info->columns=cache_info->columns;
4118 clone_info->rows=cache_info->rows;
4119 clone_info->number_channels=cache_info->number_channels;
4120 clone_info->metacontent_extent=cache_info->metacontent_extent;
4121 clone_info->mode=PersistMode;
4122 clone_info->length=cache_info->length;
4123 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4124 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4125 clone_info->offset=(*offset);
4126 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4127 if (status != MagickFalse)
4128 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4129 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4130 ((MagickOffsetType) cache_info->length % page_size));
4131 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4173MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4174 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4178 *magick_restrict cache_info;
4187 *magick_restrict pixels;
4192 assert(image != (
const Image *) NULL);
4193 assert(image->signature == MagickCoreSignature);
4194 assert(image->cache != (Cache) NULL);
4195 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4196 if (cache_info == (Cache) NULL)
4197 return((Quantum *) NULL);
4198 assert(cache_info->signature == MagickCoreSignature);
4199 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4200 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4201 (y >= (ssize_t) cache_info->rows))
4203 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4204 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4205 return((Quantum *) NULL);
4207 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4208 return((Quantum *) NULL);
4209 offset=y*(MagickOffsetType) cache_info->columns+x;
4211 return((Quantum *) NULL);
4212 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4213 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4214 (MagickOffsetType) columns-1;
4215 if ((MagickSizeType) offset >= number_pixels)
4216 return((Quantum *) NULL);
4220 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4221 ((image->channels & WriteMaskChannel) != 0) ||
4222 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4223 nexus_info,exception);
4260static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4261 const ssize_t y,
const size_t columns,
const size_t rows,
4265 *magick_restrict cache_info;
4268 id = GetOpenMPThreadId();
4271 *magick_restrict pixels;
4273 assert(image != (
const Image *) NULL);
4274 assert(image->signature == MagickCoreSignature);
4275 assert(image->cache != (Cache) NULL);
4277 assert(cache_info->signature == MagickCoreSignature);
4278 assert(
id < (
int) cache_info->number_threads);
4279 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4280 cache_info->nexus_info[
id],exception);
4340MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4341 const ssize_t y,
const size_t columns,
const size_t rows,
4345 *magick_restrict cache_info;
4348 id = GetOpenMPThreadId();
4351 *magick_restrict pixels;
4353 assert(image != (
Image *) NULL);
4354 assert(image->signature == MagickCoreSignature);
4355 assert(image->cache != (Cache) NULL);
4357 assert(cache_info->signature == MagickCoreSignature);
4358 if (cache_info->methods.queue_authentic_pixels_handler !=
4359 (QueueAuthenticPixelsHandler) NULL)
4361 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4362 columns,rows,exception);
4365 assert(
id < (
int) cache_info->number_threads);
4366 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4367 cache_info->nexus_info[
id],exception);
4400static inline MagickOffsetType ReadPixelCacheRegion(
4401 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4402 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4410#if !defined(MAGICKCORE_HAVE_PREAD)
4411 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4412 return((MagickOffsetType) -1);
4414 for (i=0; i < (MagickOffsetType) length; i+=count)
4416#if !defined(MAGICKCORE_HAVE_PREAD)
4417 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4418 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4420 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4421 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4433static MagickBooleanType ReadPixelCacheMetacontent(
4454 if (cache_info->metacontent_extent == 0)
4455 return(MagickFalse);
4456 if (nexus_info->authentic_pixel_cache != MagickFalse)
4458 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4459 return(MagickFalse);
4460 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4461 nexus_info->region.x;
4462 length=(MagickSizeType) nexus_info->region.width*
4463 cache_info->metacontent_extent;
4464 extent=length*nexus_info->region.height;
4465 rows=nexus_info->region.height;
4467 q=(
unsigned char *) nexus_info->metacontent;
4468 switch (cache_info->type)
4479 if ((cache_info->columns == nexus_info->region.width) &&
4480 (extent == (MagickSizeType) ((
size_t) extent)))
4485 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4486 cache_info->metacontent_extent;
4487 for (y=0; y < (ssize_t) rows; y++)
4489 (void) memcpy(q,p,(
size_t) length);
4490 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4491 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4500 LockSemaphoreInfo(cache_info->file_semaphore);
4501 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4503 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4504 cache_info->cache_filename);
4505 UnlockSemaphoreInfo(cache_info->file_semaphore);
4506 return(MagickFalse);
4508 if ((cache_info->columns == nexus_info->region.width) &&
4509 (extent <= MagickMaxBufferExtent))
4514 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4515 for (y=0; y < (ssize_t) rows; y++)
4517 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4518 (MagickOffsetType) extent*(MagickOffsetType)
4519 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4520 (MagickOffsetType) cache_info->metacontent_extent,length,
4521 (
unsigned char *) q);
4522 if (count != (MagickOffsetType) length)
4524 offset+=(MagickOffsetType) cache_info->columns;
4525 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4527 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4528 (void) ClosePixelCacheOnDisk(cache_info);
4529 UnlockSemaphoreInfo(cache_info->file_semaphore);
4532 case DistributedCache:
4540 LockSemaphoreInfo(cache_info->file_semaphore);
4541 region=nexus_info->region;
4542 if ((cache_info->columns != nexus_info->region.width) ||
4543 (extent > MagickMaxBufferExtent))
4550 for (y=0; y < (ssize_t) rows; y++)
4553 cache_info->server_info,®ion,length,(
unsigned char *) q);
4554 if (count != (MagickOffsetType) length)
4556 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4559 UnlockSemaphoreInfo(cache_info->file_semaphore);
4565 if (y < (ssize_t) rows)
4567 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4568 cache_info->cache_filename);
4569 return(MagickFalse);
4571 if ((cache_info->debug != MagickFalse) &&
4572 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4573 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4574 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4575 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4576 nexus_info->region.x,(
double) nexus_info->region.y);
4608static MagickBooleanType ReadPixelCachePixels(
4630 if (nexus_info->authentic_pixel_cache != MagickFalse)
4632 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4633 return(MagickFalse);
4634 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4635 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4636 return(MagickFalse);
4637 offset+=nexus_info->region.x;
4638 number_channels=cache_info->number_channels;
4639 length=(MagickSizeType) number_channels*nexus_info->region.width*
4641 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4642 return(MagickFalse);
4643 rows=nexus_info->region.height;
4645 if ((extent == 0) || ((extent/length) != rows))
4646 return(MagickFalse);
4648 q=nexus_info->pixels;
4649 switch (cache_info->type)
4660 if ((cache_info->columns == nexus_info->region.width) &&
4661 (extent == (MagickSizeType) ((
size_t) extent)))
4666 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4668 for (y=0; y < (ssize_t) rows; y++)
4670 (void) memcpy(q,p,(
size_t) length);
4671 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4672 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4681 LockSemaphoreInfo(cache_info->file_semaphore);
4682 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4684 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4685 cache_info->cache_filename);
4686 UnlockSemaphoreInfo(cache_info->file_semaphore);
4687 return(MagickFalse);
4689 if ((cache_info->columns == nexus_info->region.width) &&
4690 (extent <= MagickMaxBufferExtent))
4695 for (y=0; y < (ssize_t) rows; y++)
4697 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4698 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4699 sizeof(*q),length,(
unsigned char *) q);
4700 if (count != (MagickOffsetType) length)
4702 offset+=(MagickOffsetType) cache_info->columns;
4703 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4705 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4706 (void) ClosePixelCacheOnDisk(cache_info);
4707 UnlockSemaphoreInfo(cache_info->file_semaphore);
4710 case DistributedCache:
4718 LockSemaphoreInfo(cache_info->file_semaphore);
4719 region=nexus_info->region;
4720 if ((cache_info->columns != nexus_info->region.width) ||
4721 (extent > MagickMaxBufferExtent))
4728 for (y=0; y < (ssize_t) rows; y++)
4731 cache_info->server_info,®ion,length,(
unsigned char *) q);
4732 if (count != (MagickOffsetType) length)
4734 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4737 UnlockSemaphoreInfo(cache_info->file_semaphore);
4743 if (y < (ssize_t) rows)
4745 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4746 cache_info->cache_filename);
4747 return(MagickFalse);
4749 if ((cache_info->debug != MagickFalse) &&
4750 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4751 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4752 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4753 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4754 nexus_info->region.x,(
double) nexus_info->region.y);
4781MagickPrivate Cache ReferencePixelCache(Cache cache)
4784 *magick_restrict cache_info;
4786 assert(cache != (Cache *) NULL);
4788 assert(cache_info->signature == MagickCoreSignature);
4789 LockSemaphoreInfo(cache_info->semaphore);
4790 cache_info->reference_count++;
4791 UnlockSemaphoreInfo(cache_info->semaphore);
4817MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4820 *magick_restrict cache_info;
4822 assert(image != (
const Image *) NULL);
4823 assert(image->signature == MagickCoreSignature);
4824 assert(image->cache != (Cache) NULL);
4826 assert(cache_info->signature == MagickCoreSignature);
4827 cache_info->number_channels=GetPixelChannels(image);
4848MagickPrivate
void ResetCacheAnonymousMemory(
void)
4850 cache_anonymous_memory=0;
4882MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4883 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4891 assert(image != (
Image *) NULL);
4892 assert(image->signature == MagickCoreSignature);
4893 if (IsEventLogging() != MagickFalse)
4894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4895 assert(image->cache != (
void *) NULL);
4896 extent=(MagickSizeType) columns*rows;
4897 if (extent > ((MagickSizeType) image->columns*image->rows))
4898 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4900 image->columns=columns;
4903 cache_info->columns=columns;
4904 cache_info->rows=rows;
4905 return(SyncImagePixelCache(image,exception));
4932MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4935 *magick_restrict cache_info;
4937 GetOneAuthenticPixelFromHandler
4938 get_one_authentic_pixel_from_handler;
4940 GetOneVirtualPixelFromHandler
4941 get_one_virtual_pixel_from_handler;
4946 assert(cache != (Cache) NULL);
4949 assert(cache_info->signature == MagickCoreSignature);
4950 if (IsEventLogging() != MagickFalse)
4951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4952 cache_info->filename);
4953 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4954 cache_info->methods.get_virtual_pixel_handler=
4955 cache_methods->get_virtual_pixel_handler;
4956 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4957 cache_info->methods.destroy_pixel_handler=
4958 cache_methods->destroy_pixel_handler;
4959 if (cache_methods->get_virtual_metacontent_from_handler !=
4960 (GetVirtualMetacontentFromHandler) NULL)
4961 cache_info->methods.get_virtual_metacontent_from_handler=
4962 cache_methods->get_virtual_metacontent_from_handler;
4963 if (cache_methods->get_authentic_pixels_handler !=
4964 (GetAuthenticPixelsHandler) NULL)
4965 cache_info->methods.get_authentic_pixels_handler=
4966 cache_methods->get_authentic_pixels_handler;
4967 if (cache_methods->queue_authentic_pixels_handler !=
4968 (QueueAuthenticPixelsHandler) NULL)
4969 cache_info->methods.queue_authentic_pixels_handler=
4970 cache_methods->queue_authentic_pixels_handler;
4971 if (cache_methods->sync_authentic_pixels_handler !=
4972 (SyncAuthenticPixelsHandler) NULL)
4973 cache_info->methods.sync_authentic_pixels_handler=
4974 cache_methods->sync_authentic_pixels_handler;
4975 if (cache_methods->get_authentic_pixels_from_handler !=
4976 (GetAuthenticPixelsFromHandler) NULL)
4977 cache_info->methods.get_authentic_pixels_from_handler=
4978 cache_methods->get_authentic_pixels_from_handler;
4979 if (cache_methods->get_authentic_metacontent_from_handler !=
4980 (GetAuthenticMetacontentFromHandler) NULL)
4981 cache_info->methods.get_authentic_metacontent_from_handler=
4982 cache_methods->get_authentic_metacontent_from_handler;
4983 get_one_virtual_pixel_from_handler=
4984 cache_info->methods.get_one_virtual_pixel_from_handler;
4985 if (get_one_virtual_pixel_from_handler !=
4986 (GetOneVirtualPixelFromHandler) NULL)
4987 cache_info->methods.get_one_virtual_pixel_from_handler=
4988 cache_methods->get_one_virtual_pixel_from_handler;
4989 get_one_authentic_pixel_from_handler=
4990 cache_methods->get_one_authentic_pixel_from_handler;
4991 if (get_one_authentic_pixel_from_handler !=
4992 (GetOneAuthenticPixelFromHandler) NULL)
4993 cache_info->methods.get_one_authentic_pixel_from_handler=
4994 cache_methods->get_one_authentic_pixel_from_handler;
5035static inline MagickBooleanType AcquireCacheNexusPixels(
5036 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5039 if (length != (MagickSizeType) ((
size_t) length))
5041 (void) ThrowMagickException(exception,GetMagickModule(),
5042 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5043 cache_info->filename);
5044 return(MagickFalse);
5046 nexus_info->length=0;
5047 nexus_info->mapped=MagickFalse;
5048 if (cache_anonymous_memory <= 0)
5050 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5052 if (nexus_info->cache != (Quantum *) NULL)
5053 (void) memset(nexus_info->cache,0,(
size_t) length);
5057 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5058 if (nexus_info->cache != (Quantum *) NULL)
5059 nexus_info->mapped=MagickTrue;
5061 if (nexus_info->cache == (Quantum *) NULL)
5063 (void) ThrowMagickException(exception,GetMagickModule(),
5064 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5065 cache_info->filename);
5066 return(MagickFalse);
5068 nexus_info->length=length;
5072static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5075 if (nexus_info->length < CACHE_LINE_SIZE)
5077 if (mode == ReadMode)
5079 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5083 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5086static Quantum *SetPixelCacheNexusPixels(
5087 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5088 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5089 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5099 assert(cache_info != (
const CacheInfo *) NULL);
5100 assert(cache_info->signature == MagickCoreSignature);
5101 if (cache_info->type == UndefinedCache)
5102 return((Quantum *) NULL);
5103 assert(nexus_info->signature == MagickCoreSignature);
5104 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5105 if ((width == 0) || (height == 0))
5107 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5108 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5109 return((Quantum *) NULL);
5111 if (((MagickSizeType) width > cache_info->width_limit) ||
5112 ((MagickSizeType) height > cache_info->height_limit))
5114 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5115 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5116 return((Quantum *) NULL);
5118 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5119 (IsValidPixelOffset(y,height) == MagickFalse))
5121 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5122 "InvalidPixel",
"`%s'",cache_info->filename);
5123 return((Quantum *) NULL);
5125 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5126 (buffered == MagickFalse))
5128 if (((x >= 0) && (y >= 0) &&
5129 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5130 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5131 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5139 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5140 return((Quantum *) NULL);
5141 offset=y*(MagickOffsetType) cache_info->columns+x;
5142 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5143 cache_info->number_channels*offset;
5144 nexus_info->metacontent=(
void *) NULL;
5145 if (cache_info->metacontent_extent != 0)
5146 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5147 offset*(MagickOffsetType) cache_info->metacontent_extent;
5148 nexus_info->region.width=width;
5149 nexus_info->region.height=height;
5150 nexus_info->region.x=x;
5151 nexus_info->region.y=y;
5152 nexus_info->authentic_pixel_cache=MagickTrue;
5153 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5154 return(nexus_info->pixels);
5160 number_pixels=(MagickSizeType) width*height;
5161 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5162 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5163 if (cache_info->metacontent_extent != 0)
5164 length+=number_pixels*cache_info->metacontent_extent;
5166 if (nexus_info->cache == (Quantum *) NULL)
5167 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5169 if (nexus_info->length < length)
5171 RelinquishCacheNexusPixels(nexus_info);
5172 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5174 if (status == MagickFalse)
5175 return((Quantum *) NULL);
5176 nexus_info->pixels=nexus_info->cache;
5177 nexus_info->metacontent=(
void *) NULL;
5178 if (cache_info->metacontent_extent != 0)
5179 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5180 cache_info->number_channels*number_pixels);
5181 nexus_info->region.width=width;
5182 nexus_info->region.height=height;
5183 nexus_info->region.x=x;
5184 nexus_info->region.y=y;
5185 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5186 MagickTrue : MagickFalse;
5187 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5188 return(nexus_info->pixels);
5221static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5225 *magick_restrict image_view;
5233 assert(image != (
Image *) NULL);
5234 assert(image->signature == MagickCoreSignature);
5235 if (IsEventLogging() != MagickFalse)
5236 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5237 assert(image->cache != (Cache) NULL);
5238 image->alpha_trait=BlendPixelTrait;
5240 image_view=AcquireVirtualCacheView(image,exception);
5241#if defined(MAGICKCORE_OPENMP_SUPPORT)
5242 #pragma omp parallel for schedule(static) shared(status) \
5243 magick_number_threads(image,image,image->rows,2)
5245 for (y=0; y < (ssize_t) image->rows; y++)
5253 if (status == MagickFalse)
5255 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5256 if (q == (Quantum *) NULL)
5261 for (x=0; x < (ssize_t) image->columns; x++)
5263 SetPixelAlpha(image,alpha,q);
5264 q+=(ptrdiff_t) GetPixelChannels(image);
5266 status=SyncCacheViewAuthenticPixels(image_view,exception);
5268 image_view=DestroyCacheView(image_view);
5272MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5273 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5276 *magick_restrict cache_info;
5281 assert(image != (
Image *) NULL);
5282 assert(image->signature == MagickCoreSignature);
5283 if (IsEventLogging() != MagickFalse)
5284 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5285 assert(image->cache != (Cache) NULL);
5287 assert(cache_info->signature == MagickCoreSignature);
5288 method=cache_info->virtual_pixel_method;
5289 cache_info->virtual_pixel_method=virtual_pixel_method;
5290 if ((image->columns != 0) && (image->rows != 0))
5291 switch (virtual_pixel_method)
5293 case BackgroundVirtualPixelMethod:
5295 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5296 ((image->alpha_trait & BlendPixelTrait) == 0))
5297 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5298 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5299 (IsGrayColorspace(image->colorspace) != MagickFalse))
5300 (void) SetImageColorspace(image,sRGBColorspace,exception);
5303 case TransparentVirtualPixelMethod:
5305 if ((image->alpha_trait & BlendPixelTrait) == 0)
5306 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5315#if defined(MAGICKCORE_OPENCL_SUPPORT)
5340static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5342 assert(cache_info != (
CacheInfo *) NULL);
5343 assert(cache_info->signature == MagickCoreSignature);
5344 if ((cache_info->type != MemoryCache) ||
5345 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5350 LockSemaphoreInfo(cache_info->semaphore);
5351 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5352 UnlockSemaphoreInfo(cache_info->semaphore);
5355MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5358 *magick_restrict cache_info;
5360 assert(image != (
const Image *) NULL);
5362 CopyOpenCLBuffer(cache_info);
5395MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5399 *magick_restrict cache_info;
5407 assert(image != (
Image *) NULL);
5408 assert(image->signature == MagickCoreSignature);
5409 if (image->cache == (Cache) NULL)
5410 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5412 assert(cache_info->signature == MagickCoreSignature);
5413 if (cache_info->type == UndefinedCache)
5414 return(MagickFalse);
5415 if (image->mask_trait != UpdatePixelTrait)
5417 if (((image->channels & WriteMaskChannel) != 0) &&
5418 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5419 return(MagickFalse);
5420 if (((image->channels & CompositeMaskChannel) != 0) &&
5421 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5422 return(MagickFalse);
5424 if (nexus_info->authentic_pixel_cache != MagickFalse)
5426 if (image->taint == MagickFalse)
5427 image->taint=MagickTrue;
5430 assert(cache_info->signature == MagickCoreSignature);
5431 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5432 if ((cache_info->metacontent_extent != 0) &&
5433 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5434 return(MagickFalse);
5435 if ((status != MagickFalse) && (image->taint == MagickFalse))
5436 image->taint=MagickTrue;
5467static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5471 *magick_restrict cache_info;
5474 id = GetOpenMPThreadId();
5479 assert(image != (
Image *) NULL);
5480 assert(image->signature == MagickCoreSignature);
5481 assert(image->cache != (Cache) NULL);
5483 assert(cache_info->signature == MagickCoreSignature);
5484 assert(
id < (
int) cache_info->number_threads);
5485 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5517MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5521 *magick_restrict cache_info;
5524 id = GetOpenMPThreadId();
5529 assert(image != (
Image *) NULL);
5530 assert(image->signature == MagickCoreSignature);
5531 assert(image->cache != (Cache) NULL);
5533 assert(cache_info->signature == MagickCoreSignature);
5534 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5536 status=cache_info->methods.sync_authentic_pixels_handler(image,
5540 assert(
id < (
int) cache_info->number_threads);
5541 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5573MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5577 *magick_restrict cache_info;
5579 assert(image != (
Image *) NULL);
5581 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5582 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5613static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5633 if (cache_info->metacontent_extent == 0)
5634 return(MagickFalse);
5635 if (nexus_info->authentic_pixel_cache != MagickFalse)
5637 if (nexus_info->metacontent == (
unsigned char *) NULL)
5638 return(MagickFalse);
5639 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5640 return(MagickFalse);
5641 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5642 nexus_info->region.x;
5643 length=(MagickSizeType) nexus_info->region.width*
5644 cache_info->metacontent_extent;
5645 extent=(MagickSizeType) length*nexus_info->region.height;
5646 rows=nexus_info->region.height;
5648 p=(
unsigned char *) nexus_info->metacontent;
5649 switch (cache_info->type)
5660 if ((cache_info->columns == nexus_info->region.width) &&
5661 (extent == (MagickSizeType) ((
size_t) extent)))
5666 q=(
unsigned char *) cache_info->metacontent+offset*
5667 (MagickOffsetType) cache_info->metacontent_extent;
5668 for (y=0; y < (ssize_t) rows; y++)
5670 (void) memcpy(q,p,(
size_t) length);
5671 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5672 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5681 LockSemaphoreInfo(cache_info->file_semaphore);
5682 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5684 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5685 cache_info->cache_filename);
5686 UnlockSemaphoreInfo(cache_info->file_semaphore);
5687 return(MagickFalse);
5689 if ((cache_info->columns == nexus_info->region.width) &&
5690 (extent <= MagickMaxBufferExtent))
5695 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5696 for (y=0; y < (ssize_t) rows; y++)
5698 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5699 (MagickOffsetType) extent*(MagickOffsetType)
5700 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5701 (MagickOffsetType) cache_info->metacontent_extent,length,
5702 (
const unsigned char *) p);
5703 if (count != (MagickOffsetType) length)
5705 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5706 offset+=(MagickOffsetType) cache_info->columns;
5708 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5709 (void) ClosePixelCacheOnDisk(cache_info);
5710 UnlockSemaphoreInfo(cache_info->file_semaphore);
5713 case DistributedCache:
5721 LockSemaphoreInfo(cache_info->file_semaphore);
5722 region=nexus_info->region;
5723 if ((cache_info->columns != nexus_info->region.width) ||
5724 (extent > MagickMaxBufferExtent))
5731 for (y=0; y < (ssize_t) rows; y++)
5734 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5735 if (count != (MagickOffsetType) length)
5737 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5740 UnlockSemaphoreInfo(cache_info->file_semaphore);
5746 if (y < (ssize_t) rows)
5748 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5749 cache_info->cache_filename);
5750 return(MagickFalse);
5752 if ((cache_info->debug != MagickFalse) &&
5753 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5754 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5755 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5756 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5757 nexus_info->region.x,(
double) nexus_info->region.y);
5789static MagickBooleanType WritePixelCachePixels(
5810 if (nexus_info->authentic_pixel_cache != MagickFalse)
5812 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5813 return(MagickFalse);
5814 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5815 nexus_info->region.x;
5816 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5818 extent=length*nexus_info->region.height;
5819 rows=nexus_info->region.height;
5821 p=nexus_info->pixels;
5822 switch (cache_info->type)
5833 if ((cache_info->columns == nexus_info->region.width) &&
5834 (extent == (MagickSizeType) ((
size_t) extent)))
5839 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5841 for (y=0; y < (ssize_t) rows; y++)
5843 (void) memcpy(q,p,(
size_t) length);
5844 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5845 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5854 LockSemaphoreInfo(cache_info->file_semaphore);
5855 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5857 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5858 cache_info->cache_filename);
5859 UnlockSemaphoreInfo(cache_info->file_semaphore);
5860 return(MagickFalse);
5862 if ((cache_info->columns == nexus_info->region.width) &&
5863 (extent <= MagickMaxBufferExtent))
5868 for (y=0; y < (ssize_t) rows; y++)
5870 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5871 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5872 sizeof(*p),length,(
const unsigned char *) p);
5873 if (count != (MagickOffsetType) length)
5875 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5876 offset+=(MagickOffsetType) cache_info->columns;
5878 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5879 (void) ClosePixelCacheOnDisk(cache_info);
5880 UnlockSemaphoreInfo(cache_info->file_semaphore);
5883 case DistributedCache:
5891 LockSemaphoreInfo(cache_info->file_semaphore);
5892 region=nexus_info->region;
5893 if ((cache_info->columns != nexus_info->region.width) ||
5894 (extent > MagickMaxBufferExtent))
5901 for (y=0; y < (ssize_t) rows; y++)
5904 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5905 if (count != (MagickOffsetType) length)
5907 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5910 UnlockSemaphoreInfo(cache_info->file_semaphore);
5916 if (y < (ssize_t) rows)
5918 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5919 cache_info->cache_filename);
5920 return(MagickFalse);
5922 if ((cache_info->debug != MagickFalse) &&
5923 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5924 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5925 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5926 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5927 nexus_info->region.x,(
double) nexus_info->region.y);