43#include "MagickCore/studio.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/cache-private.h"
48#include "MagickCore/color-private.h"
49#include "MagickCore/colorspace-private.h"
50#include "MagickCore/composite-private.h"
51#include "MagickCore/distribute-cache-private.h"
52#include "MagickCore/exception.h"
53#include "MagickCore/exception-private.h"
54#include "MagickCore/geometry.h"
55#include "MagickCore/list.h"
56#include "MagickCore/log.h"
57#include "MagickCore/magick.h"
58#include "MagickCore/memory_.h"
59#include "MagickCore/memory-private.h"
60#include "MagickCore/nt-base-private.h"
61#include "MagickCore/option.h"
62#include "MagickCore/pixel.h"
63#include "MagickCore/pixel-accessor.h"
64#include "MagickCore/pixel-private.h"
65#include "MagickCore/policy.h"
66#include "MagickCore/quantum.h"
67#include "MagickCore/random_.h"
68#include "MagickCore/registry.h"
69#include "MagickCore/resource_.h"
70#include "MagickCore/semaphore.h"
71#include "MagickCore/splay-tree.h"
72#include "MagickCore/string_.h"
73#include "MagickCore/string-private.h"
74#include "MagickCore/timer-private.h"
75#include "MagickCore/thread-private.h"
76#include "MagickCore/utility.h"
77#include "MagickCore/utility-private.h"
78#if defined(MAGICKCORE_ZLIB_DELEGATE)
85#define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
86#define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
87 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
102#if defined(__cplusplus) || defined(c_plusplus)
111 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
113 *GetVirtualPixelsCache(
const Image *);
116 *GetVirtualMetacontentFromCache(
const Image *);
118static MagickBooleanType
119 GetOneAuthenticPixelFromCache(
Image *,
const ssize_t,
const ssize_t,Quantum *,
121 GetOneVirtualPixelFromCache(
const Image *,
const VirtualPixelMethod,
124 OpenPixelCacheOnDisk(
CacheInfo *,
const MapMode),
127 ReadPixelCacheMetacontent(
CacheInfo *magick_restrict,
136 *GetAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
138 *QueueAuthenticPixelsCache(
Image *,
const ssize_t,
const ssize_t,
const size_t,
140 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
141 const ssize_t,
const ssize_t,
const size_t,
const size_t,
145#if defined(MAGICKCORE_OPENCL_SUPPORT)
147 CopyOpenCLBuffer(
CacheInfo *magick_restrict);
150#if defined(__cplusplus) || defined(c_plusplus)
161 cache_anonymous_memory = (-1);
185MagickPrivate Cache AcquirePixelCache(
const size_t number_threads)
188 *magick_restrict cache_info;
193 cache_info=(
CacheInfo *) AcquireAlignedMemory(1,
sizeof(*cache_info));
195 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
196 (void) memset(cache_info,0,
sizeof(*cache_info));
197 cache_info->type=UndefinedCache;
198 cache_info->mode=IOMode;
199 cache_info->disk_mode=IOMode;
200 cache_info->colorspace=sRGBColorspace;
201 cache_info->file=(-1);
202 cache_info->id=GetMagickThreadId();
203 cache_info->number_threads=number_threads;
204 if (GetOpenMPMaximumThreads() > cache_info->number_threads)
205 cache_info->number_threads=GetOpenMPMaximumThreads();
206 if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
207 cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
208 if (cache_info->number_threads == 0)
209 cache_info->number_threads=1;
210 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
211 if (cache_info->nexus_info == (
NexusInfo **) NULL)
212 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
213 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
214 if (value != (
const char *) NULL)
216 cache_info->synchronize=IsStringTrue(value);
217 value=DestroyString(value);
219 value=GetPolicyValue(
"cache:synchronize");
220 if (value != (
const char *) NULL)
222 cache_info->synchronize=IsStringTrue(value);
223 value=DestroyString(value);
225 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
226 (MagickSizeType) MAGICK_SSIZE_MAX);
227 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
228 (MagickSizeType) MAGICK_SSIZE_MAX);
229 cache_info->semaphore=AcquireSemaphoreInfo();
230 cache_info->reference_count=1;
231 cache_info->file_semaphore=AcquireSemaphoreInfo();
232 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
234 cache_info->signature=MagickCoreSignature;
235 return((Cache ) cache_info);
260MagickPrivate
NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
263 **magick_restrict nexus_info;
268 nexus_info=(
NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
269 number_threads,
sizeof(*nexus_info)));
271 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
272 *nexus_info=(
NexusInfo *) AcquireQuantumMemory(number_threads,
273 2*
sizeof(**nexus_info));
275 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
276 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
277 for (i=0; i < (ssize_t) (2*number_threads); i++)
279 nexus_info[i]=(*nexus_info+i);
280 if (i < (ssize_t) number_threads)
281 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
282 nexus_info[i]->signature=MagickCoreSignature;
315MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
319 *magick_restrict cache_info;
321 assert(image != (
const Image *) NULL);
322 assert(image->signature == MagickCoreSignature);
324 assert(exception->signature == MagickCoreSignature);
325 assert(image->cache != (Cache) NULL);
328 assert(cache_info->signature == MagickCoreSignature);
330 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
331 return((
void *) NULL);
332 *length=(size_t) cache_info->length;
333 return(cache_info->pixels);
354MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
357 cache_semaphore=AcquireSemaphoreInfo();
379MagickPrivate
void CacheComponentTerminus(
void)
382 ActivateSemaphoreInfo(&cache_semaphore);
384 RelinquishSemaphoreInfo(&cache_semaphore);
416static MagickBooleanType ClipPixelCacheNexus(
Image *image,
420 *magick_restrict cache_info;
432 if (IsEventLogging() != MagickFalse)
433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
434 if ((image->channels & WriteMaskChannel) == 0)
436 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
439 if (cache_info == (Cache) NULL)
441 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
442 nexus_info->region.width,nexus_info->region.height,
443 nexus_info->virtual_nexus,exception);
444 q=nexus_info->pixels;
445 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
447 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
452 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
460 mask_alpha=QuantumScale*(double) GetPixelWriteMask(image,p);
461 if (fabs(mask_alpha) >= MagickEpsilon)
463 for (i=0; i < (ssize_t) image->number_channels; i++)
465 PixelChannel channel = GetPixelChannelChannel(image,i);
466 PixelTrait traits = GetPixelChannelTraits(image,channel);
467 if ((traits & UpdatePixelTrait) == 0)
469 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha*(
double)
470 GetPixelAlpha(image,p),(
double) q[i],(
double)
471 GetPixelAlpha(image,q)));
473 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
475 p+=(ptrdiff_t) GetPixelChannels(image);
476 q+=(ptrdiff_t) GetPixelChannels(image);
504MagickPrivate Cache ClonePixelCache(
const Cache cache)
507 *magick_restrict clone_info;
510 *magick_restrict cache_info;
512 assert(cache != NULL);
514 assert(cache_info->signature == MagickCoreSignature);
515 if (IsEventLogging() != MagickFalse)
516 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
517 cache_info->filename);
518 clone_info=(
CacheInfo *) AcquirePixelCache(cache_info->number_threads);
519 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
520 return((Cache ) clone_info);
548MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
551 *magick_restrict cache_info,
552 *magick_restrict source_info;
554 assert(clone != (Cache) NULL);
556 assert(source_info->signature == MagickCoreSignature);
557 if (IsEventLogging() != MagickFalse)
558 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
559 source_info->filename);
560 assert(cache != (Cache) NULL);
562 assert(cache_info->signature == MagickCoreSignature);
563 source_info->methods=cache_info->methods;
595static MagickBooleanType ClonePixelCacheOnDisk(
616 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
617 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
619 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
620 (lseek(clone_info->file,0,SEEK_SET) < 0))
622 quantum=(size_t) MagickMaxBufferExtent;
623 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
625#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
626 if (cache_info->length < 0x7ffff000)
628 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
629 (
size_t) cache_info->length);
630 if (count == (ssize_t) cache_info->length)
632 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
633 (lseek(clone_info->file,0,SEEK_SET) < 0))
637 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
639 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
640 if (buffer == (
unsigned char *) NULL)
641 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
643 while ((count=read(cache_info->file,buffer,quantum)) > 0)
648 number_bytes=write(clone_info->file,buffer,(
size_t) count);
649 if (number_bytes != count)
651 extent+=(size_t) number_bytes;
653 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
654 if (extent != cache_info->length)
659static MagickBooleanType ClonePixelCacheRepository(
663#define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
664#define cache_number_threads(source,destination,chunk,multithreaded) \
665 num_threads((multithreaded) == 0 ? 1 : \
666 (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
667 (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
668 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),2),1) : \
669 MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
676 **magick_restrict cache_nexus,
677 **magick_restrict clone_nexus;
685 assert(cache_info != (
CacheInfo *) NULL);
686 assert(clone_info != (
CacheInfo *) NULL);
688 if (cache_info->type == PingCache)
690 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
691 if ((cache_info->storage_class == clone_info->storage_class) &&
692 (cache_info->colorspace == clone_info->colorspace) &&
693 (cache_info->alpha_trait == clone_info->alpha_trait) &&
694 (cache_info->channels == clone_info->channels) &&
695 (cache_info->columns == clone_info->columns) &&
696 (cache_info->rows == clone_info->rows) &&
697 (cache_info->number_channels == clone_info->number_channels) &&
698 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
699 (cache_info->metacontent_extent == clone_info->metacontent_extent))
704 if (((cache_info->type == MemoryCache) ||
705 (cache_info->type == MapCache)) &&
706 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
708 (void) memcpy(clone_info->pixels,cache_info->pixels,
709 cache_info->number_channels*cache_info->columns*cache_info->rows*
710 sizeof(*cache_info->pixels));
711 if ((cache_info->metacontent_extent != 0) &&
712 (clone_info->metacontent_extent != 0))
713 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
714 cache_info->columns*cache_info->rows*
715 clone_info->metacontent_extent*
sizeof(
unsigned char));
718 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
719 return(ClonePixelCacheOnDisk(cache_info,clone_info));
724 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
725 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
726 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
727 optimize=(cache_info->number_channels == clone_info->number_channels) &&
728 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
729 MagickTrue : MagickFalse;
730 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
731 clone_info->number_channels*clone_info->columns);
733#if defined(MAGICKCORE_OPENMP_SUPPORT)
734 #pragma omp parallel for schedule(static) shared(status) \
735 cache_number_threads(cache_info,clone_info,(int) cache_info->rows,4)
737 for (y=0; y < (ssize_t) cache_info->rows; y++)
740 id = GetOpenMPThreadId();
748 if (status == MagickFalse)
750 if (y >= (ssize_t) clone_info->rows)
752 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
753 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
754 if (pixels == (Quantum *) NULL)
756 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
757 if (status == MagickFalse)
759 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
760 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
761 if (pixels == (Quantum *) NULL)
763 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[id]->length);
764 if (optimize != MagickFalse)
765 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
778 p=cache_nexus[id]->pixels;
779 q=clone_nexus[id]->pixels;
780 for (x=0; x < (ssize_t) cache_info->columns; x++)
785 if (x == (ssize_t) clone_info->columns)
787 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
795 channel=clone_info->channel_map[i].channel;
796 traits=cache_info->channel_map[channel].traits;
797 if (traits != UndefinedPixelTrait)
798 *q=*(p+cache_info->channel_map[channel].offset);
801 p+=(ptrdiff_t) cache_info->number_channels;
804 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
806 if ((cache_info->metacontent_extent != 0) &&
807 (clone_info->metacontent_extent != 0))
812 length=(size_t) MagickMin(cache_info->metacontent_extent,
813 clone_info->metacontent_extent);
814#if defined(MAGICKCORE_OPENMP_SUPPORT)
815 #pragma omp parallel for schedule(static) shared(status) \
816 cache_number_threads(cache_info,clone_info,(int) cache_info->rows,4)
818 for (y=0; y < (ssize_t) cache_info->rows; y++)
821 id = GetOpenMPThreadId();
826 if (status == MagickFalse)
828 if (y >= (ssize_t) clone_info->rows)
830 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
831 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
832 if (pixels == (Quantum *) NULL)
834 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
835 if (status == MagickFalse)
837 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
838 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
839 if (pixels == (Quantum *) NULL)
841 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
842 (cache_nexus[
id]->metacontent != (
void *) NULL))
843 (void) memcpy(clone_nexus[
id]->metacontent,
844 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
845 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
848 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
849 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
850 if (cache_info->debug != MagickFalse)
853 message[MagickPathExtent];
855 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
856 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
857 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
858 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
885static void DestroyImagePixelCache(
Image *image)
887 assert(image != (
Image *) NULL);
888 assert(image->signature == MagickCoreSignature);
889 if (IsEventLogging() != MagickFalse)
890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
891 if (image->cache != (
void *) NULL)
892 image->cache=DestroyPixelCache(image->cache);
917MagickExport
void DestroyImagePixels(
Image *image)
920 *magick_restrict cache_info;
922 assert(image != (
const Image *) NULL);
923 assert(image->signature == MagickCoreSignature);
924 if (IsEventLogging() != MagickFalse)
925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
926 assert(image->cache != (Cache) NULL);
928 assert(cache_info->signature == MagickCoreSignature);
929 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
931 cache_info->methods.destroy_pixel_handler(image);
934 image->cache=DestroyPixelCache(image->cache);
960static MagickBooleanType ClosePixelCacheOnDisk(
CacheInfo *cache_info)
966 if (cache_info->file != -1)
968 status=close_utf8(cache_info->file);
969 cache_info->file=(-1);
970 RelinquishMagickResource(FileResource,1);
972 return(status == -1 ? MagickFalse : MagickTrue);
975static inline void RelinquishPixelCachePixels(
CacheInfo *cache_info)
977 switch (cache_info->type)
981 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
982#if defined(MAGICKCORE_OPENCL_SUPPORT)
983 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
985 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
987 cache_info->pixels=(Quantum *) NULL;
991 if (cache_info->mapped == MagickFalse)
992 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
996 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
997 cache_info->pixels=(Quantum *) NULL;
999 RelinquishMagickResource(MemoryResource,cache_info->length);
1004 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1005 cache_info->pixels=(Quantum *) NULL;
1006 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1007 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1008 *cache_info->cache_filename=
'\0';
1009 RelinquishMagickResource(MapResource,cache_info->length);
1014 if (cache_info->file != -1)
1015 (void) ClosePixelCacheOnDisk(cache_info);
1016 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1017 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1018 *cache_info->cache_filename=
'\0';
1019 RelinquishMagickResource(DiskResource,cache_info->length);
1022 case DistributedCache:
1024 *cache_info->cache_filename=
'\0';
1026 cache_info->server_info);
1032 cache_info->type=UndefinedCache;
1033 cache_info->mapped=MagickFalse;
1034 cache_info->metacontent=(
void *) NULL;
1037MagickPrivate Cache DestroyPixelCache(Cache cache)
1040 *magick_restrict cache_info;
1042 assert(cache != (Cache) NULL);
1044 assert(cache_info->signature == MagickCoreSignature);
1045 if (IsEventLogging() != MagickFalse)
1046 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1047 cache_info->filename);
1048 LockSemaphoreInfo(cache_info->semaphore);
1049 cache_info->reference_count--;
1050 if (cache_info->reference_count != 0)
1052 UnlockSemaphoreInfo(cache_info->semaphore);
1053 return((Cache) NULL);
1055 UnlockSemaphoreInfo(cache_info->semaphore);
1056 if (cache_info->debug != MagickFalse)
1059 message[MagickPathExtent];
1061 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1062 cache_info->filename);
1063 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1065 RelinquishPixelCachePixels(cache_info);
1068 cache_info->server_info);
1069 if (cache_info->nexus_info != (
NexusInfo **) NULL)
1070 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1071 cache_info->number_threads);
1072 if (cache_info->random_info != (
RandomInfo *) NULL)
1073 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1075 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1077 RelinquishSemaphoreInfo(&cache_info->semaphore);
1078 cache_info->signature=(~MagickCoreSignature);
1079 cache_info=(
CacheInfo *) RelinquishAlignedMemory(cache_info);
1110static inline void RelinquishCacheNexusPixels(
NexusInfo *nexus_info)
1112 if (nexus_info->mapped == MagickFalse)
1113 (void) RelinquishAlignedMemory(nexus_info->cache);
1115 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1116 nexus_info->cache=(Quantum *) NULL;
1117 nexus_info->pixels=(Quantum *) NULL;
1118 nexus_info->metacontent=(
void *) NULL;
1119 nexus_info->length=0;
1120 nexus_info->mapped=MagickFalse;
1124 const size_t number_threads)
1129 assert(nexus_info != (
NexusInfo **) NULL);
1130 for (i=0; i < (ssize_t) (2*number_threads); i++)
1132 if (nexus_info[i]->cache != (Quantum *) NULL)
1133 RelinquishCacheNexusPixels(nexus_info[i]);
1134 nexus_info[i]->signature=(~MagickCoreSignature);
1136 *nexus_info=(
NexusInfo *) RelinquishMagickMemory(*nexus_info);
1137 nexus_info=(
NexusInfo **) RelinquishAlignedMemory(nexus_info);
1166MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1169 *magick_restrict cache_info;
1172 id = GetOpenMPThreadId();
1174 assert(image != (
const Image *) NULL);
1175 assert(image->signature == MagickCoreSignature);
1176 assert(image->cache != (Cache) NULL);
1178 assert(cache_info->signature == MagickCoreSignature);
1179 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1180 (GetAuthenticMetacontentFromHandler) NULL)
1185 metacontent=cache_info->methods.
1186 get_authentic_metacontent_from_handler(image);
1187 return(metacontent);
1189 assert(
id < (
int) cache_info->number_threads);
1190 return(cache_info->nexus_info[
id]->metacontent);
1217static void *GetAuthenticMetacontentFromCache(
const Image *image)
1220 *magick_restrict cache_info;
1223 id = GetOpenMPThreadId();
1225 assert(image != (
const Image *) NULL);
1226 assert(image->signature == MagickCoreSignature);
1227 assert(image->cache != (Cache) NULL);
1229 assert(cache_info->signature == MagickCoreSignature);
1230 assert(
id < (
int) cache_info->number_threads);
1231 return(cache_info->nexus_info[
id]->metacontent);
1234#if defined(MAGICKCORE_OPENCL_SUPPORT)
1263MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1267 *magick_restrict cache_info;
1269 assert(image != (
const Image *) NULL);
1270 assert(device != (
const MagickCLDevice) NULL);
1272 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1274 SyncImagePixelCache((
Image *) image,exception);
1277 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1278 return((cl_mem) NULL);
1279 LockSemaphoreInfo(cache_info->semaphore);
1280 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1281 (cache_info->opencl->device->context != device->context))
1282 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1283 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1285 assert(cache_info->pixels != (Quantum *) NULL);
1286 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1287 cache_info->length);
1289 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1290 RetainOpenCLMemObject(cache_info->opencl->buffer);
1291 UnlockSemaphoreInfo(cache_info->semaphore);
1292 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1293 return((cl_mem) NULL);
1294 assert(cache_info->opencl->pixels == cache_info->pixels);
1295 return(cache_info->opencl->buffer);
1334MagickPrivate Quantum *GetAuthenticPixelCacheNexus(
Image *image,
const ssize_t x,
1335 const ssize_t y,
const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
1339 *magick_restrict cache_info;
1342 *magick_restrict pixels;
1347 assert(image != (
Image *) NULL);
1348 assert(image->signature == MagickCoreSignature);
1349 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1350 nexus_info,exception);
1351 if (pixels == (Quantum *) NULL)
1352 return((Quantum *) NULL);
1354 assert(cache_info->signature == MagickCoreSignature);
1355 if (nexus_info->authentic_pixel_cache != MagickFalse)
1357 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1358 return((Quantum *) NULL);
1359 if (cache_info->metacontent_extent != 0)
1360 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1361 return((Quantum *) NULL);
1388static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1391 *magick_restrict cache_info;
1394 id = GetOpenMPThreadId();
1396 assert(image != (
const Image *) NULL);
1397 assert(image->signature == MagickCoreSignature);
1398 assert(image->cache != (Cache) NULL);
1400 assert(cache_info->signature == MagickCoreSignature);
1401 assert(
id < (
int) cache_info->number_threads);
1402 return(cache_info->nexus_info[
id]->pixels);
1429MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1432 *magick_restrict cache_info;
1435 id = GetOpenMPThreadId();
1437 assert(image != (
const Image *) NULL);
1438 assert(image->signature == MagickCoreSignature);
1439 assert(image->cache != (Cache) NULL);
1441 assert(cache_info->signature == MagickCoreSignature);
1442 if (cache_info->methods.get_authentic_pixels_from_handler !=
1443 (GetAuthenticPixelsFromHandler) NULL)
1444 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1445 assert(
id < (
int) cache_info->number_threads);
1446 return(cache_info->nexus_info[
id]->pixels);
1494MagickExport Quantum *GetAuthenticPixels(
Image *image,
const ssize_t x,
1495 const ssize_t y,
const size_t columns,
const size_t rows,
1499 *magick_restrict cache_info;
1502 id = GetOpenMPThreadId();
1507 assert(image != (
Image *) NULL);
1508 assert(image->signature == MagickCoreSignature);
1509 assert(image->cache != (Cache) NULL);
1511 assert(cache_info->signature == MagickCoreSignature);
1512 if (cache_info->methods.get_authentic_pixels_handler !=
1513 (GetAuthenticPixelsHandler) NULL)
1515 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1519 assert(
id < (
int) cache_info->number_threads);
1520 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1521 cache_info->nexus_info[
id],exception);
1556static Quantum *GetAuthenticPixelsCache(
Image *image,
const ssize_t x,
1557 const ssize_t y,
const size_t columns,
const size_t rows,
1561 *magick_restrict cache_info;
1564 id = GetOpenMPThreadId();
1567 *magick_restrict pixels;
1569 assert(image != (
const Image *) NULL);
1570 assert(image->signature == MagickCoreSignature);
1571 assert(image->cache != (Cache) NULL);
1573 if (cache_info == (Cache) NULL)
1574 return((Quantum *) NULL);
1575 assert(cache_info->signature == MagickCoreSignature);
1576 assert(
id < (
int) cache_info->number_threads);
1577 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1578 cache_info->nexus_info[
id],exception);
1605MagickExport MagickSizeType GetImageExtent(
const Image *image)
1608 *magick_restrict cache_info;
1611 id = GetOpenMPThreadId();
1613 assert(image != (
Image *) NULL);
1614 assert(image->signature == MagickCoreSignature);
1615 if (IsEventLogging() != MagickFalse)
1616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1617 assert(image->cache != (Cache) NULL);
1619 assert(cache_info->signature == MagickCoreSignature);
1620 assert(
id < (
int) cache_info->number_threads);
1621 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1654static inline MagickBooleanType ValidatePixelCacheMorphology(
1655 const Image *magick_restrict image)
1658 *magick_restrict cache_info;
1668 p=image->channel_map;
1669 q=cache_info->channel_map;
1670 if ((image->storage_class != cache_info->storage_class) ||
1671 (image->colorspace != cache_info->colorspace) ||
1672 (image->alpha_trait != cache_info->alpha_trait) ||
1673 (image->channels != cache_info->channels) ||
1674 (image->columns != cache_info->columns) ||
1675 (image->rows != cache_info->rows) ||
1676 (image->number_channels != cache_info->number_channels) ||
1677 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1678 (image->metacontent_extent != cache_info->metacontent_extent) ||
1679 (cache_info->nexus_info == (
NexusInfo **) NULL))
1680 return(MagickFalse);
1684static Cache GetImagePixelCache(
Image *image,
const MagickBooleanType clone,
1688 *magick_restrict cache_info;
1692 status = MagickTrue;
1694 static MagickSizeType
1695 cpu_throttle = MagickResourceInfinity,
1698 if (IsImageTTLExpired(image) != MagickFalse)
1703 (void) ThrowMagickException(exception,GetMagickModule(),
1704 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1705 return((Cache) NULL);
1707 if (cpu_throttle == MagickResourceInfinity)
1708 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1709 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1710 MagickDelay(cpu_throttle);
1711 LockSemaphoreInfo(image->semaphore);
1712 assert(image->cache != (Cache) NULL);
1714#if defined(MAGICKCORE_OPENCL_SUPPORT)
1715 CopyOpenCLBuffer(cache_info);
1717 destroy=MagickFalse;
1718 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1720 LockSemaphoreInfo(cache_info->semaphore);
1721 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1732 clone_image=(*image);
1733 clone_image.semaphore=AcquireSemaphoreInfo();
1734 clone_image.reference_count=1;
1735 clone_image.cache=ClonePixelCache(cache_info);
1736 clone_info=(
CacheInfo *) clone_image.cache;
1737 status=OpenPixelCache(&clone_image,IOMode,exception);
1738 if (status == MagickFalse)
1739 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1742 if (clone != MagickFalse)
1743 status=ClonePixelCacheRepository(clone_info,cache_info,
1745 if (status == MagickFalse)
1746 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
1750 image->cache=clone_info;
1753 RelinquishSemaphoreInfo(&clone_image.semaphore);
1755 UnlockSemaphoreInfo(cache_info->semaphore);
1757 if (destroy != MagickFalse)
1758 cache_info=(
CacheInfo *) DestroyPixelCache(cache_info);
1759 if (status != MagickFalse)
1764 if (image->type != UndefinedType)
1765 image->type=UndefinedType;
1766 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1768 status=OpenPixelCache(image,IOMode,exception);
1770 if (cache_info->file != -1)
1771 (void) ClosePixelCacheOnDisk(cache_info);
1774 UnlockSemaphoreInfo(image->semaphore);
1775 if (status == MagickFalse)
1776 return((Cache) NULL);
1777 return(image->cache);
1803MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1806 *magick_restrict cache_info;
1808 assert(image != (
Image *) NULL);
1809 assert(image->signature == MagickCoreSignature);
1810 assert(image->cache != (Cache) NULL);
1812 assert(cache_info->signature == MagickCoreSignature);
1813 return(cache_info->type);
1847static inline MagickBooleanType CopyPixel(
const Image *image,
1848 const Quantum *source,Quantum *destination)
1853 if (source == (
const Quantum *) NULL)
1855 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1856 destination[GreenPixelChannel]=ClampToQuantum(
1857 image->background_color.green);
1858 destination[BluePixelChannel]=ClampToQuantum(
1859 image->background_color.blue);
1860 destination[BlackPixelChannel]=ClampToQuantum(
1861 image->background_color.black);
1862 destination[AlphaPixelChannel]=ClampToQuantum(
1863 image->background_color.alpha);
1864 return(MagickFalse);
1866 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1868 PixelChannel channel = GetPixelChannelChannel(image,i);
1869 destination[channel]=source[i];
1874MagickExport MagickBooleanType GetOneAuthenticPixel(
Image *image,
1875 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1878 *magick_restrict cache_info;
1883 assert(image != (
Image *) NULL);
1884 assert(image->signature == MagickCoreSignature);
1885 assert(image->cache != (Cache) NULL);
1887 assert(cache_info->signature == MagickCoreSignature);
1888 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1889 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1890 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1891 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1892 return(CopyPixel(image,q,pixel));
1926static MagickBooleanType GetOneAuthenticPixelFromCache(
Image *image,
1927 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1930 *magick_restrict cache_info;
1933 id = GetOpenMPThreadId();
1938 assert(image != (
const Image *) NULL);
1939 assert(image->signature == MagickCoreSignature);
1940 assert(image->cache != (Cache) NULL);
1942 assert(cache_info->signature == MagickCoreSignature);
1943 assert(
id < (
int) cache_info->number_threads);
1944 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1945 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
1947 return(CopyPixel(image,q,pixel));
1981MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
1982 const ssize_t x,
const ssize_t y,Quantum *pixel,
ExceptionInfo *exception)
1985 *magick_restrict cache_info;
1988 id = GetOpenMPThreadId();
1993 assert(image != (
const Image *) NULL);
1994 assert(image->signature == MagickCoreSignature);
1995 assert(image->cache != (Cache) NULL);
1997 assert(cache_info->signature == MagickCoreSignature);
1998 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1999 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2000 (GetOneVirtualPixelFromHandler) NULL)
2001 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2002 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2003 assert(
id < (
int) cache_info->number_threads);
2004 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2005 1UL,1UL,cache_info->nexus_info[
id],exception);
2006 return(CopyPixel(image,p,pixel));
2043static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2044 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2048 *magick_restrict cache_info;
2051 id = GetOpenMPThreadId();
2056 assert(image != (
const Image *) NULL);
2057 assert(image->signature == MagickCoreSignature);
2058 assert(image->cache != (Cache) NULL);
2060 assert(cache_info->signature == MagickCoreSignature);
2061 assert(
id < (
int) cache_info->number_threads);
2062 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2063 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2064 cache_info->nexus_info[
id],exception);
2065 return(CopyPixel(image,p,pixel));
2102MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2103 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2107 *magick_restrict cache_info;
2110 id = GetOpenMPThreadId();
2115 assert(image != (
const Image *) NULL);
2116 assert(image->signature == MagickCoreSignature);
2117 assert(image->cache != (Cache) NULL);
2119 assert(cache_info->signature == MagickCoreSignature);
2120 assert(
id < (
int) cache_info->number_threads);
2121 GetPixelInfo(image,pixel);
2122 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2123 cache_info->nexus_info[
id],exception);
2124 if (p == (
const Quantum *) NULL)
2125 return(MagickFalse);
2126 GetPixelInfoPixel(image,p,pixel);
2152MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2155 *magick_restrict cache_info;
2157 assert(cache != (Cache) NULL);
2159 assert(cache_info->signature == MagickCoreSignature);
2160 if (IsEventLogging() != MagickFalse)
2161 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2162 cache_info->filename);
2163 return(cache_info->colorspace);
2189MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2192 *magick_restrict cache_info;
2194 assert(image != (
const Image *) NULL);
2195 assert(image->signature == MagickCoreSignature);
2196 assert(image->cache != (Cache) NULL);
2198 assert(cache_info->signature == MagickCoreSignature);
2199 return(cache_info->cache_filename);
2224MagickPrivate
void GetPixelCacheMethods(
CacheMethods *cache_methods)
2227 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2228 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2229 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2230 cache_methods->get_virtual_metacontent_from_handler=
2231 GetVirtualMetacontentFromCache;
2232 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2233 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2234 cache_methods->get_authentic_metacontent_from_handler=
2235 GetAuthenticMetacontentFromCache;
2236 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2237 cache_methods->get_one_authentic_pixel_from_handler=
2238 GetOneAuthenticPixelFromCache;
2239 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2240 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2241 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2269MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2273 *magick_restrict cache_info;
2278 assert(cache != NULL);
2280 assert(cache_info->signature == MagickCoreSignature);
2281 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2283 return((MagickSizeType) cache_info->columns*cache_info->rows);
2314MagickExport
void *GetPixelCachePixels(
Image *image,MagickSizeType *length,
2318 *magick_restrict cache_info;
2320 assert(image != (
const Image *) NULL);
2321 assert(image->signature == MagickCoreSignature);
2322 assert(image->cache != (Cache) NULL);
2323 assert(length != (MagickSizeType *) NULL);
2324 magick_unreferenced(exception);
2326 assert(cache_info->signature == MagickCoreSignature);
2327 *length=cache_info->length;
2328 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2329 return((
void *) NULL);
2330 return((
void *) cache_info->pixels);
2357MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2360 *magick_restrict cache_info;
2362 assert(cache != (Cache) NULL);
2364 assert(cache_info->signature == MagickCoreSignature);
2365 if (IsEventLogging() != MagickFalse)
2366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2367 cache_info->filename);
2368 return(cache_info->storage_class);
2398MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2402 *magick_restrict cache_info;
2404 assert(image != (
Image *) NULL);
2405 assert(image->signature == MagickCoreSignature);
2406 if (IsEventLogging() != MagickFalse)
2407 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2409 assert(cache_info->signature == MagickCoreSignature);
2410 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2411 if (GetImagePixelCacheType(image) == DiskCache)
2412 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2440MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2443 *magick_restrict cache_info;
2445 assert(image != (
Image *) NULL);
2446 assert(image->signature == MagickCoreSignature);
2447 assert(image->cache != (Cache) NULL);
2449 assert(cache_info->signature == MagickCoreSignature);
2450 return(cache_info->virtual_pixel_method);
2476static const void *GetVirtualMetacontentFromCache(
const Image *image)
2479 *magick_restrict cache_info;
2482 id = GetOpenMPThreadId();
2485 *magick_restrict metacontent;
2487 assert(image != (
const Image *) NULL);
2488 assert(image->signature == MagickCoreSignature);
2489 assert(image->cache != (Cache) NULL);
2491 assert(cache_info->signature == MagickCoreSignature);
2492 assert(
id < (
int) cache_info->number_threads);
2493 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2494 cache_info->nexus_info[
id]);
2495 return(metacontent);
2524MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2528 *magick_restrict cache_info;
2530 assert(cache != (Cache) NULL);
2532 assert(cache_info->signature == MagickCoreSignature);
2533 if (cache_info->storage_class == UndefinedClass)
2534 return((
void *) NULL);
2535 return(nexus_info->metacontent);
2562MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2565 *magick_restrict cache_info;
2568 id = GetOpenMPThreadId();
2571 *magick_restrict metacontent;
2573 assert(image != (
const Image *) NULL);
2574 assert(image->signature == MagickCoreSignature);
2575 assert(image->cache != (Cache) NULL);
2577 assert(cache_info->signature == MagickCoreSignature);
2578 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2580 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2582 if (metacontent != (
const void *) NULL)
2583 return(metacontent);
2585 assert(
id < (
int) cache_info->number_threads);
2586 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2587 cache_info->nexus_info[
id]);
2588 return(metacontent);
2631 0, 48, 12, 60, 3, 51, 15, 63,
2632 32, 16, 44, 28, 35, 19, 47, 31,
2633 8, 56, 4, 52, 11, 59, 7, 55,
2634 40, 24, 36, 20, 43, 27, 39, 23,
2635 2, 50, 14, 62, 1, 49, 13, 61,
2636 34, 18, 46, 30, 33, 17, 45, 29,
2637 10, 58, 6, 54, 9, 57, 5, 53,
2638 42, 26, 38, 22, 41, 25, 37, 21
2641static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2646 index=x+DitherMatrix[x & 0x07]-32L;
2649 if (index >= (ssize_t) columns)
2650 return((ssize_t) columns-1L);
2654static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2659 index=y+DitherMatrix[y & 0x07]-32L;
2662 if (index >= (ssize_t) rows)
2663 return((ssize_t) rows-1L);
2667static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2671 if (x >= (ssize_t) columns)
2672 return((ssize_t) (columns-1));
2676static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2680 if (y >= (ssize_t) rows)
2681 return((ssize_t) (rows-1));
2685static inline MagickBooleanType IsOffsetOverflow(
const ssize_t x,
2688 if (((y > 0) && (x > (MAGICK_SSIZE_MAX-y))) ||
2689 ((y < 0) && (x < (MAGICK_SSIZE_MIN-y))))
2690 return(MagickFalse);
2694static inline ssize_t RandomX(
RandomInfo *random_info,
const size_t columns)
2696 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2699static inline ssize_t RandomY(
RandomInfo *random_info,
const size_t rows)
2701 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2704static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2705 const size_t extent)
2710 modulo.quotient=offset;
2714 modulo.quotient=offset/((ssize_t) extent);
2715 modulo.remainder=offset % ((ssize_t) extent);
2717 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2720 modulo.remainder+=((ssize_t) extent);
2725MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2726 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2727 const size_t columns,
const size_t rows,
NexusInfo *nexus_info,
2731 *magick_restrict cache_info;
2747 *magick_restrict virtual_nexus;
2750 *magick_restrict pixels,
2752 virtual_pixel[MaxPixelChannels];
2763 *magick_restrict virtual_metacontent;
2768 assert(image != (
const Image *) NULL);
2769 assert(image->signature == MagickCoreSignature);
2770 assert(image->cache != (Cache) NULL);
2772 assert(cache_info->signature == MagickCoreSignature);
2773 if (cache_info->type == UndefinedCache)
2774 return((
const Quantum *) NULL);
2775#if defined(MAGICKCORE_OPENCL_SUPPORT)
2776 CopyOpenCLBuffer(cache_info);
2778 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2779 ((image->channels & WriteMaskChannel) != 0) ||
2780 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2781 nexus_info,exception);
2782 if (pixels == (Quantum *) NULL)
2783 return((
const Quantum *) NULL);
2784 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2785 return((
const Quantum *) NULL);
2786 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2787 if (IsOffsetOverflow(offset,nexus_info->region.x) == MagickFalse)
2788 return((
const Quantum *) NULL);
2789 offset+=nexus_info->region.x;
2790 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2791 nexus_info->region.width-1L;
2792 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2793 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2794 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2795 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2803 if (nexus_info->authentic_pixel_cache != MagickFalse)
2805 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2806 if (status == MagickFalse)
2807 return((
const Quantum *) NULL);
2808 if (cache_info->metacontent_extent != 0)
2810 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2811 if (status == MagickFalse)
2812 return((
const Quantum *) NULL);
2819 virtual_nexus=nexus_info->virtual_nexus;
2821 s=(
unsigned char *) nexus_info->metacontent;
2822 (void) memset(virtual_pixel,0,cache_info->number_channels*
2823 sizeof(*virtual_pixel));
2824 virtual_metacontent=(
void *) NULL;
2825 switch (virtual_pixel_method)
2827 case BackgroundVirtualPixelMethod:
2828 case BlackVirtualPixelMethod:
2829 case GrayVirtualPixelMethod:
2830 case TransparentVirtualPixelMethod:
2831 case MaskVirtualPixelMethod:
2832 case WhiteVirtualPixelMethod:
2833 case EdgeVirtualPixelMethod:
2834 case CheckerTileVirtualPixelMethod:
2835 case HorizontalTileVirtualPixelMethod:
2836 case VerticalTileVirtualPixelMethod:
2838 if (cache_info->metacontent_extent != 0)
2843 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2844 cache_info->metacontent_extent);
2845 if (virtual_metacontent == (
void *) NULL)
2847 (void) ThrowMagickException(exception,GetMagickModule(),
2848 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2849 return((
const Quantum *) NULL);
2851 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2853 switch (virtual_pixel_method)
2855 case BlackVirtualPixelMethod:
2857 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2858 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2859 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2862 case GrayVirtualPixelMethod:
2864 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2865 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2867 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2870 case TransparentVirtualPixelMethod:
2872 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2873 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2874 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2877 case MaskVirtualPixelMethod:
2878 case WhiteVirtualPixelMethod:
2880 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2881 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2882 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2887 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2889 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2891 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2893 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2895 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2905 for (v=0; v < (ssize_t) rows; v++)
2911 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2912 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2913 y_offset=EdgeY(y_offset,cache_info->rows);
2914 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2920 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2921 x_offset,(ssize_t) columns-u);
2922 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2923 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2933 length=(MagickSizeType) 1;
2934 switch (virtual_pixel_method)
2936 case EdgeVirtualPixelMethod:
2939 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2940 EdgeX(x_offset,cache_info->columns),
2941 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2943 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2946 case RandomVirtualPixelMethod:
2948 if (cache_info->random_info == (
RandomInfo *) NULL)
2949 cache_info->random_info=AcquireRandomInfo();
2950 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2951 RandomX(cache_info->random_info,cache_info->columns),
2952 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2953 virtual_nexus,exception);
2954 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2957 case DitherVirtualPixelMethod:
2959 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2960 DitherX(x_offset,cache_info->columns),
2961 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2963 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2966 case TileVirtualPixelMethod:
2968 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2969 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2970 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2971 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2973 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2976 case MirrorVirtualPixelMethod:
2978 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2979 if ((x_modulo.quotient & 0x01) == 1L)
2980 x_modulo.remainder=(ssize_t) cache_info->columns-
2981 x_modulo.remainder-1L;
2982 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2983 if ((y_modulo.quotient & 0x01) == 1L)
2984 y_modulo.remainder=(ssize_t) cache_info->rows-
2985 y_modulo.remainder-1L;
2986 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2987 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2989 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2992 case HorizontalTileEdgeVirtualPixelMethod:
2994 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2995 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2996 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
2997 virtual_nexus,exception);
2998 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3001 case VerticalTileEdgeVirtualPixelMethod:
3003 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3004 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3005 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3006 virtual_nexus,exception);
3007 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3010 case BackgroundVirtualPixelMethod:
3011 case BlackVirtualPixelMethod:
3012 case GrayVirtualPixelMethod:
3013 case TransparentVirtualPixelMethod:
3014 case MaskVirtualPixelMethod:
3015 case WhiteVirtualPixelMethod:
3018 r=virtual_metacontent;
3021 case CheckerTileVirtualPixelMethod:
3023 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3024 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3025 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3028 r=virtual_metacontent;
3031 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3032 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3034 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3037 case HorizontalTileVirtualPixelMethod:
3039 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3042 r=virtual_metacontent;
3045 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3046 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3047 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3048 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3050 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3053 case VerticalTileVirtualPixelMethod:
3055 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3058 r=virtual_metacontent;
3061 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3062 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3063 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3064 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3066 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3070 if (p == (
const Quantum *) NULL)
3072 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3074 q+=(ptrdiff_t) cache_info->number_channels;
3075 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3077 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3078 s+=(ptrdiff_t) cache_info->metacontent_extent;
3085 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3086 (
size_t) length,1UL,virtual_nexus,exception);
3087 if (p == (
const Quantum *) NULL)
3089 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3090 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3092 q+=(ptrdiff_t) cache_info->number_channels*length;
3093 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3095 (void) memcpy(s,r,(
size_t) length);
3096 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3099 if (u < (ssize_t) columns)
3105 if (virtual_metacontent != (
void *) NULL)
3106 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3107 if (v < (ssize_t) rows)
3108 return((
const Quantum *) NULL);
3146static const Quantum *GetVirtualPixelCache(
const Image *image,
3147 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3148 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
3151 *magick_restrict cache_info;
3154 id = GetOpenMPThreadId();
3159 assert(image != (
const Image *) NULL);
3160 assert(image->signature == MagickCoreSignature);
3161 assert(image->cache != (Cache) NULL);
3163 assert(cache_info->signature == MagickCoreSignature);
3164 assert(
id < (
int) cache_info->number_threads);
3165 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3166 cache_info->nexus_info[
id],exception);
3193MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3196 *magick_restrict cache_info;
3199 id = GetOpenMPThreadId();
3201 assert(image != (
const Image *) NULL);
3202 assert(image->signature == MagickCoreSignature);
3203 assert(image->cache != (Cache) NULL);
3205 assert(cache_info->signature == MagickCoreSignature);
3206 if (cache_info->methods.get_virtual_pixels_handler !=
3207 (GetVirtualPixelsHandler) NULL)
3208 return(cache_info->methods.get_virtual_pixels_handler(image));
3209 assert(
id < (
int) cache_info->number_threads);
3210 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3261MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3262 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3266 *magick_restrict cache_info;
3269 id = GetOpenMPThreadId();
3274 assert(image != (
const Image *) NULL);
3275 assert(image->signature == MagickCoreSignature);
3276 assert(image->cache != (Cache) NULL);
3278 assert(cache_info->signature == MagickCoreSignature);
3279 if (cache_info->methods.get_virtual_pixel_handler !=
3280 (GetVirtualPixelHandler) NULL)
3281 return(cache_info->methods.get_virtual_pixel_handler(image,
3282 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3283 assert(
id < (
int) cache_info->number_threads);
3284 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3285 columns,rows,cache_info->nexus_info[
id],exception);
3312static const Quantum *GetVirtualPixelsCache(
const Image *image)
3315 *magick_restrict cache_info;
3318 id = GetOpenMPThreadId();
3320 assert(image != (
const Image *) NULL);
3321 assert(image->signature == MagickCoreSignature);
3322 assert(image->cache != (Cache) NULL);
3324 assert(cache_info->signature == MagickCoreSignature);
3325 assert(
id < (
int) cache_info->number_threads);
3326 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3355MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3359 *magick_restrict cache_info;
3361 assert(cache != (Cache) NULL);
3363 assert(cache_info->signature == MagickCoreSignature);
3364 if (cache_info->storage_class == UndefinedClass)
3365 return((Quantum *) NULL);
3366 return((
const Quantum *) nexus_info->pixels);
3399static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3400 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3405 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3407 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3408 gamma=PerceptibleReciprocal(gamma);
3409 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3412static MagickBooleanType MaskPixelCacheNexus(
Image *image,
NexusInfo *nexus_info,
3416 *magick_restrict cache_info;
3428 if (IsEventLogging() != MagickFalse)
3429 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3430 if ((image->channels & CompositeMaskChannel) == 0)
3432 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3435 if (cache_info == (Cache) NULL)
3436 return(MagickFalse);
3437 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3438 nexus_info->region.width,nexus_info->region.height,
3439 nexus_info->virtual_nexus,exception);
3440 q=nexus_info->pixels;
3441 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3442 return(MagickFalse);
3443 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3448 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3456 alpha=(double) GetPixelCompositeMask(image,p);
3457 for (i=0; i < (ssize_t) image->number_channels; i++)
3459 PixelChannel channel = GetPixelChannelChannel(image,i);
3460 PixelTrait traits = GetPixelChannelTraits(image,channel);
3461 if ((traits & UpdatePixelTrait) == 0)
3463 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3465 p+=(ptrdiff_t) GetPixelChannels(image);
3466 q+=(ptrdiff_t) GetPixelChannels(image);
3503static inline MagickBooleanType CacheOverflowSanityCheckGetSize(
3504 const MagickSizeType count,
const size_t quantum,MagickSizeType *
const extent)
3509 if ((count == 0) || (quantum == 0))
3511 length=count*quantum;
3512 if (quantum != (length/count))
3519 return(MagickFalse);
3522static MagickBooleanType OpenPixelCacheOnDisk(
CacheInfo *cache_info,
3531 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3533 if (*cache_info->cache_filename ==
'\0')
3534 file=AcquireUniqueFileResource(cache_info->cache_filename);
3540 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3545 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3546 O_BINARY | O_EXCL,S_MODE);
3548 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3554 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3557 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3562 return(MagickFalse);
3563 (void) AcquireMagickResource(FileResource,1);
3564 if (cache_info->file != -1)
3565 (void) ClosePixelCacheOnDisk(cache_info);
3566 cache_info->file=file;
3567 cache_info->disk_mode=mode;
3571static inline MagickOffsetType WritePixelCacheRegion(
3572 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3573 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3581#if !defined(MAGICKCORE_HAVE_PWRITE)
3582 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3583 return((MagickOffsetType) -1);
3585 for (i=0; i < (MagickOffsetType) length; i+=count)
3587#if !defined(MAGICKCORE_HAVE_PWRITE)
3588 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3589 (MagickSizeType) i,MagickMaxBufferExtent));
3591 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3592 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3604static MagickBooleanType SetPixelCacheExtent(
Image *image,MagickSizeType length)
3607 *magick_restrict cache_info;
3613 if (cache_info->debug != MagickFalse)
3616 format[MagickPathExtent],
3617 message[MagickPathExtent];
3619 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3620 (void) FormatLocaleString(message,MagickPathExtent,
3621 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3622 cache_info->cache_filename,cache_info->file,format);
3623 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3625 if (length != (MagickSizeType) ((MagickOffsetType) length))
3626 return(MagickFalse);
3627 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3629 return(MagickFalse);
3630 if ((MagickSizeType) offset < length)
3636 extent=(MagickOffsetType) length-1;
3637 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3640 return(MagickFalse);
3641#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3642 if (cache_info->synchronize != MagickFalse)
3643 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3644 return(MagickFalse);
3647 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3649 return(MagickFalse);
3653static MagickBooleanType OpenPixelCache(
Image *image,
const MapMode mode,
3657 *magick_restrict cache_info,
3661 format[MagickPathExtent],
3662 message[MagickPathExtent];
3679 assert(image != (
const Image *) NULL);
3680 assert(image->signature == MagickCoreSignature);
3681 assert(image->cache != (Cache) NULL);
3682 if (IsEventLogging() != MagickFalse)
3683 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3684 if (cache_anonymous_memory < 0)
3692 cache_anonymous_memory=0;
3693 value=GetPolicyValue(
"pixel-cache-memory");
3694 if (value == (
char *) NULL)
3695 value=GetPolicyValue(
"cache:memory-map");
3696 if (LocaleCompare(value,
"anonymous") == 0)
3698#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3699 cache_anonymous_memory=1;
3701 (void) ThrowMagickException(exception,GetMagickModule(),
3702 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3703 "'%s' (policy requires anonymous memory mapping)",image->filename);
3706 value=DestroyString(value);
3708 if ((image->columns == 0) || (image->rows == 0))
3709 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3711 assert(cache_info->signature == MagickCoreSignature);
3712 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3713 ((MagickSizeType) image->rows > cache_info->height_limit))
3714 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
3716 if (GetMagickResourceLimit(ListLengthResource) != MagickResourceInfinity)
3718 length=GetImageListLength(image);
3719 if (AcquireMagickResource(ListLengthResource,length) == MagickFalse)
3720 ThrowBinaryException(ResourceLimitError,
"ListLengthExceedsLimit",
3723 source_info=(*cache_info);
3724 source_info.file=(-1);
3725 (void) FormatLocaleString(cache_info->filename,MagickPathExtent,
"%s[%.20g]",
3726 image->filename,(
double) image->scene);
3727 cache_info->storage_class=image->storage_class;
3728 cache_info->colorspace=image->colorspace;
3729 cache_info->alpha_trait=image->alpha_trait;
3730 cache_info->channels=image->channels;
3731 cache_info->rows=image->rows;
3732 cache_info->columns=image->columns;
3733 status=ResetPixelChannelMap(image,exception);
3734 if (status == MagickFalse)
3735 return(MagickFalse);
3736 cache_info->number_channels=GetPixelChannels(image);
3737 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3738 sizeof(*image->channel_map));
3739 cache_info->metacontent_extent=image->metacontent_extent;
3740 cache_info->mode=mode;
3741 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3742 packet_size=MagickMax(cache_info->number_channels,1)*
sizeof(Quantum);
3743 if (image->metacontent_extent != 0)
3744 packet_size+=cache_info->metacontent_extent;
3745 if (CacheOverflowSanityCheckGetSize(number_pixels,packet_size,&length) != MagickFalse)
3747 cache_info->storage_class=UndefinedClass;
3748 cache_info->length=0;
3749 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3752 columns=(size_t) (length/cache_info->rows/packet_size);
3753 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3754 ((ssize_t) cache_info->rows < 0))
3756 cache_info->storage_class=UndefinedClass;
3757 cache_info->length=0;
3758 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3761 cache_info->length=length;
3762 if (image->ping != MagickFalse)
3764 cache_info->type=PingCache;
3767 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3768 cache_info->columns*cache_info->rows);
3769 if (cache_info->mode == PersistMode)
3771 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3772 cache_info->metacontent_extent);
3773 if ((status != MagickFalse) &&
3774 (length == (MagickSizeType) ((
size_t) length)) &&
3775 ((cache_info->type == UndefinedCache) ||
3776 (cache_info->type == MemoryCache)))
3778 status=AcquireMagickResource(MemoryResource,cache_info->length);
3779 if (status != MagickFalse)
3782 if (cache_anonymous_memory <= 0)
3784 cache_info->mapped=MagickFalse;
3785 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3786 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3790 cache_info->mapped=MagickTrue;
3791 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3792 cache_info->length);
3794 if (cache_info->pixels == (Quantum *) NULL)
3796 cache_info->mapped=source_info.mapped;
3797 cache_info->pixels=source_info.pixels;
3804 cache_info->type=MemoryCache;
3805 cache_info->metacontent=(
void *) NULL;
3806 if (cache_info->metacontent_extent != 0)
3807 cache_info->metacontent=(
void *) (cache_info->pixels+
3808 cache_info->number_channels*number_pixels);
3809 if ((source_info.storage_class != UndefinedClass) &&
3812 status=ClonePixelCacheRepository(cache_info,&source_info,
3814 RelinquishPixelCachePixels(&source_info);
3816 if (cache_info->debug != MagickFalse)
3818 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3819 MagickPathExtent,format);
3820 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3822 (void) FormatLocaleString(message,MagickPathExtent,
3823 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3824 cache_info->filename,cache_info->mapped != MagickFalse ?
3825 "Anonymous" :
"Heap",type,(double) cache_info->columns,
3826 (double) cache_info->rows,(double)
3827 cache_info->number_channels,format);
3828 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3831 cache_info->storage_class=image->storage_class;
3834 if ((source_info.storage_class != UndefinedClass) &&
3836 RelinquishPixelCachePixels(&source_info);
3837 cache_info->type=UndefinedCache;
3838 return(MagickFalse);
3844 status=AcquireMagickResource(DiskResource,cache_info->length);
3845 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3847 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3855 server_info=AcquireDistributeCacheInfo(exception);
3858 status=OpenDistributePixelCache(server_info,image);
3859 if (status == MagickFalse)
3861 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3862 GetDistributeCacheHostname(server_info));
3863 server_info=DestroyDistributeCacheInfo(server_info);
3871 cache_info->type=DistributedCache;
3872 cache_info->server_info=server_info;
3873 (void) FormatLocaleString(cache_info->cache_filename,
3874 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3877 cache_info->server_info));
3878 if ((source_info.storage_class != UndefinedClass) &&
3881 status=ClonePixelCacheRepository(cache_info,&source_info,
3883 RelinquishPixelCachePixels(&source_info);
3885 if (cache_info->debug != MagickFalse)
3887 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3888 MagickPathExtent,format);
3889 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3891 (void) FormatLocaleString(message,MagickPathExtent,
3892 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3893 cache_info->filename,cache_info->cache_filename,
3895 cache_info->server_info),type,(double) cache_info->columns,
3896 (
double) cache_info->rows,(double)
3897 cache_info->number_channels,format);
3898 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3903 if ((source_info.storage_class != UndefinedClass) &&
3905 RelinquishPixelCachePixels(&source_info);
3906 cache_info->type=UndefinedCache;
3907 return(MagickFalse);
3912 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3913 RelinquishPixelCachePixels(&source_info);
3914 cache_info->type=UndefinedCache;
3915 (void) memset(image->channel_map,0,MaxPixelChannels*
3916 sizeof(*image->channel_map));
3917 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3918 "CacheResourcesExhausted",
"`%s'",image->filename);
3919 return(MagickFalse);
3924 if (status == MagickFalse)
3926 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3927 RelinquishPixelCachePixels(&source_info);
3928 cache_info->type=UndefinedCache;
3929 (void) memset(image->channel_map,0,MaxPixelChannels*
3930 sizeof(*image->channel_map));
3931 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3932 "CacheResourcesExhausted",
"`%s'",image->filename);
3933 return(MagickFalse);
3935 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3936 (cache_info->mode != PersistMode))
3938 (void) ClosePixelCacheOnDisk(cache_info);
3939 *cache_info->cache_filename=
'\0';
3941 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3943 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3944 RelinquishPixelCachePixels(&source_info);
3945 cache_info->type=UndefinedCache;
3946 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3948 return(MagickFalse);
3950 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3951 cache_info->length);
3952 if (status == MagickFalse)
3954 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3955 RelinquishPixelCachePixels(&source_info);
3956 cache_info->type=UndefinedCache;
3957 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3959 return(MagickFalse);
3961 cache_info->type=DiskCache;
3962 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3963 cache_info->metacontent_extent);
3964 if (length == (MagickSizeType) ((
size_t) length))
3966 status=AcquireMagickResource(MapResource,cache_info->length);
3967 if (status != MagickFalse)
3969 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3970 cache_info->offset,(
size_t) cache_info->length);
3971 if (cache_info->pixels == (Quantum *) NULL)
3973 cache_info->mapped=source_info.mapped;
3974 cache_info->pixels=source_info.pixels;
3975 RelinquishMagickResource(MapResource,cache_info->length);
3982 (void) ClosePixelCacheOnDisk(cache_info);
3983 cache_info->type=MapCache;
3984 cache_info->mapped=MagickTrue;
3985 cache_info->metacontent=(
void *) NULL;
3986 if (cache_info->metacontent_extent != 0)
3987 cache_info->metacontent=(
void *) (cache_info->pixels+
3988 cache_info->number_channels*number_pixels);
3989 if ((source_info.storage_class != UndefinedClass) &&
3992 status=ClonePixelCacheRepository(cache_info,&source_info,
3994 RelinquishPixelCachePixels(&source_info);
3996 if (cache_info->debug != MagickFalse)
3998 (void) FormatMagickSize(cache_info->length,MagickTrue,
"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)",
4004 cache_info->filename,cache_info->cache_filename,
4005 cache_info->file,type,(
double) cache_info->columns,
4006 (double) cache_info->rows,(
double)
4007 cache_info->number_channels,format);
4008 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
4013 if ((source_info.storage_class != UndefinedClass) &&
4015 RelinquishPixelCachePixels(&source_info);
4016 cache_info->type=UndefinedCache;
4017 return(MagickFalse);
4024 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4026 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4027 RelinquishPixelCachePixels(&source_info);
4029 if (cache_info->debug != MagickFalse)
4031 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4032 MagickPathExtent,format);
4033 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4035 (void) FormatLocaleString(message,MagickPathExtent,
4036 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4037 cache_info->cache_filename,cache_info->file,type,(
double)
4038 cache_info->columns,(double) cache_info->rows,(
double)
4039 cache_info->number_channels,format);
4040 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4044 cache_info->type=UndefinedCache;
4045 return(MagickFalse);
4087MagickExport MagickBooleanType PersistPixelCache(
Image *image,
4088 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4092 *magick_restrict cache_info,
4093 *magick_restrict clone_info;
4101 assert(image != (
Image *) NULL);
4102 assert(image->signature == MagickCoreSignature);
4103 if (IsEventLogging() != MagickFalse)
4104 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4105 assert(image->cache != (
void *) NULL);
4106 assert(filename != (
const char *) NULL);
4107 assert(offset != (MagickOffsetType *) NULL);
4108 page_size=GetMagickPageSize();
4110 assert(cache_info->signature == MagickCoreSignature);
4111#if defined(MAGICKCORE_OPENCL_SUPPORT)
4112 CopyOpenCLBuffer(cache_info);
4114 if (attach != MagickFalse)
4119 if (cache_info->debug != MagickFalse)
4120 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4121 "attach persistent cache");
4122 (void) CopyMagickString(cache_info->cache_filename,filename,
4124 cache_info->type=MapCache;
4125 cache_info->offset=(*offset);
4126 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4127 return(MagickFalse);
4128 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4129 ((MagickOffsetType) cache_info->length % page_size));
4135 status=AcquireMagickResource(DiskResource,cache_info->length);
4136 if (status == MagickFalse)
4138 cache_info->type=UndefinedCache;
4139 (void) memset(image->channel_map,0,MaxPixelChannels*
4140 sizeof(*image->channel_map));
4141 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4142 "CacheResourcesExhausted",
"`%s'",image->filename);
4143 return(MagickFalse);
4145 clone_info=(
CacheInfo *) ClonePixelCache(cache_info);
4146 clone_info->type=DiskCache;
4147 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4148 clone_info->file=(-1);
4149 clone_info->storage_class=cache_info->storage_class;
4150 clone_info->colorspace=cache_info->colorspace;
4151 clone_info->alpha_trait=cache_info->alpha_trait;
4152 clone_info->channels=cache_info->channels;
4153 clone_info->columns=cache_info->columns;
4154 clone_info->rows=cache_info->rows;
4155 clone_info->number_channels=cache_info->number_channels;
4156 clone_info->metacontent_extent=cache_info->metacontent_extent;
4157 clone_info->mode=PersistMode;
4158 clone_info->length=cache_info->length;
4159 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4160 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4161 clone_info->offset=(*offset);
4162 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4163 if (status != MagickFalse)
4164 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4165 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4166 ((MagickOffsetType) cache_info->length % page_size));
4167 clone_info=(
CacheInfo *) DestroyPixelCache(clone_info);
4209MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(
Image *image,
4210 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4214 *magick_restrict cache_info;
4223 *magick_restrict pixels;
4228 assert(image != (
const Image *) NULL);
4229 assert(image->signature == MagickCoreSignature);
4230 assert(image->cache != (Cache) NULL);
4231 cache_info=(
CacheInfo *) GetImagePixelCache(image,clone,exception);
4232 if (cache_info == (Cache) NULL)
4233 return((Quantum *) NULL);
4234 assert(cache_info->signature == MagickCoreSignature);
4235 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4236 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4237 (y >= (ssize_t) cache_info->rows))
4239 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4240 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4241 return((Quantum *) NULL);
4243 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4244 return((Quantum *) NULL);
4245 offset=y*(MagickOffsetType) cache_info->columns+x;
4247 return((Quantum *) NULL);
4248 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4249 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4250 (MagickOffsetType) columns-1;
4251 if ((MagickSizeType) offset >= number_pixels)
4252 return((Quantum *) NULL);
4256 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4257 ((image->channels & WriteMaskChannel) != 0) ||
4258 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4259 nexus_info,exception);
4296static Quantum *QueueAuthenticPixelsCache(
Image *image,
const ssize_t x,
4297 const ssize_t y,
const size_t columns,
const size_t rows,
4301 *magick_restrict cache_info;
4304 id = GetOpenMPThreadId();
4307 *magick_restrict pixels;
4309 assert(image != (
const Image *) NULL);
4310 assert(image->signature == MagickCoreSignature);
4311 assert(image->cache != (Cache) NULL);
4313 assert(cache_info->signature == MagickCoreSignature);
4314 assert(
id < (
int) cache_info->number_threads);
4315 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4316 cache_info->nexus_info[
id],exception);
4376MagickExport Quantum *QueueAuthenticPixels(
Image *image,
const ssize_t x,
4377 const ssize_t y,
const size_t columns,
const size_t rows,
4381 *magick_restrict cache_info;
4384 id = GetOpenMPThreadId();
4387 *magick_restrict pixels;
4389 assert(image != (
Image *) NULL);
4390 assert(image->signature == MagickCoreSignature);
4391 assert(image->cache != (Cache) NULL);
4393 assert(cache_info->signature == MagickCoreSignature);
4394 if (cache_info->methods.queue_authentic_pixels_handler !=
4395 (QueueAuthenticPixelsHandler) NULL)
4397 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4398 columns,rows,exception);
4401 assert(
id < (
int) cache_info->number_threads);
4402 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4403 cache_info->nexus_info[
id],exception);
4436static inline MagickOffsetType ReadPixelCacheRegion(
4437 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4438 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4446#if !defined(MAGICKCORE_HAVE_PREAD)
4447 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4448 return((MagickOffsetType) -1);
4450 for (i=0; i < (MagickOffsetType) length; i+=count)
4452#if !defined(MAGICKCORE_HAVE_PREAD)
4453 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4454 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4456 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4457 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4469static MagickBooleanType ReadPixelCacheMetacontent(
4490 if (cache_info->metacontent_extent == 0)
4491 return(MagickFalse);
4492 if (nexus_info->authentic_pixel_cache != MagickFalse)
4494 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4495 return(MagickFalse);
4496 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4497 nexus_info->region.x;
4498 length=(MagickSizeType) nexus_info->region.width*
4499 cache_info->metacontent_extent;
4500 extent=length*nexus_info->region.height;
4501 rows=nexus_info->region.height;
4503 q=(
unsigned char *) nexus_info->metacontent;
4504 switch (cache_info->type)
4515 if ((cache_info->columns == nexus_info->region.width) &&
4516 (extent == (MagickSizeType) ((
size_t) extent)))
4521 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4522 cache_info->metacontent_extent;
4523 for (y=0; y < (ssize_t) rows; y++)
4525 (void) memcpy(q,p,(
size_t) length);
4526 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4527 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4536 LockSemaphoreInfo(cache_info->file_semaphore);
4537 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4539 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4540 cache_info->cache_filename);
4541 UnlockSemaphoreInfo(cache_info->file_semaphore);
4542 return(MagickFalse);
4544 if ((cache_info->columns == nexus_info->region.width) &&
4545 (extent <= MagickMaxBufferExtent))
4550 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4551 for (y=0; y < (ssize_t) rows; y++)
4553 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4554 (MagickOffsetType) extent*(MagickOffsetType)
4555 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4556 (MagickOffsetType) cache_info->metacontent_extent,length,
4557 (
unsigned char *) q);
4558 if (count != (MagickOffsetType) length)
4560 offset+=(MagickOffsetType) cache_info->columns;
4561 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4563 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4564 (void) ClosePixelCacheOnDisk(cache_info);
4565 UnlockSemaphoreInfo(cache_info->file_semaphore);
4568 case DistributedCache:
4576 LockSemaphoreInfo(cache_info->file_semaphore);
4577 region=nexus_info->region;
4578 if ((cache_info->columns != nexus_info->region.width) ||
4579 (extent > MagickMaxBufferExtent))
4586 for (y=0; y < (ssize_t) rows; y++)
4589 cache_info->server_info,®ion,length,(
unsigned char *) q);
4590 if (count != (MagickOffsetType) length)
4592 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4595 UnlockSemaphoreInfo(cache_info->file_semaphore);
4601 if (y < (ssize_t) rows)
4603 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4604 cache_info->cache_filename);
4605 return(MagickFalse);
4607 if ((cache_info->debug != MagickFalse) &&
4608 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4609 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4610 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4611 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4612 nexus_info->region.x,(
double) nexus_info->region.y);
4644static MagickBooleanType ReadPixelCachePixels(
4666 if (nexus_info->authentic_pixel_cache != MagickFalse)
4668 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4669 return(MagickFalse);
4670 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4671 if ((offset/(MagickOffsetType) cache_info->columns) != nexus_info->region.y)
4672 return(MagickFalse);
4673 offset+=nexus_info->region.x;
4674 number_channels=cache_info->number_channels;
4675 length=(MagickSizeType) number_channels*nexus_info->region.width*
4677 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4678 return(MagickFalse);
4679 rows=nexus_info->region.height;
4681 if ((extent == 0) || ((extent/length) != rows))
4682 return(MagickFalse);
4684 q=nexus_info->pixels;
4685 switch (cache_info->type)
4696 if ((cache_info->columns == nexus_info->region.width) &&
4697 (extent == (MagickSizeType) ((
size_t) extent)))
4702 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4704 for (y=0; y < (ssize_t) rows; y++)
4706 (void) memcpy(q,p,(
size_t) length);
4707 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4708 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4717 LockSemaphoreInfo(cache_info->file_semaphore);
4718 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4720 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4721 cache_info->cache_filename);
4722 UnlockSemaphoreInfo(cache_info->file_semaphore);
4723 return(MagickFalse);
4725 if ((cache_info->columns == nexus_info->region.width) &&
4726 (extent <= MagickMaxBufferExtent))
4731 for (y=0; y < (ssize_t) rows; y++)
4733 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4734 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4735 sizeof(*q),length,(
unsigned char *) q);
4736 if (count != (MagickOffsetType) length)
4738 offset+=(MagickOffsetType) cache_info->columns;
4739 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4741 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4742 (void) ClosePixelCacheOnDisk(cache_info);
4743 UnlockSemaphoreInfo(cache_info->file_semaphore);
4746 case DistributedCache:
4754 LockSemaphoreInfo(cache_info->file_semaphore);
4755 region=nexus_info->region;
4756 if ((cache_info->columns != nexus_info->region.width) ||
4757 (extent > MagickMaxBufferExtent))
4764 for (y=0; y < (ssize_t) rows; y++)
4767 cache_info->server_info,®ion,length,(
unsigned char *) q);
4768 if (count != (MagickOffsetType) length)
4770 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4773 UnlockSemaphoreInfo(cache_info->file_semaphore);
4779 if (y < (ssize_t) rows)
4781 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4782 cache_info->cache_filename);
4783 return(MagickFalse);
4785 if ((cache_info->debug != MagickFalse) &&
4786 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4787 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4788 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4789 nexus_info->region.width,(
double) nexus_info->region.height,(double)
4790 nexus_info->region.x,(
double) nexus_info->region.y);
4817MagickPrivate Cache ReferencePixelCache(Cache cache)
4820 *magick_restrict cache_info;
4822 assert(cache != (Cache *) NULL);
4824 assert(cache_info->signature == MagickCoreSignature);
4825 LockSemaphoreInfo(cache_info->semaphore);
4826 cache_info->reference_count++;
4827 UnlockSemaphoreInfo(cache_info->semaphore);
4853MagickPrivate
void ResetPixelCacheChannels(
Image *image)
4856 *magick_restrict cache_info;
4858 assert(image != (
const Image *) NULL);
4859 assert(image->signature == MagickCoreSignature);
4860 assert(image->cache != (Cache) NULL);
4862 assert(cache_info->signature == MagickCoreSignature);
4863 cache_info->number_channels=GetPixelChannels(image);
4884MagickPrivate
void ResetCacheAnonymousMemory(
void)
4886 cache_anonymous_memory=0;
4918MagickExport MagickBooleanType ReshapePixelCache(
Image *image,
4919 const size_t columns,
const size_t rows,
ExceptionInfo *exception)
4927 assert(image != (
Image *) NULL);
4928 assert(image->signature == MagickCoreSignature);
4929 if (IsEventLogging() != MagickFalse)
4930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4931 assert(image->cache != (
void *) NULL);
4932 extent=(MagickSizeType) columns*rows;
4933 if (extent > ((MagickSizeType) image->columns*image->rows))
4934 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4936 image->columns=columns;
4939 cache_info->columns=columns;
4940 cache_info->rows=rows;
4941 return(SyncImagePixelCache(image,exception));
4968MagickPrivate
void SetPixelCacheMethods(Cache cache,
CacheMethods *cache_methods)
4971 *magick_restrict cache_info;
4973 GetOneAuthenticPixelFromHandler
4974 get_one_authentic_pixel_from_handler;
4976 GetOneVirtualPixelFromHandler
4977 get_one_virtual_pixel_from_handler;
4982 assert(cache != (Cache) NULL);
4985 assert(cache_info->signature == MagickCoreSignature);
4986 if (IsEventLogging() != MagickFalse)
4987 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4988 cache_info->filename);
4989 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4990 cache_info->methods.get_virtual_pixel_handler=
4991 cache_methods->get_virtual_pixel_handler;
4992 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4993 cache_info->methods.destroy_pixel_handler=
4994 cache_methods->destroy_pixel_handler;
4995 if (cache_methods->get_virtual_metacontent_from_handler !=
4996 (GetVirtualMetacontentFromHandler) NULL)
4997 cache_info->methods.get_virtual_metacontent_from_handler=
4998 cache_methods->get_virtual_metacontent_from_handler;
4999 if (cache_methods->get_authentic_pixels_handler !=
5000 (GetAuthenticPixelsHandler) NULL)
5001 cache_info->methods.get_authentic_pixels_handler=
5002 cache_methods->get_authentic_pixels_handler;
5003 if (cache_methods->queue_authentic_pixels_handler !=
5004 (QueueAuthenticPixelsHandler) NULL)
5005 cache_info->methods.queue_authentic_pixels_handler=
5006 cache_methods->queue_authentic_pixels_handler;
5007 if (cache_methods->sync_authentic_pixels_handler !=
5008 (SyncAuthenticPixelsHandler) NULL)
5009 cache_info->methods.sync_authentic_pixels_handler=
5010 cache_methods->sync_authentic_pixels_handler;
5011 if (cache_methods->get_authentic_pixels_from_handler !=
5012 (GetAuthenticPixelsFromHandler) NULL)
5013 cache_info->methods.get_authentic_pixels_from_handler=
5014 cache_methods->get_authentic_pixels_from_handler;
5015 if (cache_methods->get_authentic_metacontent_from_handler !=
5016 (GetAuthenticMetacontentFromHandler) NULL)
5017 cache_info->methods.get_authentic_metacontent_from_handler=
5018 cache_methods->get_authentic_metacontent_from_handler;
5019 get_one_virtual_pixel_from_handler=
5020 cache_info->methods.get_one_virtual_pixel_from_handler;
5021 if (get_one_virtual_pixel_from_handler !=
5022 (GetOneVirtualPixelFromHandler) NULL)
5023 cache_info->methods.get_one_virtual_pixel_from_handler=
5024 cache_methods->get_one_virtual_pixel_from_handler;
5025 get_one_authentic_pixel_from_handler=
5026 cache_methods->get_one_authentic_pixel_from_handler;
5027 if (get_one_authentic_pixel_from_handler !=
5028 (GetOneAuthenticPixelFromHandler) NULL)
5029 cache_info->methods.get_one_authentic_pixel_from_handler=
5030 cache_methods->get_one_authentic_pixel_from_handler;
5071static inline MagickBooleanType AcquireCacheNexusPixels(
5072 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5075 if (length != (MagickSizeType) ((
size_t) length))
5077 (void) ThrowMagickException(exception,GetMagickModule(),
5078 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5079 cache_info->filename);
5080 return(MagickFalse);
5082 nexus_info->length=0;
5083 nexus_info->mapped=MagickFalse;
5084 if (cache_anonymous_memory <= 0)
5086 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5088 if (nexus_info->cache != (Quantum *) NULL)
5089 (
void) memset(nexus_info->cache,0,(
size_t) length);
5093 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5094 if (nexus_info->cache != (Quantum *) NULL)
5095 nexus_info->mapped=MagickTrue;
5097 if (nexus_info->cache == (Quantum *) NULL)
5099 (void) ThrowMagickException(exception,GetMagickModule(),
5100 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5101 cache_info->filename);
5102 return(MagickFalse);
5104 nexus_info->length=length;
5108static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5111 if (nexus_info->length < CACHE_LINE_SIZE)
5113 if (mode == ReadMode)
5115 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5119 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5122static Quantum *SetPixelCacheNexusPixels(
5123 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5124 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5125 const MagickBooleanType buffered,
NexusInfo *magick_restrict nexus_info,
5135 assert(cache_info != (
const CacheInfo *) NULL);
5136 assert(cache_info->signature == MagickCoreSignature);
5137 if (cache_info->type == UndefinedCache)
5138 return((Quantum *) NULL);
5139 assert(nexus_info->signature == MagickCoreSignature);
5140 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5141 if ((width == 0) || (height == 0))
5143 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5144 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5145 return((Quantum *) NULL);
5147 if (((MagickSizeType) width > cache_info->width_limit) ||
5148 ((MagickSizeType) height > cache_info->height_limit))
5150 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5151 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5152 return((Quantum *) NULL);
5154 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5155 (IsValidPixelOffset(y,height) == MagickFalse))
5157 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5158 "InvalidPixel",
"`%s'",cache_info->filename);
5159 return((Quantum *) NULL);
5161 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5162 (buffered == MagickFalse))
5164 if (((x >= 0) && (y >= 0) &&
5165 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5166 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5167 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5175 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5176 return((Quantum *) NULL);
5177 offset=y*(MagickOffsetType) cache_info->columns+x;
5178 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5179 cache_info->number_channels*offset;
5180 nexus_info->metacontent=(
void *) NULL;
5181 if (cache_info->metacontent_extent != 0)
5182 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5183 offset*(MagickOffsetType) cache_info->metacontent_extent;
5184 nexus_info->region.width=width;
5185 nexus_info->region.height=height;
5186 nexus_info->region.x=x;
5187 nexus_info->region.y=y;
5188 nexus_info->authentic_pixel_cache=MagickTrue;
5189 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5190 return(nexus_info->pixels);
5196 number_pixels=(MagickSizeType) width*height;
5197 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5198 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5199 if (cache_info->metacontent_extent != 0)
5200 length+=number_pixels*cache_info->metacontent_extent;
5202 if (nexus_info->cache == (Quantum *) NULL)
5203 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5205 if (nexus_info->length < length)
5207 RelinquishCacheNexusPixels(nexus_info);
5208 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5210 if (status == MagickFalse)
5211 return((Quantum *) NULL);
5212 nexus_info->pixels=nexus_info->cache;
5213 nexus_info->metacontent=(
void *) NULL;
5214 if (cache_info->metacontent_extent != 0)
5215 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5216 cache_info->number_channels*number_pixels);
5217 nexus_info->region.width=width;
5218 nexus_info->region.height=height;
5219 nexus_info->region.x=x;
5220 nexus_info->region.y=y;
5221 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5222 MagickTrue : MagickFalse;
5223 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5224 return(nexus_info->pixels);
5257static MagickBooleanType SetCacheAlphaChannel(
Image *image,
const Quantum alpha,
5261 *magick_restrict image_view;
5269 assert(image != (
Image *) NULL);
5270 assert(image->signature == MagickCoreSignature);
5271 if (IsEventLogging() != MagickFalse)
5272 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5273 assert(image->cache != (Cache) NULL);
5274 image->alpha_trait=BlendPixelTrait;
5276 image_view=AcquireVirtualCacheView(image,exception);
5277#if defined(MAGICKCORE_OPENMP_SUPPORT)
5278 #pragma omp parallel for schedule(static) shared(status) \
5279 magick_number_threads(image,image,image->rows,2)
5281 for (y=0; y < (ssize_t) image->rows; y++)
5289 if (status == MagickFalse)
5291 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5292 if (q == (Quantum *) NULL)
5297 for (x=0; x < (ssize_t) image->columns; x++)
5299 SetPixelAlpha(image,alpha,q);
5300 q+=(ptrdiff_t) GetPixelChannels(image);
5302 status=SyncCacheViewAuthenticPixels(image_view,exception);
5304 image_view=DestroyCacheView(image_view);
5308MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(
Image *image,
5309 const VirtualPixelMethod virtual_pixel_method,
ExceptionInfo *exception)
5312 *magick_restrict cache_info;
5317 assert(image != (
Image *) NULL);
5318 assert(image->signature == MagickCoreSignature);
5319 if (IsEventLogging() != MagickFalse)
5320 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5321 assert(image->cache != (Cache) NULL);
5323 assert(cache_info->signature == MagickCoreSignature);
5324 method=cache_info->virtual_pixel_method;
5325 cache_info->virtual_pixel_method=virtual_pixel_method;
5326 if ((image->columns != 0) && (image->rows != 0))
5327 switch (virtual_pixel_method)
5329 case BackgroundVirtualPixelMethod:
5331 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5332 ((image->alpha_trait & BlendPixelTrait) == 0))
5333 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5334 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5335 (IsGrayColorspace(image->colorspace) != MagickFalse))
5336 (void) SetImageColorspace(image,sRGBColorspace,exception);
5339 case TransparentVirtualPixelMethod:
5341 if ((image->alpha_trait & BlendPixelTrait) == 0)
5342 (
void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5351#if defined(MAGICKCORE_OPENCL_SUPPORT)
5376static void CopyOpenCLBuffer(
CacheInfo *magick_restrict cache_info)
5378 assert(cache_info != (
CacheInfo *) NULL);
5379 assert(cache_info->signature == MagickCoreSignature);
5380 if ((cache_info->type != MemoryCache) ||
5381 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5386 LockSemaphoreInfo(cache_info->semaphore);
5387 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5388 UnlockSemaphoreInfo(cache_info->semaphore);
5391MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5394 *magick_restrict cache_info;
5396 assert(image != (
const Image *) NULL);
5398 CopyOpenCLBuffer(cache_info);
5431MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(
Image *image,
5435 *magick_restrict cache_info;
5443 assert(image != (
Image *) NULL);
5444 assert(image->signature == MagickCoreSignature);
5445 if (image->cache == (Cache) NULL)
5446 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5448 assert(cache_info->signature == MagickCoreSignature);
5449 if (cache_info->type == UndefinedCache)
5450 return(MagickFalse);
5451 if (image->mask_trait != UpdatePixelTrait)
5453 if (((image->channels & WriteMaskChannel) != 0) &&
5454 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5455 return(MagickFalse);
5456 if (((image->channels & CompositeMaskChannel) != 0) &&
5457 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5458 return(MagickFalse);
5460 if (nexus_info->authentic_pixel_cache != MagickFalse)
5462 if (image->taint == MagickFalse)
5463 image->taint=MagickTrue;
5466 assert(cache_info->signature == MagickCoreSignature);
5467 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5468 if ((cache_info->metacontent_extent != 0) &&
5469 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5470 return(MagickFalse);
5471 if ((status != MagickFalse) && (image->taint == MagickFalse))
5472 image->taint=MagickTrue;
5503static MagickBooleanType SyncAuthenticPixelsCache(
Image *image,
5507 *magick_restrict cache_info;
5510 id = GetOpenMPThreadId();
5515 assert(image != (
Image *) NULL);
5516 assert(image->signature == MagickCoreSignature);
5517 assert(image->cache != (Cache) NULL);
5519 assert(cache_info->signature == MagickCoreSignature);
5520 assert(
id < (
int) cache_info->number_threads);
5521 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5553MagickExport MagickBooleanType SyncAuthenticPixels(
Image *image,
5557 *magick_restrict cache_info;
5560 id = GetOpenMPThreadId();
5565 assert(image != (
Image *) NULL);
5566 assert(image->signature == MagickCoreSignature);
5567 assert(image->cache != (Cache) NULL);
5569 assert(cache_info->signature == MagickCoreSignature);
5570 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5572 status=cache_info->methods.sync_authentic_pixels_handler(image,
5576 assert(
id < (
int) cache_info->number_threads);
5577 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5609MagickPrivate MagickBooleanType SyncImagePixelCache(
Image *image,
5613 *magick_restrict cache_info;
5615 assert(image != (
Image *) NULL);
5617 cache_info=(
CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5618 return(cache_info == (
CacheInfo *) NULL ? MagickFalse : MagickTrue);
5649static MagickBooleanType WritePixelCacheMetacontent(
CacheInfo *cache_info,
5669 if (cache_info->metacontent_extent == 0)
5670 return(MagickFalse);
5671 if (nexus_info->authentic_pixel_cache != MagickFalse)
5673 if (nexus_info->metacontent == (
unsigned char *) NULL)
5674 return(MagickFalse);
5675 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5676 return(MagickFalse);
5677 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5678 nexus_info->region.x;
5679 length=(MagickSizeType) nexus_info->region.width*
5680 cache_info->metacontent_extent;
5681 extent=(MagickSizeType) length*nexus_info->region.height;
5682 rows=nexus_info->region.height;
5684 p=(
unsigned char *) nexus_info->metacontent;
5685 switch (cache_info->type)
5696 if ((cache_info->columns == nexus_info->region.width) &&
5697 (extent == (MagickSizeType) ((
size_t) extent)))
5702 q=(
unsigned char *) cache_info->metacontent+offset*
5703 (MagickOffsetType) cache_info->metacontent_extent;
5704 for (y=0; y < (ssize_t) rows; y++)
5706 (void) memcpy(q,p,(
size_t) length);
5707 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5708 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5717 LockSemaphoreInfo(cache_info->file_semaphore);
5718 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5720 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5721 cache_info->cache_filename);
5722 UnlockSemaphoreInfo(cache_info->file_semaphore);
5723 return(MagickFalse);
5725 if ((cache_info->columns == nexus_info->region.width) &&
5726 (extent <= MagickMaxBufferExtent))
5731 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5732 for (y=0; y < (ssize_t) rows; y++)
5734 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5735 (MagickOffsetType) extent*(MagickOffsetType)
5736 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5737 (MagickOffsetType) cache_info->metacontent_extent,length,
5738 (
const unsigned char *) p);
5739 if (count != (MagickOffsetType) length)
5741 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5742 offset+=(MagickOffsetType) cache_info->columns;
5744 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5745 (void) ClosePixelCacheOnDisk(cache_info);
5746 UnlockSemaphoreInfo(cache_info->file_semaphore);
5749 case DistributedCache:
5757 LockSemaphoreInfo(cache_info->file_semaphore);
5758 region=nexus_info->region;
5759 if ((cache_info->columns != nexus_info->region.width) ||
5760 (extent > MagickMaxBufferExtent))
5767 for (y=0; y < (ssize_t) rows; y++)
5770 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5771 if (count != (MagickOffsetType) length)
5773 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5776 UnlockSemaphoreInfo(cache_info->file_semaphore);
5782 if (y < (ssize_t) rows)
5784 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5785 cache_info->cache_filename);
5786 return(MagickFalse);
5788 if ((cache_info->debug != MagickFalse) &&
5789 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5790 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5791 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5792 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5793 nexus_info->region.x,(
double) nexus_info->region.y);
5825static MagickBooleanType WritePixelCachePixels(
5846 if (nexus_info->authentic_pixel_cache != MagickFalse)
5848 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5849 return(MagickFalse);
5850 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5851 nexus_info->region.x;
5852 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5854 extent=length*nexus_info->region.height;
5855 rows=nexus_info->region.height;
5857 p=nexus_info->pixels;
5858 switch (cache_info->type)
5869 if ((cache_info->columns == nexus_info->region.width) &&
5870 (extent == (MagickSizeType) ((
size_t) extent)))
5875 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5877 for (y=0; y < (ssize_t) rows; y++)
5879 (void) memcpy(q,p,(
size_t) length);
5880 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5881 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5890 LockSemaphoreInfo(cache_info->file_semaphore);
5891 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5893 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5894 cache_info->cache_filename);
5895 UnlockSemaphoreInfo(cache_info->file_semaphore);
5896 return(MagickFalse);
5898 if ((cache_info->columns == nexus_info->region.width) &&
5899 (extent <= MagickMaxBufferExtent))
5904 for (y=0; y < (ssize_t) rows; y++)
5906 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5907 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5908 sizeof(*p),length,(
const unsigned char *) p);
5909 if (count != (MagickOffsetType) length)
5911 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5912 offset+=(MagickOffsetType) cache_info->columns;
5914 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5915 (void) ClosePixelCacheOnDisk(cache_info);
5916 UnlockSemaphoreInfo(cache_info->file_semaphore);
5919 case DistributedCache:
5927 LockSemaphoreInfo(cache_info->file_semaphore);
5928 region=nexus_info->region;
5929 if ((cache_info->columns != nexus_info->region.width) ||
5930 (extent > MagickMaxBufferExtent))
5937 for (y=0; y < (ssize_t) rows; y++)
5940 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5941 if (count != (MagickOffsetType) length)
5943 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5946 UnlockSemaphoreInfo(cache_info->file_semaphore);
5952 if (y < (ssize_t) rows)
5954 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5955 cache_info->cache_filename);
5956 return(MagickFalse);
5958 if ((cache_info->debug != MagickFalse) &&
5959 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5960 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5961 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5962 nexus_info->region.width,(
double) nexus_info->region.height,(double)
5963 nexus_info->region.x,(
double) nexus_info->region.y);