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)
107 GetImagePixelCache(Image *,
const MagickBooleanType,ExceptionInfo *)
111 *GetVirtualPixelCache(
const Image *,
const VirtualPixelMethod,
const ssize_t,
112 const ssize_t,
const size_t,
const size_t,ExceptionInfo *),
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,
122 const ssize_t,
const ssize_t,Quantum *,ExceptionInfo *),
123 OpenPixelCache(Image *,
const MapMode,ExceptionInfo *),
124 OpenPixelCacheOnDisk(CacheInfo *,
const MapMode),
125 ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
127 ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
128 NexusInfo *magick_restrict,ExceptionInfo *),
129 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
130 WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
132 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
136 *GetAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
137 const size_t,ExceptionInfo *),
138 *QueueAuthenticPixelsCache(Image *,
const ssize_t,
const ssize_t,
const size_t,
139 const size_t,ExceptionInfo *),
140 *SetPixelCacheNexusPixels(
const CacheInfo *magick_restrict,
const MapMode,
141 const ssize_t,
const ssize_t,
const size_t,
const size_t,
142 const MagickBooleanType,NexusInfo *magick_restrict,ExceptionInfo *)
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));
194 if (cache_info == (CacheInfo *) NULL)
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 (cache_info->number_threads == 0)
207 cache_info->number_threads=1;
208 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
209 value=GetEnvironmentValue(
"MAGICK_SYNCHRONIZE");
210 if (value != (
const char *) NULL)
212 cache_info->synchronize=IsStringTrue(value);
213 value=DestroyString(value);
215 value=GetPolicyValue(
"cache:synchronize");
216 if (value != (
const char *) NULL)
218 cache_info->synchronize=IsStringTrue(value);
219 value=DestroyString(value);
221 cache_info->width_limit=MagickMin(GetMagickResourceLimit(WidthResource),
222 (MagickSizeType) MAGICK_SSIZE_MAX);
223 cache_info->height_limit=MagickMin(GetMagickResourceLimit(HeightResource),
224 (MagickSizeType) MAGICK_SSIZE_MAX);
225 cache_info->semaphore=AcquireSemaphoreInfo();
226 cache_info->reference_count=1;
227 cache_info->file_semaphore=AcquireSemaphoreInfo();
228 cache_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
230 cache_info->signature=MagickCoreSignature;
231 return((Cache ) cache_info);
256MagickPrivate NexusInfo **AcquirePixelCacheNexus(
const size_t number_threads)
259 **magick_restrict nexus_info;
264 nexus_info=(NexusInfo **) MagickAssumeAligned(AcquireAlignedMemory(2*
265 number_threads,
sizeof(*nexus_info)));
266 if (nexus_info == (NexusInfo **) NULL)
267 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
268 *nexus_info=(NexusInfo *) AcquireQuantumMemory(number_threads,
269 2*
sizeof(**nexus_info));
270 if (*nexus_info == (NexusInfo *) NULL)
271 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
272 (void) memset(*nexus_info,0,2*number_threads*
sizeof(**nexus_info));
273 for (i=0; i < (ssize_t) (2*number_threads); i++)
275 nexus_info[i]=(*nexus_info+i);
276 if (i < (ssize_t) number_threads)
277 nexus_info[i]->virtual_nexus=(*nexus_info+number_threads+i);
278 nexus_info[i]->signature=MagickCoreSignature;
311MagickExport
void *AcquirePixelCachePixels(
const Image *image,
size_t *length,
312 ExceptionInfo *exception)
315 *magick_restrict cache_info;
317 assert(image != (
const Image *) NULL);
318 assert(image->signature == MagickCoreSignature);
319 assert(exception != (ExceptionInfo *) NULL);
320 assert(exception->signature == MagickCoreSignature);
321 assert(image->cache != (Cache) NULL);
323 cache_info=(CacheInfo *) image->cache;
324 assert(cache_info->signature == MagickCoreSignature);
326 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
327 return((
void *) NULL);
328 *length=(size_t) cache_info->length;
329 return(cache_info->pixels);
350MagickPrivate MagickBooleanType CacheComponentGenesis(
void)
353 cache_semaphore=AcquireSemaphoreInfo();
375MagickPrivate
void CacheComponentTerminus(
void)
378 ActivateSemaphoreInfo(&cache_semaphore);
380 RelinquishSemaphoreInfo(&cache_semaphore);
412static MagickBooleanType ClipPixelCacheNexus(Image *image,
413 NexusInfo *nexus_info,ExceptionInfo *exception)
416 *magick_restrict cache_info;
428 if (IsEventLogging() != MagickFalse)
429 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
430 if ((image->channels & WriteMaskChannel) == 0)
432 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
434 cache_info=(CacheInfo *) image->cache;
435 if (cache_info == (CacheInfo *) NULL)
437 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
438 nexus_info->region.width,nexus_info->region.height,
439 nexus_info->virtual_nexus,exception);
440 q=nexus_info->pixels;
441 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
443 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
448 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
456 mask_alpha=QuantumScale*(double) GetPixelWriteMask(image,p);
457 if (fabs(mask_alpha) >= MagickEpsilon)
459 for (i=0; i < (ssize_t) image->number_channels; i++)
461 PixelChannel channel = GetPixelChannelChannel(image,i);
462 PixelTrait traits = GetPixelChannelTraits(image,channel);
463 if ((traits & UpdatePixelTrait) == 0)
465 q[i]=ClampToQuantum(MagickOver_((
double) p[i],mask_alpha*(
double)
466 GetPixelAlpha(image,p),(
double) q[i],(
double)
467 GetPixelAlpha(image,q)));
469 SetPixelAlpha(image,GetPixelAlpha(image,p),q);
471 p+=(ptrdiff_t) GetPixelChannels(image);
472 q+=(ptrdiff_t) GetPixelChannels(image);
500MagickPrivate Cache ClonePixelCache(
const Cache cache)
503 *magick_restrict clone_info;
506 *magick_restrict cache_info;
508 assert(cache != NULL);
509 cache_info=(
const CacheInfo *) cache;
510 assert(cache_info->signature == MagickCoreSignature);
511 if (IsEventLogging() != MagickFalse)
512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
513 cache_info->filename);
514 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
515 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
516 return((Cache ) clone_info);
544MagickPrivate
void ClonePixelCacheMethods(Cache clone,
const Cache cache)
547 *magick_restrict cache_info,
548 *magick_restrict source_info;
550 assert(clone != (Cache) NULL);
551 source_info=(CacheInfo *) clone;
552 assert(source_info->signature == MagickCoreSignature);
553 if (IsEventLogging() != MagickFalse)
554 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
555 source_info->filename);
556 assert(cache != (Cache) NULL);
557 cache_info=(CacheInfo *) cache;
558 assert(cache_info->signature == MagickCoreSignature);
559 source_info->methods=cache_info->methods;
591static MagickBooleanType ClonePixelCacheOnDisk(
592 CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
612 if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
613 (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
615 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
616 (lseek(clone_info->file,0,SEEK_SET) < 0))
618 quantum=(size_t) MagickMaxBufferExtent;
619 if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
621#if defined(MAGICKCORE_HAVE_LINUX_SENDFILE)
622 if (cache_info->length < 0x7ffff000)
624 count=sendfile(clone_info->file,cache_info->file,(off_t *) NULL,
625 (
size_t) cache_info->length);
626 if (count == (ssize_t) cache_info->length)
628 if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
629 (lseek(clone_info->file,0,SEEK_SET) < 0))
633 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
635 buffer=(
unsigned char *) AcquireQuantumMemory(quantum,
sizeof(*buffer));
636 if (buffer == (
unsigned char *) NULL)
637 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
639 while ((count=read(cache_info->file,buffer,quantum)) > 0)
644 number_bytes=write(clone_info->file,buffer,(
size_t) count);
645 if (number_bytes != count)
647 extent+=(size_t) number_bytes;
649 buffer=(
unsigned char *) RelinquishMagickMemory(buffer);
650 if (extent != cache_info->length)
655static inline int GetCacheNumberThreads(
const CacheInfo *source,
656 const CacheInfo *destination,
const size_t chunk,
const int factor)
659 max_threads = (size_t) GetMagickResourceLimit(ThreadResource),
660 number_threads = 1UL,
661 workload_factor = 64UL << factor;
666 number_threads=(chunk <= workload_factor) ? 1UL :
667 (chunk >= (workload_factor << 6)) ? max_threads :
668 1UL+(chunk-workload_factor)*(max_threads-1L)/(((workload_factor << 6))-1L);
672 if (((source->type != MemoryCache) && (source->type != MapCache)) ||
673 ((destination->type != MemoryCache) && (destination->type != MapCache)))
674 number_threads=MagickMin(number_threads,4);
675 return((
int) number_threads);
678static MagickBooleanType ClonePixelCacheRepository(
679 CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
680 ExceptionInfo *exception)
682#define cache_number_threads(source,destination,chunk,factor) \
683 num_threads(GetCacheNumberThreads((source),(destination),(chunk),(factor)))
690 **magick_restrict cache_nexus,
691 **magick_restrict clone_nexus;
699 assert(cache_info != (CacheInfo *) NULL);
700 assert(clone_info != (CacheInfo *) NULL);
701 assert(exception != (ExceptionInfo *) NULL);
702 if (cache_info->type == PingCache)
704 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
705 if ((cache_info->storage_class == clone_info->storage_class) &&
706 (cache_info->colorspace == clone_info->colorspace) &&
707 (cache_info->alpha_trait == clone_info->alpha_trait) &&
708 (cache_info->channels == clone_info->channels) &&
709 (cache_info->columns == clone_info->columns) &&
710 (cache_info->rows == clone_info->rows) &&
711 (cache_info->number_channels == clone_info->number_channels) &&
712 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
713 (cache_info->metacontent_extent == clone_info->metacontent_extent))
718 if (((cache_info->type == MemoryCache) ||
719 (cache_info->type == MapCache)) &&
720 ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
722 (void) memcpy(clone_info->pixels,cache_info->pixels,
723 cache_info->number_channels*cache_info->columns*cache_info->rows*
724 sizeof(*cache_info->pixels));
725 if ((cache_info->metacontent_extent != 0) &&
726 (clone_info->metacontent_extent != 0))
727 (void) memcpy(clone_info->metacontent,cache_info->metacontent,
728 cache_info->columns*cache_info->rows*
729 clone_info->metacontent_extent*
sizeof(
unsigned char));
732 if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
733 return(ClonePixelCacheOnDisk(cache_info,clone_info));
738 cache_nexus=AcquirePixelCacheNexus(cache_info->number_threads);
739 clone_nexus=AcquirePixelCacheNexus(clone_info->number_threads);
740 length=cache_info->number_channels*
sizeof(*cache_info->channel_map);
741 optimize=(cache_info->number_channels == clone_info->number_channels) &&
742 (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
743 MagickTrue : MagickFalse;
744 length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
745 clone_info->number_channels*clone_info->columns);
747#if defined(MAGICKCORE_OPENMP_SUPPORT)
748 #pragma omp parallel for schedule(static) shared(status) \
749 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
751 for (y=0; y < (ssize_t) cache_info->rows; y++)
754 id = GetOpenMPThreadId();
762 if (status == MagickFalse)
764 if (y >= (ssize_t) clone_info->rows)
766 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
767 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
768 if (pixels == (Quantum *) NULL)
770 status=ReadPixelCachePixels(cache_info,cache_nexus[
id],exception);
771 if (status == MagickFalse)
773 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
774 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
775 if (pixels == (Quantum *) NULL)
777 (void) memset(clone_nexus[
id]->pixels,0,(
size_t) clone_nexus[
id]->length);
778 if (optimize != MagickFalse)
779 (void) memcpy(clone_nexus[
id]->pixels,cache_nexus[
id]->pixels,length*
792 p=cache_nexus[id]->pixels;
793 q=clone_nexus[id]->pixels;
794 for (x=0; x < (ssize_t) cache_info->columns; x++)
799 if (x == (ssize_t) clone_info->columns)
801 for (i=0; i < (ssize_t) clone_info->number_channels; i++)
809 channel=clone_info->channel_map[i].channel;
810 traits=cache_info->channel_map[channel].traits;
811 if (traits != UndefinedPixelTrait)
812 *q=*(p+cache_info->channel_map[channel].offset);
815 p+=(ptrdiff_t) cache_info->number_channels;
818 status=WritePixelCachePixels(clone_info,clone_nexus[
id],exception);
820 if ((cache_info->metacontent_extent != 0) &&
821 (clone_info->metacontent_extent != 0))
826 length=(size_t) MagickMin(cache_info->metacontent_extent,
827 clone_info->metacontent_extent);
828#if defined(MAGICKCORE_OPENMP_SUPPORT)
829 #pragma omp parallel for schedule(static) shared(status) \
830 cache_number_threads(cache_info,clone_info,cache_info->rows,3)
832 for (y=0; y < (ssize_t) cache_info->rows; y++)
835 id = GetOpenMPThreadId();
840 if (status == MagickFalse)
842 if (y >= (ssize_t) clone_info->rows)
844 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
845 cache_info->columns,1,MagickFalse,cache_nexus[
id],exception);
846 if (pixels == (Quantum *) NULL)
848 status=ReadPixelCacheMetacontent(cache_info,cache_nexus[
id],exception);
849 if (status == MagickFalse)
851 pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
852 clone_info->columns,1,MagickFalse,clone_nexus[
id],exception);
853 if (pixels == (Quantum *) NULL)
855 if ((clone_nexus[
id]->metacontent != (
void *) NULL) &&
856 (cache_nexus[
id]->metacontent != (
void *) NULL))
857 (void) memcpy(clone_nexus[
id]->metacontent,
858 cache_nexus[
id]->metacontent,length*
sizeof(
unsigned char));
859 status=WritePixelCacheMetacontent(clone_info,clone_nexus[
id],exception);
862 clone_nexus=DestroyPixelCacheNexus(clone_nexus,clone_info->number_threads);
863 cache_nexus=DestroyPixelCacheNexus(cache_nexus,cache_info->number_threads);
864 if (cache_info->debug != MagickFalse)
867 message[MagickPathExtent];
869 (void) FormatLocaleString(message,MagickPathExtent,
"%s => %s",
870 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
871 CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
872 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
899static void DestroyImagePixelCache(Image *image)
901 assert(image != (Image *) NULL);
902 assert(image->signature == MagickCoreSignature);
903 if (IsEventLogging() != MagickFalse)
904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
905 if (image->cache != (
void *) NULL)
906 image->cache=DestroyPixelCache(image->cache);
931MagickExport
void DestroyImagePixels(Image *image)
934 *magick_restrict cache_info;
936 assert(image != (
const Image *) NULL);
937 assert(image->signature == MagickCoreSignature);
938 if (IsEventLogging() != MagickFalse)
939 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
940 assert(image->cache != (Cache) NULL);
941 cache_info=(CacheInfo *) image->cache;
942 assert(cache_info->signature == MagickCoreSignature);
943 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
945 cache_info->methods.destroy_pixel_handler(image);
948 image->cache=DestroyPixelCache(image->cache);
974static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
980 if (cache_info->file != -1)
982 status=close_utf8(cache_info->file);
983 cache_info->file=(-1);
984 RelinquishMagickResource(FileResource,1);
986 return(status == -1 ? MagickFalse : MagickTrue);
989static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
991 switch (cache_info->type)
995 (void) ShredMagickMemory(cache_info->pixels,(
size_t) cache_info->length);
996#if defined(MAGICKCORE_OPENCL_SUPPORT)
997 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
999 cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
1001 cache_info->pixels=(Quantum *) NULL;
1005 if (cache_info->mapped == MagickFalse)
1006 cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
1007 cache_info->pixels);
1010 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1011 cache_info->pixels=(Quantum *) NULL;
1013 RelinquishMagickResource(MemoryResource,cache_info->length);
1018 (void) UnmapBlob(cache_info->pixels,(
size_t) cache_info->length);
1019 cache_info->pixels=(Quantum *) NULL;
1020 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1021 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1022 *cache_info->cache_filename=
'\0';
1023 RelinquishMagickResource(MapResource,cache_info->length);
1028 if (cache_info->file != -1)
1029 (void) ClosePixelCacheOnDisk(cache_info);
1030 if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
1031 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
1032 *cache_info->cache_filename=
'\0';
1033 RelinquishMagickResource(DiskResource,cache_info->length);
1036 case DistributedCache:
1038 *cache_info->cache_filename=
'\0';
1039 (void) RelinquishDistributePixelCache((DistributeCacheInfo *)
1040 cache_info->server_info);
1046 cache_info->type=UndefinedCache;
1047 cache_info->mapped=MagickFalse;
1048 cache_info->metacontent=(
void *) NULL;
1051MagickPrivate Cache DestroyPixelCache(Cache cache)
1054 *magick_restrict cache_info;
1056 assert(cache != (Cache) NULL);
1057 cache_info=(CacheInfo *) cache;
1058 assert(cache_info->signature == MagickCoreSignature);
1059 if (IsEventLogging() != MagickFalse)
1060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
1061 cache_info->filename);
1062 LockSemaphoreInfo(cache_info->semaphore);
1063 cache_info->reference_count--;
1064 if (cache_info->reference_count != 0)
1066 UnlockSemaphoreInfo(cache_info->semaphore);
1067 return((Cache) NULL);
1069 UnlockSemaphoreInfo(cache_info->semaphore);
1070 if (cache_info->debug != MagickFalse)
1073 message[MagickPathExtent];
1075 (void) FormatLocaleString(message,MagickPathExtent,
"destroy %s",
1076 cache_info->filename);
1077 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
1079 RelinquishPixelCachePixels(cache_info);
1080 if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1081 cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1082 cache_info->server_info);
1083 if (cache_info->nexus_info != (NexusInfo **) NULL)
1084 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1085 cache_info->number_threads);
1086 if (cache_info->random_info != (RandomInfo *) NULL)
1087 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1089 RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1091 RelinquishSemaphoreInfo(&cache_info->semaphore);
1092 cache_info->signature=(~MagickCoreSignature);
1093 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1124static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1126 if (nexus_info->mapped == MagickFalse)
1127 (void) RelinquishAlignedMemory(nexus_info->cache);
1129 (
void) UnmapBlob(nexus_info->cache,(
size_t) nexus_info->length);
1130 nexus_info->cache=(Quantum *) NULL;
1131 nexus_info->pixels=(Quantum *) NULL;
1132 nexus_info->metacontent=(
void *) NULL;
1133 nexus_info->length=0;
1134 nexus_info->mapped=MagickFalse;
1137MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
1138 const size_t number_threads)
1143 assert(nexus_info != (NexusInfo **) NULL);
1144 for (i=0; i < (ssize_t) (2*number_threads); i++)
1146 if (nexus_info[i]->cache != (Quantum *) NULL)
1147 RelinquishCacheNexusPixels(nexus_info[i]);
1148 nexus_info[i]->signature=(~MagickCoreSignature);
1150 *nexus_info=(NexusInfo *) RelinquishMagickMemory(*nexus_info);
1151 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1180MagickExport
void *GetAuthenticMetacontent(
const Image *image)
1183 *magick_restrict cache_info;
1186 id = GetOpenMPThreadId();
1188 assert(image != (
const Image *) NULL);
1189 assert(image->signature == MagickCoreSignature);
1190 assert(image->cache != (Cache) NULL);
1191 cache_info=(CacheInfo *) image->cache;
1192 assert(cache_info->signature == MagickCoreSignature);
1193 if (cache_info->methods.get_authentic_metacontent_from_handler !=
1194 (GetAuthenticMetacontentFromHandler) NULL)
1199 metacontent=cache_info->methods.
1200 get_authentic_metacontent_from_handler(image);
1201 return(metacontent);
1203 assert(
id < (
int) cache_info->number_threads);
1204 return(cache_info->nexus_info[
id]->metacontent);
1231static void *GetAuthenticMetacontentFromCache(
const Image *image)
1234 *magick_restrict cache_info;
1237 id = GetOpenMPThreadId();
1239 assert(image != (
const Image *) NULL);
1240 assert(image->signature == MagickCoreSignature);
1241 assert(image->cache != (Cache) NULL);
1242 cache_info=(CacheInfo *) image->cache;
1243 assert(cache_info->signature == MagickCoreSignature);
1244 assert(
id < (
int) cache_info->number_threads);
1245 return(cache_info->nexus_info[
id]->metacontent);
1248#if defined(MAGICKCORE_OPENCL_SUPPORT)
1277MagickPrivate cl_mem GetAuthenticOpenCLBuffer(
const Image *image,
1278 MagickCLDevice device,ExceptionInfo *exception)
1281 *magick_restrict cache_info;
1283 assert(image != (
const Image *) NULL);
1284 assert(device != (
const MagickCLDevice) NULL);
1285 cache_info=(CacheInfo *) image->cache;
1286 if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1288 SyncImagePixelCache((Image *) image,exception);
1289 cache_info=(CacheInfo *) image->cache;
1291 if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1292 return((cl_mem) NULL);
1293 LockSemaphoreInfo(cache_info->semaphore);
1294 if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1295 (cache_info->opencl->device->context != device->context))
1296 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1297 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1299 assert(cache_info->pixels != (Quantum *) NULL);
1300 cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1301 cache_info->length);
1303 if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1304 RetainOpenCLMemObject(cache_info->opencl->buffer);
1305 UnlockSemaphoreInfo(cache_info->semaphore);
1306 if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1307 return((cl_mem) NULL);
1308 assert(cache_info->opencl->pixels == cache_info->pixels);
1309 return(cache_info->opencl->buffer);
1348MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,
const ssize_t x,
1349 const ssize_t y,
const size_t columns,
const size_t rows,NexusInfo *nexus_info,
1350 ExceptionInfo *exception)
1353 *magick_restrict cache_info;
1356 *magick_restrict pixels;
1361 assert(image != (Image *) NULL);
1362 assert(image->signature == MagickCoreSignature);
1363 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1364 nexus_info,exception);
1365 if (pixels == (Quantum *) NULL)
1366 return((Quantum *) NULL);
1367 cache_info=(CacheInfo *) image->cache;
1368 assert(cache_info->signature == MagickCoreSignature);
1369 if (nexus_info->authentic_pixel_cache != MagickFalse)
1371 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1372 return((Quantum *) NULL);
1373 if (cache_info->metacontent_extent != 0)
1374 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1375 return((Quantum *) NULL);
1402static Quantum *GetAuthenticPixelsFromCache(
const Image *image)
1405 *magick_restrict cache_info;
1408 id = GetOpenMPThreadId();
1410 assert(image != (
const Image *) NULL);
1411 assert(image->signature == MagickCoreSignature);
1412 assert(image->cache != (Cache) NULL);
1413 cache_info=(CacheInfo *) image->cache;
1414 assert(cache_info->signature == MagickCoreSignature);
1415 assert(
id < (
int) cache_info->number_threads);
1416 return(cache_info->nexus_info[
id]->pixels);
1443MagickExport Quantum *GetAuthenticPixelQueue(
const Image *image)
1446 *magick_restrict cache_info;
1449 id = GetOpenMPThreadId();
1451 assert(image != (
const Image *) NULL);
1452 assert(image->signature == MagickCoreSignature);
1453 assert(image->cache != (Cache) NULL);
1454 cache_info=(CacheInfo *) image->cache;
1455 assert(cache_info->signature == MagickCoreSignature);
1456 if (cache_info->methods.get_authentic_pixels_from_handler !=
1457 (GetAuthenticPixelsFromHandler) NULL)
1458 return(cache_info->methods.get_authentic_pixels_from_handler(image));
1459 assert(
id < (
int) cache_info->number_threads);
1460 return(cache_info->nexus_info[
id]->pixels);
1508MagickExport Quantum *GetAuthenticPixels(Image *image,
const ssize_t x,
1509 const ssize_t y,
const size_t columns,
const size_t rows,
1510 ExceptionInfo *exception)
1513 *magick_restrict cache_info;
1516 id = GetOpenMPThreadId();
1521 assert(image != (Image *) NULL);
1522 assert(image->signature == MagickCoreSignature);
1523 assert(image->cache != (Cache) NULL);
1524 cache_info=(CacheInfo *) image->cache;
1525 assert(cache_info->signature == MagickCoreSignature);
1526 if (cache_info->methods.get_authentic_pixels_handler !=
1527 (GetAuthenticPixelsHandler) NULL)
1529 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1533 assert(
id < (
int) cache_info->number_threads);
1534 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1535 cache_info->nexus_info[
id],exception);
1570static Quantum *GetAuthenticPixelsCache(Image *image,
const ssize_t x,
1571 const ssize_t y,
const size_t columns,
const size_t rows,
1572 ExceptionInfo *exception)
1575 *magick_restrict cache_info;
1578 id = GetOpenMPThreadId();
1581 *magick_restrict pixels;
1583 assert(image != (
const Image *) NULL);
1584 assert(image->signature == MagickCoreSignature);
1585 assert(image->cache != (Cache) NULL);
1586 cache_info=(CacheInfo *) image->cache;
1587 if (cache_info == (Cache) NULL)
1588 return((Quantum *) NULL);
1589 assert(cache_info->signature == MagickCoreSignature);
1590 assert(
id < (
int) cache_info->number_threads);
1591 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1592 cache_info->nexus_info[
id],exception);
1619MagickExport MagickSizeType GetImageExtent(
const Image *image)
1622 *magick_restrict cache_info;
1625 id = GetOpenMPThreadId();
1627 assert(image != (Image *) NULL);
1628 assert(image->signature == MagickCoreSignature);
1629 if (IsEventLogging() != MagickFalse)
1630 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1631 assert(image->cache != (Cache) NULL);
1632 cache_info=(CacheInfo *) image->cache;
1633 assert(cache_info->signature == MagickCoreSignature);
1634 assert(
id < (
int) cache_info->number_threads);
1635 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[
id]));
1668static inline MagickBooleanType ValidatePixelCacheMorphology(
1669 const Image *magick_restrict image)
1672 *magick_restrict cache_info;
1674 const PixelChannelMap
1681 cache_info=(CacheInfo *) image->cache;
1682 p=image->channel_map;
1683 q=cache_info->channel_map;
1684 if ((image->storage_class != cache_info->storage_class) ||
1685 (image->colorspace != cache_info->colorspace) ||
1686 (image->alpha_trait != cache_info->alpha_trait) ||
1687 (image->channels != cache_info->channels) ||
1688 (image->columns != cache_info->columns) ||
1689 (image->rows != cache_info->rows) ||
1690 (image->number_channels != cache_info->number_channels) ||
1691 (memcmp(p,q,image->number_channels*
sizeof(*p)) != 0) ||
1692 (image->metacontent_extent != cache_info->metacontent_extent) ||
1693 (cache_info->nexus_info == (NexusInfo **) NULL))
1694 return(MagickFalse);
1698static Cache GetImagePixelCache(Image *image,
const MagickBooleanType clone,
1699 ExceptionInfo *exception)
1702 *magick_restrict cache_info;
1706 status = MagickTrue;
1708 static MagickSizeType
1709 cpu_throttle = MagickResourceInfinity,
1712 if (IsImageTTLExpired(image) != MagickFalse)
1717 (void) ThrowMagickException(exception,GetMagickModule(),
1718 ResourceLimitError,
"TimeLimitExceeded",
"`%s'",image->filename);
1719 return((Cache) NULL);
1721 if (cpu_throttle == MagickResourceInfinity)
1722 cpu_throttle=GetMagickResourceLimit(ThrottleResource);
1723 if ((cpu_throttle != 0) && ((cycles++ % 4096) == 0))
1724 MagickDelay(cpu_throttle);
1725 LockSemaphoreInfo(image->semaphore);
1726 assert(image->cache != (Cache) NULL);
1727 cache_info=(CacheInfo *) image->cache;
1728#if defined(MAGICKCORE_OPENCL_SUPPORT)
1729 CopyOpenCLBuffer(cache_info);
1731 destroy=MagickFalse;
1732 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1734 LockSemaphoreInfo(cache_info->semaphore);
1735 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1746 clone_image=(*image);
1747 clone_image.semaphore=AcquireSemaphoreInfo();
1748 clone_image.reference_count=1;
1749 clone_image.cache=ClonePixelCache(cache_info);
1750 clone_info=(CacheInfo *) clone_image.cache;
1751 status=OpenPixelCache(&clone_image,IOMode,exception);
1752 if (status == MagickFalse)
1753 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1756 if (clone != MagickFalse)
1757 status=ClonePixelCacheRepository(clone_info,cache_info,
1759 if (status == MagickFalse)
1760 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1764 image->cache=clone_info;
1767 RelinquishSemaphoreInfo(&clone_image.semaphore);
1769 UnlockSemaphoreInfo(cache_info->semaphore);
1771 if (destroy != MagickFalse)
1772 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1773 if (status != MagickFalse)
1778 if (image->type != UndefinedType)
1779 image->type=UndefinedType;
1780 if (ValidatePixelCacheMorphology(image) == MagickFalse)
1782 status=OpenPixelCache(image,IOMode,exception);
1783 cache_info=(CacheInfo *) image->cache;
1784 if (cache_info->file != -1)
1785 (void) ClosePixelCacheOnDisk(cache_info);
1788 UnlockSemaphoreInfo(image->semaphore);
1789 if (status == MagickFalse)
1790 return((Cache) NULL);
1791 return(image->cache);
1817MagickExport CacheType GetImagePixelCacheType(
const Image *image)
1820 *magick_restrict cache_info;
1822 assert(image != (Image *) NULL);
1823 assert(image->signature == MagickCoreSignature);
1824 assert(image->cache != (Cache) NULL);
1825 cache_info=(CacheInfo *) image->cache;
1826 assert(cache_info->signature == MagickCoreSignature);
1827 return(cache_info->type);
1861static inline MagickBooleanType CopyPixel(
const Image *image,
1862 const Quantum *source,Quantum *destination)
1867 if (source == (
const Quantum *) NULL)
1869 destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1870 destination[GreenPixelChannel]=ClampToQuantum(
1871 image->background_color.green);
1872 destination[BluePixelChannel]=ClampToQuantum(
1873 image->background_color.blue);
1874 destination[BlackPixelChannel]=ClampToQuantum(
1875 image->background_color.black);
1876 destination[AlphaPixelChannel]=ClampToQuantum(
1877 image->background_color.alpha);
1878 return(MagickFalse);
1880 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1882 PixelChannel channel = GetPixelChannelChannel(image,i);
1883 destination[channel]=source[i];
1888MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
1889 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1892 *magick_restrict cache_info;
1897 assert(image != (Image *) NULL);
1898 assert(image->signature == MagickCoreSignature);
1899 assert(image->cache != (Cache) NULL);
1900 cache_info=(CacheInfo *) image->cache;
1901 assert(cache_info->signature == MagickCoreSignature);
1902 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1903 if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1904 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1905 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1906 return(CopyPixel(image,q,pixel));
1940static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
1941 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1944 *magick_restrict cache_info;
1947 id = GetOpenMPThreadId();
1952 assert(image != (
const Image *) NULL);
1953 assert(image->signature == MagickCoreSignature);
1954 assert(image->cache != (Cache) NULL);
1955 cache_info=(CacheInfo *) image->cache;
1956 assert(cache_info->signature == MagickCoreSignature);
1957 assert(
id < (
int) cache_info->number_threads);
1958 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
1959 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[
id],
1961 return(CopyPixel(image,q,pixel));
1995MagickExport MagickBooleanType GetOneVirtualPixel(
const Image *image,
1996 const ssize_t x,
const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1999 *magick_restrict cache_info;
2002 id = GetOpenMPThreadId();
2007 assert(image != (
const Image *) NULL);
2008 assert(image->signature == MagickCoreSignature);
2009 assert(image->cache != (Cache) NULL);
2010 cache_info=(CacheInfo *) image->cache;
2011 assert(cache_info->signature == MagickCoreSignature);
2012 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2013 if (cache_info->methods.get_one_virtual_pixel_from_handler !=
2014 (GetOneVirtualPixelFromHandler) NULL)
2015 return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
2016 GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
2017 assert(
id < (
int) cache_info->number_threads);
2018 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
2019 1UL,1UL,cache_info->nexus_info[
id],exception);
2020 return(CopyPixel(image,p,pixel));
2057static MagickBooleanType GetOneVirtualPixelFromCache(
const Image *image,
2058 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2059 Quantum *pixel,ExceptionInfo *exception)
2062 *magick_restrict cache_info;
2065 id = GetOpenMPThreadId();
2070 assert(image != (
const Image *) NULL);
2071 assert(image->signature == MagickCoreSignature);
2072 assert(image->cache != (Cache) NULL);
2073 cache_info=(CacheInfo *) image->cache;
2074 assert(cache_info->signature == MagickCoreSignature);
2075 assert(
id < (
int) cache_info->number_threads);
2076 (void) memset(pixel,0,MaxPixelChannels*
sizeof(*pixel));
2077 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2078 cache_info->nexus_info[
id],exception);
2079 return(CopyPixel(image,p,pixel));
2116MagickExport MagickBooleanType GetOneVirtualPixelInfo(
const Image *image,
2117 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2118 PixelInfo *pixel,ExceptionInfo *exception)
2121 *magick_restrict cache_info;
2124 id = GetOpenMPThreadId();
2129 assert(image != (
const Image *) NULL);
2130 assert(image->signature == MagickCoreSignature);
2131 assert(image->cache != (Cache) NULL);
2132 cache_info=(CacheInfo *) image->cache;
2133 assert(cache_info->signature == MagickCoreSignature);
2134 assert(
id < (
int) cache_info->number_threads);
2135 GetPixelInfo(image,pixel);
2136 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2137 cache_info->nexus_info[
id],exception);
2138 if (p == (
const Quantum *) NULL)
2139 return(MagickFalse);
2140 GetPixelInfoPixel(image,p,pixel);
2166MagickPrivate ColorspaceType GetPixelCacheColorspace(
const Cache cache)
2169 *magick_restrict cache_info;
2171 assert(cache != (Cache) NULL);
2172 cache_info=(CacheInfo *) cache;
2173 assert(cache_info->signature == MagickCoreSignature);
2174 if (IsEventLogging() != MagickFalse)
2175 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2176 cache_info->filename);
2177 return(cache_info->colorspace);
2203MagickExport
const char *GetPixelCacheFilename(
const Image *image)
2206 *magick_restrict cache_info;
2208 assert(image != (
const Image *) NULL);
2209 assert(image->signature == MagickCoreSignature);
2210 assert(image->cache != (Cache) NULL);
2211 cache_info=(CacheInfo *) image->cache;
2212 assert(cache_info->signature == MagickCoreSignature);
2213 return(cache_info->cache_filename);
2238MagickPrivate
void GetPixelCacheMethods(CacheMethods *cache_methods)
2240 assert(cache_methods != (CacheMethods *) NULL);
2241 (void) memset(cache_methods,0,
sizeof(*cache_methods));
2242 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
2243 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
2244 cache_methods->get_virtual_metacontent_from_handler=
2245 GetVirtualMetacontentFromCache;
2246 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
2247 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
2248 cache_methods->get_authentic_metacontent_from_handler=
2249 GetAuthenticMetacontentFromCache;
2250 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
2251 cache_methods->get_one_authentic_pixel_from_handler=
2252 GetOneAuthenticPixelFromCache;
2253 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
2254 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
2255 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
2283MagickPrivate MagickSizeType GetPixelCacheNexusExtent(
const Cache cache,
2284 NexusInfo *magick_restrict nexus_info)
2287 *magick_restrict cache_info;
2292 assert(cache != NULL);
2293 cache_info=(CacheInfo *) cache;
2294 assert(cache_info->signature == MagickCoreSignature);
2295 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2297 return((MagickSizeType) cache_info->columns*cache_info->rows);
2328MagickExport
void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2329 ExceptionInfo *magick_unused(exception))
2332 *magick_restrict cache_info;
2334 assert(image != (
const Image *) NULL);
2335 assert(image->signature == MagickCoreSignature);
2336 assert(image->cache != (Cache) NULL);
2337 assert(length != (MagickSizeType *) NULL);
2338 magick_unreferenced(exception);
2339 cache_info=(CacheInfo *) image->cache;
2340 assert(cache_info->signature == MagickCoreSignature);
2341 *length=cache_info->length;
2342 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2343 return((
void *) NULL);
2344 return((
void *) cache_info->pixels);
2371MagickPrivate ClassType GetPixelCacheStorageClass(
const Cache cache)
2374 *magick_restrict cache_info;
2376 assert(cache != (Cache) NULL);
2377 cache_info=(CacheInfo *) cache;
2378 assert(cache_info->signature == MagickCoreSignature);
2379 if (IsEventLogging() != MagickFalse)
2380 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
2381 cache_info->filename);
2382 return(cache_info->storage_class);
2412MagickPrivate
void GetPixelCacheTileSize(
const Image *image,
size_t *width,
2416 *magick_restrict cache_info;
2418 assert(image != (Image *) NULL);
2419 assert(image->signature == MagickCoreSignature);
2420 if (IsEventLogging() != MagickFalse)
2421 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2422 cache_info=(CacheInfo *) image->cache;
2423 assert(cache_info->signature == MagickCoreSignature);
2424 *width=2048UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2425 if (GetImagePixelCacheType(image) == DiskCache)
2426 *width=8192UL/(MagickMax(cache_info->number_channels,1)*
sizeof(Quantum));
2454MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(
const Image *image)
2457 *magick_restrict cache_info;
2459 assert(image != (Image *) NULL);
2460 assert(image->signature == MagickCoreSignature);
2461 assert(image->cache != (Cache) NULL);
2462 cache_info=(CacheInfo *) image->cache;
2463 assert(cache_info->signature == MagickCoreSignature);
2464 return(cache_info->virtual_pixel_method);
2490static const void *GetVirtualMetacontentFromCache(
const Image *image)
2493 *magick_restrict cache_info;
2496 id = GetOpenMPThreadId();
2499 *magick_restrict metacontent;
2501 assert(image != (
const Image *) NULL);
2502 assert(image->signature == MagickCoreSignature);
2503 assert(image->cache != (Cache) NULL);
2504 cache_info=(CacheInfo *) image->cache;
2505 assert(cache_info->signature == MagickCoreSignature);
2506 assert(
id < (
int) cache_info->number_threads);
2507 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2508 cache_info->nexus_info[
id]);
2509 return(metacontent);
2538MagickPrivate
const void *GetVirtualMetacontentFromNexus(
const Cache cache,
2539 NexusInfo *magick_restrict nexus_info)
2542 *magick_restrict cache_info;
2544 assert(cache != (Cache) NULL);
2545 cache_info=(CacheInfo *) cache;
2546 assert(cache_info->signature == MagickCoreSignature);
2547 if (cache_info->storage_class == UndefinedClass)
2548 return((
void *) NULL);
2549 return(nexus_info->metacontent);
2576MagickExport
const void *GetVirtualMetacontent(
const Image *image)
2579 *magick_restrict cache_info;
2582 id = GetOpenMPThreadId();
2585 *magick_restrict metacontent;
2587 assert(image != (
const Image *) NULL);
2588 assert(image->signature == MagickCoreSignature);
2589 assert(image->cache != (Cache) NULL);
2590 cache_info=(CacheInfo *) image->cache;
2591 assert(cache_info->signature == MagickCoreSignature);
2592 if (cache_info->methods.get_virtual_metacontent_from_handler != (GetVirtualMetacontentFromHandler) NULL)
2594 metacontent=cache_info->methods.get_virtual_metacontent_from_handler(
2596 if (metacontent != (
const void *) NULL)
2597 return(metacontent);
2599 assert(
id < (
int) cache_info->number_threads);
2600 metacontent=GetVirtualMetacontentFromNexus(cache_info,
2601 cache_info->nexus_info[
id]);
2602 return(metacontent);
2645 0, 48, 12, 60, 3, 51, 15, 63,
2646 32, 16, 44, 28, 35, 19, 47, 31,
2647 8, 56, 4, 52, 11, 59, 7, 55,
2648 40, 24, 36, 20, 43, 27, 39, 23,
2649 2, 50, 14, 62, 1, 49, 13, 61,
2650 34, 18, 46, 30, 33, 17, 45, 29,
2651 10, 58, 6, 54, 9, 57, 5, 53,
2652 42, 26, 38, 22, 41, 25, 37, 21
2655static inline ssize_t DitherX(
const ssize_t x,
const size_t columns)
2660 index=x+DitherMatrix[x & 0x07]-32L;
2663 if (index >= (ssize_t) columns)
2664 return((ssize_t) columns-1L);
2668static inline ssize_t DitherY(
const ssize_t y,
const size_t rows)
2673 index=y+DitherMatrix[y & 0x07]-32L;
2676 if (index >= (ssize_t) rows)
2677 return((ssize_t) rows-1L);
2681static inline ssize_t EdgeX(
const ssize_t x,
const size_t columns)
2685 if (x >= (ssize_t) columns)
2686 return((ssize_t) (columns-1));
2690static inline ssize_t EdgeY(
const ssize_t y,
const size_t rows)
2694 if (y >= (ssize_t) rows)
2695 return((ssize_t) (rows-1));
2699static inline MagickBooleanType IsOffsetOverflow(
const MagickOffsetType x,
2700 const MagickOffsetType y)
2702 if (((y > 0) && (x > ((MagickOffsetType) MAGICK_SSIZE_MAX-y))) ||
2703 ((y < 0) && (x < ((MagickOffsetType) MAGICK_SSIZE_MIN-y))))
2704 return(MagickFalse);
2708static inline ssize_t RandomX(RandomInfo *random_info,
const size_t columns)
2710 return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2713static inline ssize_t RandomY(RandomInfo *random_info,
const size_t rows)
2715 return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2718static inline MagickModulo VirtualPixelModulo(
const ssize_t offset,
2719 const size_t extent)
2724 modulo.quotient=offset;
2728 modulo.quotient=offset/((ssize_t) extent);
2729 modulo.remainder=offset % ((ssize_t) extent);
2731 if ((modulo.remainder != 0) && ((offset ^ ((ssize_t) extent)) < 0))
2734 modulo.remainder+=((ssize_t) extent);
2739MagickPrivate
const Quantum *GetVirtualPixelCacheNexus(
const Image *image,
2740 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
2741 const size_t columns,
const size_t rows,NexusInfo *nexus_info,
2742 ExceptionInfo *exception)
2745 *magick_restrict cache_info;
2761 *magick_restrict virtual_nexus;
2764 *magick_restrict pixels,
2766 virtual_pixel[MaxPixelChannels];
2777 *magick_restrict virtual_metacontent;
2782 assert(image != (
const Image *) NULL);
2783 assert(image->signature == MagickCoreSignature);
2784 assert(image->cache != (Cache) NULL);
2785 cache_info=(CacheInfo *) image->cache;
2786 assert(cache_info->signature == MagickCoreSignature);
2787 if (cache_info->type == UndefinedCache)
2788 return((
const Quantum *) NULL);
2789#if defined(MAGICKCORE_OPENCL_SUPPORT)
2790 CopyOpenCLBuffer(cache_info);
2792 pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2793 ((image->channels & WriteMaskChannel) != 0) ||
2794 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2795 nexus_info,exception);
2796 if (pixels == (Quantum *) NULL)
2797 return((
const Quantum *) NULL);
2798 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
2799 return((
const Quantum *) NULL);
2800 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
2801 if (IsOffsetOverflow(offset,(MagickOffsetType) nexus_info->region.x) == MagickFalse)
2802 return((
const Quantum *) NULL);
2803 offset+=nexus_info->region.x;
2804 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2805 nexus_info->region.width-1L;
2806 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2807 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2808 if ((x >= 0) && ((x+(ssize_t) columns-1) < (ssize_t) cache_info->columns) &&
2809 (y >= 0) && ((y+(ssize_t) rows-1) < (ssize_t) cache_info->rows))
2817 if (nexus_info->authentic_pixel_cache != MagickFalse)
2819 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2820 if (status == MagickFalse)
2821 return((
const Quantum *) NULL);
2822 if (cache_info->metacontent_extent != 0)
2824 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2825 if (status == MagickFalse)
2826 return((
const Quantum *) NULL);
2833 virtual_nexus=nexus_info->virtual_nexus;
2835 s=(
unsigned char *) nexus_info->metacontent;
2836 (void) memset(virtual_pixel,0,cache_info->number_channels*
2837 sizeof(*virtual_pixel));
2838 virtual_metacontent=(
void *) NULL;
2839 switch (virtual_pixel_method)
2841 case BackgroundVirtualPixelMethod:
2842 case BlackVirtualPixelMethod:
2843 case GrayVirtualPixelMethod:
2844 case TransparentVirtualPixelMethod:
2845 case MaskVirtualPixelMethod:
2846 case WhiteVirtualPixelMethod:
2847 case EdgeVirtualPixelMethod:
2848 case CheckerTileVirtualPixelMethod:
2849 case HorizontalTileVirtualPixelMethod:
2850 case VerticalTileVirtualPixelMethod:
2852 if (cache_info->metacontent_extent != 0)
2857 virtual_metacontent=(
void *) AcquireQuantumMemory(1,
2858 cache_info->metacontent_extent);
2859 if (virtual_metacontent == (
void *) NULL)
2861 (void) ThrowMagickException(exception,GetMagickModule(),
2862 CacheError,
"UnableToGetCacheNexus",
"`%s'",image->filename);
2863 return((
const Quantum *) NULL);
2865 (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2867 switch (virtual_pixel_method)
2869 case BlackVirtualPixelMethod:
2871 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2872 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2873 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2876 case GrayVirtualPixelMethod:
2878 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2879 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
2881 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2884 case TransparentVirtualPixelMethod:
2886 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2887 SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2888 SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2891 case MaskVirtualPixelMethod:
2892 case WhiteVirtualPixelMethod:
2894 for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2895 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2896 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2901 SetPixelRed(image,ClampToQuantum(image->background_color.red),
2903 SetPixelGreen(image,ClampToQuantum(image->background_color.green),
2905 SetPixelBlue(image,ClampToQuantum(image->background_color.blue),
2907 SetPixelBlack(image,ClampToQuantum(image->background_color.black),
2909 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha),
2919 for (v=0; v < (ssize_t) rows; v++)
2925 if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2926 (virtual_pixel_method == UndefinedVirtualPixelMethod))
2927 y_offset=EdgeY(y_offset,cache_info->rows);
2928 for (u=0; u < (ssize_t) columns; u+=(ssize_t) length)
2934 length=(MagickSizeType) MagickMin((ssize_t) cache_info->columns-
2935 x_offset,(ssize_t) columns-u);
2936 if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2937 ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2947 length=(MagickSizeType) 1;
2948 switch (virtual_pixel_method)
2950 case EdgeVirtualPixelMethod:
2953 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2954 EdgeX(x_offset,cache_info->columns),
2955 EdgeY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2957 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2960 case RandomVirtualPixelMethod:
2962 if (cache_info->random_info == (RandomInfo *) NULL)
2963 cache_info->random_info=AcquireRandomInfo();
2964 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2965 RandomX(cache_info->random_info,cache_info->columns),
2966 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2967 virtual_nexus,exception);
2968 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2971 case DitherVirtualPixelMethod:
2973 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2974 DitherX(x_offset,cache_info->columns),
2975 DitherY(y_offset,cache_info->rows),1UL,1UL,virtual_nexus,
2977 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2980 case TileVirtualPixelMethod:
2982 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2983 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2984 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2985 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
2987 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
2990 case MirrorVirtualPixelMethod:
2992 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2993 if ((x_modulo.quotient & 0x01) == 1L)
2994 x_modulo.remainder=(ssize_t) cache_info->columns-
2995 x_modulo.remainder-1L;
2996 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2997 if ((y_modulo.quotient & 0x01) == 1L)
2998 y_modulo.remainder=(ssize_t) cache_info->rows-
2999 y_modulo.remainder-1L;
3000 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3001 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3003 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3006 case HorizontalTileEdgeVirtualPixelMethod:
3008 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3009 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3010 x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
3011 virtual_nexus,exception);
3012 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3015 case VerticalTileEdgeVirtualPixelMethod:
3017 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3018 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3019 EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3020 virtual_nexus,exception);
3021 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3024 case BackgroundVirtualPixelMethod:
3025 case BlackVirtualPixelMethod:
3026 case GrayVirtualPixelMethod:
3027 case TransparentVirtualPixelMethod:
3028 case MaskVirtualPixelMethod:
3029 case WhiteVirtualPixelMethod:
3032 r=virtual_metacontent;
3035 case CheckerTileVirtualPixelMethod:
3037 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3038 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3039 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3042 r=virtual_metacontent;
3045 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3046 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3048 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3051 case HorizontalTileVirtualPixelMethod:
3053 if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3056 r=virtual_metacontent;
3059 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3060 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3061 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3062 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3064 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3067 case VerticalTileVirtualPixelMethod:
3069 if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3072 r=virtual_metacontent;
3075 x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3076 y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3077 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3078 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus,
3080 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3084 if (p == (
const Quantum *) NULL)
3086 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3088 q+=(ptrdiff_t) cache_info->number_channels;
3089 if ((s != (
void *) NULL) && (r != (
const void *) NULL))
3091 (void) memcpy(s,r,(
size_t) cache_info->metacontent_extent);
3092 s+=(ptrdiff_t) cache_info->metacontent_extent;
3099 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3100 (
size_t) length,1UL,virtual_nexus,exception);
3101 if (p == (
const Quantum *) NULL)
3103 r=GetVirtualMetacontentFromNexus(cache_info,virtual_nexus);
3104 (void) memcpy(q,p,(
size_t) (cache_info->number_channels*length*
3106 q+=(ptrdiff_t) cache_info->number_channels*length;
3107 if ((r != (
void *) NULL) && (s != (
const void *) NULL))
3109 (void) memcpy(s,r,(
size_t) length);
3110 s+=(ptrdiff_t) length*cache_info->metacontent_extent;
3113 if (u < (ssize_t) columns)
3119 if (virtual_metacontent != (
void *) NULL)
3120 virtual_metacontent=(
void *) RelinquishMagickMemory(virtual_metacontent);
3121 if (v < (ssize_t) rows)
3122 return((
const Quantum *) NULL);
3160static const Quantum *GetVirtualPixelCache(
const Image *image,
3161 const VirtualPixelMethod virtual_pixel_method,
const ssize_t x,
const ssize_t y,
3162 const size_t columns,
const size_t rows,ExceptionInfo *exception)
3165 *magick_restrict cache_info;
3168 id = GetOpenMPThreadId();
3173 assert(image != (
const Image *) NULL);
3174 assert(image->signature == MagickCoreSignature);
3175 assert(image->cache != (Cache) NULL);
3176 cache_info=(CacheInfo *) image->cache;
3177 assert(cache_info->signature == MagickCoreSignature);
3178 assert(
id < (
int) cache_info->number_threads);
3179 p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3180 cache_info->nexus_info[
id],exception);
3207MagickExport
const Quantum *GetVirtualPixelQueue(
const Image *image)
3210 *magick_restrict cache_info;
3213 id = GetOpenMPThreadId();
3215 assert(image != (
const Image *) NULL);
3216 assert(image->signature == MagickCoreSignature);
3217 assert(image->cache != (Cache) NULL);
3218 cache_info=(CacheInfo *) image->cache;
3219 assert(cache_info->signature == MagickCoreSignature);
3220 if (cache_info->methods.get_virtual_pixels_handler !=
3221 (GetVirtualPixelsHandler) NULL)
3222 return(cache_info->methods.get_virtual_pixels_handler(image));
3223 assert(
id < (
int) cache_info->number_threads);
3224 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[
id]));
3275MagickExport
const Quantum *GetVirtualPixels(
const Image *image,
3276 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
3277 ExceptionInfo *exception)
3280 *magick_restrict cache_info;
3283 id = GetOpenMPThreadId();
3288 assert(image != (
const Image *) NULL);
3289 assert(image->signature == MagickCoreSignature);
3290 assert(image->cache != (Cache) NULL);
3291 cache_info=(CacheInfo *) image->cache;
3292 assert(cache_info->signature == MagickCoreSignature);
3293 if (cache_info->methods.get_virtual_pixel_handler !=
3294 (GetVirtualPixelHandler) NULL)
3295 return(cache_info->methods.get_virtual_pixel_handler(image,
3296 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3297 assert(
id < (
int) cache_info->number_threads);
3298 p=GetVirtualPixelCacheNexus(image,GetPixelCacheVirtualMethod(image),x,y,
3299 columns,rows,cache_info->nexus_info[
id],exception);
3326static const Quantum *GetVirtualPixelsCache(
const Image *image)
3329 *magick_restrict cache_info;
3332 id = GetOpenMPThreadId();
3334 assert(image != (
const Image *) NULL);
3335 assert(image->signature == MagickCoreSignature);
3336 assert(image->cache != (Cache) NULL);
3337 cache_info=(CacheInfo *) image->cache;
3338 assert(cache_info->signature == MagickCoreSignature);
3339 assert(
id < (
int) cache_info->number_threads);
3340 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[
id]));
3369MagickPrivate
const Quantum *GetVirtualPixelsNexus(
const Cache cache,
3370 NexusInfo *magick_restrict nexus_info)
3373 *magick_restrict cache_info;
3375 assert(cache != (Cache) NULL);
3376 cache_info=(CacheInfo *) cache;
3377 assert(cache_info->signature == MagickCoreSignature);
3378 if (cache_info->storage_class == UndefinedClass)
3379 return((Quantum *) NULL);
3380 return((
const Quantum *) nexus_info->pixels);
3413static inline Quantum ApplyPixelCompositeMask(
const Quantum p,
3414 const MagickRealType alpha,
const Quantum q,
const MagickRealType beta)
3419 if (fabs((
double) (alpha-(
double) TransparentAlpha)) < MagickEpsilon)
3421 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
3422 gamma=MagickSafeReciprocal(gamma);
3423 return(ClampToQuantum(gamma*MagickOver_((
double) p,alpha,(
double) q,beta)));
3426static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
3427 ExceptionInfo *exception)
3430 *magick_restrict cache_info;
3442 if (IsEventLogging() != MagickFalse)
3443 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3444 if ((image->channels & CompositeMaskChannel) == 0)
3446 if ((nexus_info->region.width == 0) || (nexus_info->region.height == 0))
3448 cache_info=(CacheInfo *) image->cache;
3449 if (cache_info == (Cache) NULL)
3450 return(MagickFalse);
3451 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3452 nexus_info->region.width,nexus_info->region.height,
3453 nexus_info->virtual_nexus,exception);
3454 q=nexus_info->pixels;
3455 if ((p == (Quantum *) NULL) || (q == (Quantum *) NULL))
3456 return(MagickFalse);
3457 for (y=0; y < (ssize_t) nexus_info->region.height; y++)
3462 for (x=0; x < (ssize_t) nexus_info->region.width; x++)
3470 alpha=(double) GetPixelCompositeMask(image,p);
3471 for (i=0; i < (ssize_t) image->number_channels; i++)
3473 PixelChannel channel = GetPixelChannelChannel(image,i);
3474 PixelTrait traits = GetPixelChannelTraits(image,channel);
3475 if ((traits & UpdatePixelTrait) == 0)
3477 q[i]=ApplyPixelCompositeMask(q[i],alpha,p[i],GetPixelAlpha(image,p));
3479 p+=(ptrdiff_t) GetPixelChannels(image);
3480 q+=(ptrdiff_t) GetPixelChannels(image);
3517static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
3526 if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3528 if (*cache_info->cache_filename ==
'\0')
3529 file=AcquireUniqueFileResource(cache_info->cache_filename);
3535 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3540 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3541 O_BINARY | O_EXCL,S_MODE);
3543 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3549 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3552 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3557 return(MagickFalse);
3558 (void) AcquireMagickResource(FileResource,1);
3559 if (cache_info->file != -1)
3560 (void) ClosePixelCacheOnDisk(cache_info);
3561 cache_info->file=file;
3562 cache_info->disk_mode=mode;
3566static inline MagickOffsetType WritePixelCacheRegion(
3567 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
3568 const MagickSizeType length,
const unsigned char *magick_restrict buffer)
3576#if !defined(MAGICKCORE_HAVE_PWRITE)
3577 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3578 return((MagickOffsetType) -1);
3580 for (i=0; i < (MagickOffsetType) length; i+=count)
3582#if !defined(MAGICKCORE_HAVE_PWRITE)
3583 count=write(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3584 (MagickSizeType) i,MagickMaxBufferExtent));
3586 count=pwrite(cache_info->file,buffer+i,(
size_t) MagickMin(length-
3587 (MagickSizeType) i,MagickMaxBufferExtent),offset+i);
3599static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
3602 *magick_restrict cache_info;
3607 cache_info=(CacheInfo *) image->cache;
3608 if (cache_info->debug != MagickFalse)
3611 format[MagickPathExtent],
3612 message[MagickPathExtent];
3614 (void) FormatMagickSize(length,MagickFalse,
"B",MagickPathExtent,format);
3615 (void) FormatLocaleString(message,MagickPathExtent,
3616 "extend %s (%s[%d], disk, %s)",cache_info->filename,
3617 cache_info->cache_filename,cache_info->file,format);
3618 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
3620 if (length != (MagickSizeType) ((MagickOffsetType) length))
3621 return(MagickFalse);
3622 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3624 return(MagickFalse);
3625 if ((MagickSizeType) offset < length)
3631 extent=(MagickOffsetType) length-1;
3632 count=WritePixelCacheRegion(cache_info,extent,1,(
const unsigned char *)
3635 return(MagickFalse);
3636#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3637 if (cache_info->synchronize != MagickFalse)
3638 if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3639 return(MagickFalse);
3642 offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3644 return(MagickFalse);
3648static MagickBooleanType OpenPixelCache(Image *image,
const MapMode mode,
3649 ExceptionInfo *exception)
3652 *magick_restrict cache_info,
3656 format[MagickPathExtent],
3657 message[MagickPathExtent];
3674 assert(image != (
const Image *) NULL);
3675 assert(image->signature == MagickCoreSignature);
3676 assert(image->cache != (Cache) NULL);
3677 if (IsEventLogging() != MagickFalse)
3678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3679 if (cache_anonymous_memory < 0)
3687 cache_anonymous_memory=0;
3688 value=GetPolicyValue(
"pixel-cache-memory");
3689 if (value == (
char *) NULL)
3690 value=GetPolicyValue(
"cache:memory-map");
3691 if (LocaleCompare(value,
"anonymous") == 0)
3693#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3694 cache_anonymous_memory=1;
3696 (void) ThrowMagickException(exception,GetMagickModule(),
3697 MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn",
3698 "`%s' (policy requires anonymous memory mapping)",image->filename);
3701 value=DestroyString(value);
3703 if ((image->columns == 0) || (image->rows == 0))
3704 ThrowBinaryException(CacheError,
"NoPixelsDefinedInCache",image->filename);
3705 cache_info=(CacheInfo *) image->cache;
3706 assert(cache_info->signature == MagickCoreSignature);
3707 if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3708 ((MagickSizeType) image->rows > cache_info->height_limit))
3710 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
3711 "WidthOrHeightExceedsLimit",
"`%s' (%.20gx%.20g) > (%.20gx%.20g)",
3712 image->filename, (
double) image->columns, (
double) image->rows,
3713 (
double) cache_info->width_limit,(
double) cache_info->height_limit);
3714 return(MagickFalse);
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 length=number_pixels*packet_size;
3746 columns=(size_t) (length/cache_info->rows/packet_size);
3747 if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3748 ((ssize_t) cache_info->rows < 0))
3749 ThrowBinaryException(ResourceLimitError,
"PixelCacheAllocationFailed",
3751 cache_info->length=length;
3752 if (image->ping != MagickFalse)
3754 cache_info->type=PingCache;
3757 status=AcquireMagickResource(AreaResource,(MagickSizeType)
3758 cache_info->columns*cache_info->rows);
3759 if (cache_info->mode == PersistMode)
3761 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3762 cache_info->metacontent_extent);
3763 if ((status != MagickFalse) &&
3764 (length == (MagickSizeType) ((
size_t) length)) &&
3765 ((cache_info->type == UndefinedCache) ||
3766 (cache_info->type == MemoryCache)))
3768 status=AcquireMagickResource(MemoryResource,cache_info->length);
3769 if (status != MagickFalse)
3772 if (cache_anonymous_memory <= 0)
3774 cache_info->mapped=MagickFalse;
3775 cache_info->pixels=(Quantum *) MagickAssumeAligned(
3776 AcquireAlignedMemory(1,(
size_t) cache_info->length));
3780 cache_info->mapped=MagickTrue;
3781 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(
size_t)
3782 cache_info->length);
3784 if (cache_info->pixels == (Quantum *) NULL)
3786 cache_info->mapped=source_info.mapped;
3787 cache_info->pixels=source_info.pixels;
3794 cache_info->type=MemoryCache;
3795 cache_info->metacontent=(
void *) NULL;
3796 if (cache_info->metacontent_extent != 0)
3797 cache_info->metacontent=(
void *) (cache_info->pixels+
3798 cache_info->number_channels*number_pixels);
3799 if ((source_info.storage_class != UndefinedClass) &&
3802 status=ClonePixelCacheRepository(cache_info,&source_info,
3804 RelinquishPixelCachePixels(&source_info);
3806 if (cache_info->debug != MagickFalse)
3808 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3809 MagickPathExtent,format);
3810 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3812 (void) FormatLocaleString(message,MagickPathExtent,
3813 "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3814 cache_info->filename,cache_info->mapped != MagickFalse ?
3815 "Anonymous" :
"Heap",type,(
double) cache_info->columns,
3816 (
double) cache_info->rows,(
double)
3817 cache_info->number_channels,format);
3818 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3821 cache_info->storage_class=image->storage_class;
3824 if ((source_info.storage_class != UndefinedClass) &&
3826 RelinquishPixelCachePixels(&source_info);
3827 cache_info->type=UndefinedCache;
3828 return(MagickFalse);
3834 status=AcquireMagickResource(DiskResource,cache_info->length);
3835 hosts=(
const char *) GetImageRegistry(StringRegistryType,
"cache:hosts",
3837 if ((status == MagickFalse) && (hosts != (
const char *) NULL))
3845 server_info=AcquireDistributeCacheInfo(exception);
3846 if (server_info != (DistributeCacheInfo *) NULL)
3848 status=OpenDistributePixelCache(server_info,image);
3849 if (status == MagickFalse)
3851 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3852 GetDistributeCacheHostname(server_info));
3853 server_info=DestroyDistributeCacheInfo(server_info);
3861 cache_info->type=DistributedCache;
3862 cache_info->server_info=server_info;
3863 (void) FormatLocaleString(cache_info->cache_filename,
3864 MagickPathExtent,
"%s:%d",GetDistributeCacheHostname(
3865 (DistributeCacheInfo *) cache_info->server_info),
3866 GetDistributeCachePort((DistributeCacheInfo *)
3867 cache_info->server_info));
3868 if ((source_info.storage_class != UndefinedClass) &&
3871 status=ClonePixelCacheRepository(cache_info,&source_info,
3873 RelinquishPixelCachePixels(&source_info);
3875 if (cache_info->debug != MagickFalse)
3877 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
3878 MagickPathExtent,format);
3879 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3881 (void) FormatLocaleString(message,MagickPathExtent,
3882 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3883 cache_info->filename,cache_info->cache_filename,
3884 GetDistributeCacheFile((DistributeCacheInfo *)
3885 cache_info->server_info),type,(
double) cache_info->columns,
3886 (
double) cache_info->rows,(
double)
3887 cache_info->number_channels,format);
3888 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3893 if ((source_info.storage_class != UndefinedClass) &&
3895 RelinquishPixelCachePixels(&source_info);
3896 cache_info->type=UndefinedCache;
3897 return(MagickFalse);
3902 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3903 RelinquishPixelCachePixels(&source_info);
3904 cache_info->type=UndefinedCache;
3905 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3906 "CacheResourcesExhausted",
"`%s'",image->filename);
3907 return(MagickFalse);
3912 if (status == MagickFalse)
3914 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3915 RelinquishPixelCachePixels(&source_info);
3916 cache_info->type=UndefinedCache;
3917 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3918 "CacheResourcesExhausted",
"`%s'",image->filename);
3919 return(MagickFalse);
3921 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3922 (cache_info->mode != PersistMode))
3924 (void) ClosePixelCacheOnDisk(cache_info);
3925 *cache_info->cache_filename=
'\0';
3927 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3929 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3930 RelinquishPixelCachePixels(&source_info);
3931 cache_info->type=UndefinedCache;
3932 ThrowFileException(exception,CacheError,
"UnableToOpenPixelCache",
3934 return(MagickFalse);
3936 status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3937 cache_info->length);
3938 if (status == MagickFalse)
3940 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3941 RelinquishPixelCachePixels(&source_info);
3942 cache_info->type=UndefinedCache;
3943 ThrowFileException(exception,CacheError,
"UnableToExtendCache",
3945 return(MagickFalse);
3947 cache_info->type=DiskCache;
3948 length=number_pixels*(cache_info->number_channels*
sizeof(Quantum)+
3949 cache_info->metacontent_extent);
3950 if (length == (MagickSizeType) ((
size_t) length))
3952 status=AcquireMagickResource(MapResource,cache_info->length);
3953 if (status != MagickFalse)
3955 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3956 cache_info->offset,(
size_t) cache_info->length);
3957 if (cache_info->pixels == (Quantum *) NULL)
3959 cache_info->mapped=source_info.mapped;
3960 cache_info->pixels=source_info.pixels;
3961 RelinquishMagickResource(MapResource,cache_info->length);
3968 (void) ClosePixelCacheOnDisk(cache_info);
3969 cache_info->type=MapCache;
3970 cache_info->mapped=MagickTrue;
3971 cache_info->metacontent=(
void *) NULL;
3972 if (cache_info->metacontent_extent != 0)
3973 cache_info->metacontent=(
void *) (cache_info->pixels+
3974 cache_info->number_channels*number_pixels);
3975 if ((source_info.storage_class != UndefinedClass) &&
3978 status=ClonePixelCacheRepository(cache_info,&source_info,
3980 RelinquishPixelCachePixels(&source_info);
3982 if (cache_info->debug != MagickFalse)
3984 (void) FormatMagickSize(cache_info->length,MagickTrue,
"B",
3985 MagickPathExtent,format);
3986 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
3988 (void) FormatLocaleString(message,MagickPathExtent,
3989 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3990 cache_info->filename,cache_info->cache_filename,
3991 cache_info->file,type,(
double) cache_info->columns,
3992 (
double) cache_info->rows,(
double)
3993 cache_info->number_channels,format);
3994 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",
3999 if ((source_info.storage_class != UndefinedClass) &&
4001 RelinquishPixelCachePixels(&source_info);
4002 cache_info->type=UndefinedCache;
4003 return(MagickFalse);
4010 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
4012 status=ClonePixelCacheRepository(cache_info,&source_info,exception);
4013 RelinquishPixelCachePixels(&source_info);
4015 if (cache_info->debug != MagickFalse)
4017 (void) FormatMagickSize(cache_info->length,MagickFalse,
"B",
4018 MagickPathExtent,format);
4019 type=CommandOptionToMnemonic(MagickCacheOptions,(ssize_t)
4021 (void) FormatLocaleString(message,MagickPathExtent,
4022 "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
4023 cache_info->cache_filename,cache_info->file,type,(
double)
4024 cache_info->columns,(
double) cache_info->rows,(
double)
4025 cache_info->number_channels,format);
4026 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
"%s",message);
4030 cache_info->type=UndefinedCache;
4031 return(MagickFalse);
4073MagickExport MagickBooleanType PersistPixelCache(Image *image,
4074 const char *filename,
const MagickBooleanType attach,MagickOffsetType *offset,
4075 ExceptionInfo *exception)
4078 *magick_restrict cache_info,
4079 *magick_restrict clone_info;
4087 assert(image != (Image *) NULL);
4088 assert(image->signature == MagickCoreSignature);
4089 if (IsEventLogging() != MagickFalse)
4090 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4091 assert(image->cache != (
void *) NULL);
4092 assert(filename != (
const char *) NULL);
4093 assert(offset != (MagickOffsetType *) NULL);
4094 page_size=GetMagickPageSize();
4095 cache_info=(CacheInfo *) image->cache;
4096 assert(cache_info->signature == MagickCoreSignature);
4097#if defined(MAGICKCORE_OPENCL_SUPPORT)
4098 CopyOpenCLBuffer(cache_info);
4100 if (attach != MagickFalse)
4105 if (cache_info->debug != MagickFalse)
4106 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4107 "attach persistent cache");
4108 (void) CopyMagickString(cache_info->cache_filename,filename,
4110 cache_info->type=MapCache;
4111 cache_info->offset=(*offset);
4112 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4113 return(MagickFalse);
4114 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4115 ((MagickOffsetType) cache_info->length % page_size));
4121 status=AcquireMagickResource(DiskResource,cache_info->length);
4122 if (status == MagickFalse)
4124 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4125 "CacheResourcesExhausted",
"`%s'",image->filename);
4126 return(MagickFalse);
4128 clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4129 clone_info->type=DiskCache;
4130 (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4131 clone_info->file=(-1);
4132 clone_info->storage_class=cache_info->storage_class;
4133 clone_info->colorspace=cache_info->colorspace;
4134 clone_info->alpha_trait=cache_info->alpha_trait;
4135 clone_info->channels=cache_info->channels;
4136 clone_info->columns=cache_info->columns;
4137 clone_info->rows=cache_info->rows;
4138 clone_info->number_channels=cache_info->number_channels;
4139 clone_info->metacontent_extent=cache_info->metacontent_extent;
4140 clone_info->mode=PersistMode;
4141 clone_info->length=cache_info->length;
4142 (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4143 MaxPixelChannels*
sizeof(*cache_info->channel_map));
4144 clone_info->offset=(*offset);
4145 status=OpenPixelCacheOnDisk(clone_info,WriteMode);
4146 if (status != MagickFalse)
4147 status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4148 *offset=(*offset+(MagickOffsetType) cache_info->length+page_size-
4149 ((MagickOffsetType) cache_info->length % page_size));
4150 clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4192MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
4193 const ssize_t x,
const ssize_t y,
const size_t columns,
const size_t rows,
4194 const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4197 *magick_restrict cache_info;
4206 *magick_restrict pixels;
4211 assert(image != (
const Image *) NULL);
4212 assert(image->signature == MagickCoreSignature);
4213 assert(image->cache != (Cache) NULL);
4214 cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4215 if (cache_info == (Cache) NULL)
4216 return((Quantum *) NULL);
4217 assert(cache_info->signature == MagickCoreSignature);
4218 if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4219 (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4220 (y >= (ssize_t) cache_info->rows))
4222 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4223 "PixelsAreNotAuthentic",
"`%s'",image->filename);
4224 return((Quantum *) NULL);
4226 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
4227 return((Quantum *) NULL);
4228 offset=y*(MagickOffsetType) cache_info->columns+x;
4230 return((Quantum *) NULL);
4231 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4232 offset+=((MagickOffsetType) rows-1)*(MagickOffsetType) cache_info->columns+
4233 (MagickOffsetType) columns-1;
4234 if ((MagickSizeType) offset >= number_pixels)
4235 return((Quantum *) NULL);
4239 pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4240 ((image->channels & WriteMaskChannel) != 0) ||
4241 ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4242 nexus_info,exception);
4279static Quantum *QueueAuthenticPixelsCache(Image *image,
const ssize_t x,
4280 const ssize_t y,
const size_t columns,
const size_t rows,
4281 ExceptionInfo *exception)
4284 *magick_restrict cache_info;
4287 id = GetOpenMPThreadId();
4290 *magick_restrict pixels;
4292 assert(image != (
const Image *) NULL);
4293 assert(image->signature == MagickCoreSignature);
4294 assert(image->cache != (Cache) NULL);
4295 cache_info=(CacheInfo *) image->cache;
4296 assert(cache_info->signature == MagickCoreSignature);
4297 assert(
id < (
int) cache_info->number_threads);
4298 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4299 cache_info->nexus_info[
id],exception);
4359MagickExport Quantum *QueueAuthenticPixels(Image *image,
const ssize_t x,
4360 const ssize_t y,
const size_t columns,
const size_t rows,
4361 ExceptionInfo *exception)
4364 *magick_restrict cache_info;
4367 id = GetOpenMPThreadId();
4370 *magick_restrict pixels;
4372 assert(image != (Image *) NULL);
4373 assert(image->signature == MagickCoreSignature);
4374 assert(image->cache != (Cache) NULL);
4375 cache_info=(CacheInfo *) image->cache;
4376 assert(cache_info->signature == MagickCoreSignature);
4377 if (cache_info->methods.queue_authentic_pixels_handler !=
4378 (QueueAuthenticPixelsHandler) NULL)
4380 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4381 columns,rows,exception);
4384 assert(
id < (
int) cache_info->number_threads);
4385 pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4386 cache_info->nexus_info[
id],exception);
4419static inline MagickOffsetType ReadPixelCacheRegion(
4420 const CacheInfo *magick_restrict cache_info,
const MagickOffsetType offset,
4421 const MagickSizeType length,
unsigned char *magick_restrict buffer)
4429#if !defined(MAGICKCORE_HAVE_PREAD)
4430 if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4431 return((MagickOffsetType) -1);
4433 for (i=0; i < (MagickOffsetType) length; i+=count)
4435#if !defined(MAGICKCORE_HAVE_PREAD)
4436 count=read(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4437 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent));
4439 count=pread(cache_info->file,buffer+i,(
size_t) MagickMin(length-
4440 (MagickSizeType) i,(
size_t) MagickMaxBufferExtent),offset+i);
4452static MagickBooleanType ReadPixelCacheMetacontent(
4453 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4454 ExceptionInfo *exception)
4473 if (cache_info->metacontent_extent == 0)
4474 return(MagickFalse);
4475 if (nexus_info->authentic_pixel_cache != MagickFalse)
4477 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4478 return(MagickFalse);
4479 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
4480 nexus_info->region.x;
4481 length=(MagickSizeType) nexus_info->region.width*
4482 cache_info->metacontent_extent;
4483 extent=length*nexus_info->region.height;
4484 rows=nexus_info->region.height;
4486 q=(
unsigned char *) nexus_info->metacontent;
4487 switch (cache_info->type)
4498 if ((cache_info->columns == nexus_info->region.width) &&
4499 (extent == (MagickSizeType) ((
size_t) extent)))
4504 p=(
unsigned char *) cache_info->metacontent+offset*(MagickOffsetType)
4505 cache_info->metacontent_extent;
4506 for (y=0; y < (ssize_t) rows; y++)
4508 (void) memcpy(q,p,(
size_t) length);
4509 p+=(ptrdiff_t) cache_info->metacontent_extent*cache_info->columns;
4510 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4519 LockSemaphoreInfo(cache_info->file_semaphore);
4520 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4522 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4523 cache_info->cache_filename);
4524 UnlockSemaphoreInfo(cache_info->file_semaphore);
4525 return(MagickFalse);
4527 if ((cache_info->columns == nexus_info->region.width) &&
4528 (extent <= MagickMaxBufferExtent))
4533 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4534 for (y=0; y < (ssize_t) rows; y++)
4536 count=ReadPixelCacheRegion(cache_info,cache_info->offset+
4537 (MagickOffsetType) extent*(MagickOffsetType)
4538 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
4539 (MagickOffsetType) cache_info->metacontent_extent,length,
4540 (
unsigned char *) q);
4541 if (count != (MagickOffsetType) length)
4543 offset+=(MagickOffsetType) cache_info->columns;
4544 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4546 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4547 (void) ClosePixelCacheOnDisk(cache_info);
4548 UnlockSemaphoreInfo(cache_info->file_semaphore);
4551 case DistributedCache:
4559 LockSemaphoreInfo(cache_info->file_semaphore);
4560 region=nexus_info->region;
4561 if ((cache_info->columns != nexus_info->region.width) ||
4562 (extent > MagickMaxBufferExtent))
4569 for (y=0; y < (ssize_t) rows; y++)
4571 count=ReadDistributePixelCacheMetacontent((DistributeCacheInfo *)
4572 cache_info->server_info,®ion,length,(
unsigned char *) q);
4573 if (count != (MagickOffsetType) length)
4575 q+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
4578 UnlockSemaphoreInfo(cache_info->file_semaphore);
4584 if (y < (ssize_t) rows)
4586 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4587 cache_info->cache_filename);
4588 return(MagickFalse);
4590 if ((cache_info->debug != MagickFalse) &&
4591 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4592 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4593 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4594 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4595 nexus_info->region.x,(
double) nexus_info->region.y);
4627static MagickBooleanType ReadPixelCachePixels(
4628 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4629 ExceptionInfo *exception)
4649 if (nexus_info->authentic_pixel_cache != MagickFalse)
4651 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
4652 return(MagickFalse);
4653 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns;
4654 if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4655 return(MagickFalse);
4656 offset+=nexus_info->region.x;
4657 number_channels=cache_info->number_channels;
4658 length=(MagickSizeType) number_channels*nexus_info->region.width*
4660 if ((length/number_channels/
sizeof(Quantum)) != nexus_info->region.width)
4661 return(MagickFalse);
4662 rows=nexus_info->region.height;
4664 if ((extent == 0) || ((extent/length) != rows))
4665 return(MagickFalse);
4667 q=nexus_info->pixels;
4668 switch (cache_info->type)
4679 if ((cache_info->columns == nexus_info->region.width) &&
4680 (extent == (MagickSizeType) ((
size_t) extent)))
4685 p=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
4687 for (y=0; y < (ssize_t) rows; y++)
4689 (void) memcpy(q,p,(
size_t) length);
4690 p+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
4691 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4700 LockSemaphoreInfo(cache_info->file_semaphore);
4701 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4703 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
4704 cache_info->cache_filename);
4705 UnlockSemaphoreInfo(cache_info->file_semaphore);
4706 return(MagickFalse);
4708 if ((cache_info->columns == nexus_info->region.width) &&
4709 (extent <= MagickMaxBufferExtent))
4714 for (y=0; y < (ssize_t) rows; y++)
4716 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4717 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
4718 sizeof(*q),length,(
unsigned char *) q);
4719 if (count != (MagickOffsetType) length)
4721 offset+=(MagickOffsetType) cache_info->columns;
4722 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4724 if (IsFileDescriptorLimitExceeded() != MagickFalse)
4725 (void) ClosePixelCacheOnDisk(cache_info);
4726 UnlockSemaphoreInfo(cache_info->file_semaphore);
4729 case DistributedCache:
4737 LockSemaphoreInfo(cache_info->file_semaphore);
4738 region=nexus_info->region;
4739 if ((cache_info->columns != nexus_info->region.width) ||
4740 (extent > MagickMaxBufferExtent))
4747 for (y=0; y < (ssize_t) rows; y++)
4749 count=ReadDistributePixelCachePixels((DistributeCacheInfo *)
4750 cache_info->server_info,®ion,length,(
unsigned char *) q);
4751 if (count != (MagickOffsetType) length)
4753 q+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
4756 UnlockSemaphoreInfo(cache_info->file_semaphore);
4762 if (y < (ssize_t) rows)
4764 ThrowFileException(exception,CacheError,
"UnableToReadPixelCache",
4765 cache_info->cache_filename);
4766 return(MagickFalse);
4768 if ((cache_info->debug != MagickFalse) &&
4769 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4770 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
4771 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
4772 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
4773 nexus_info->region.x,(
double) nexus_info->region.y);
4800MagickPrivate Cache ReferencePixelCache(Cache cache)
4803 *magick_restrict cache_info;
4805 assert(cache != (Cache *) NULL);
4806 cache_info=(CacheInfo *) cache;
4807 assert(cache_info->signature == MagickCoreSignature);
4808 LockSemaphoreInfo(cache_info->semaphore);
4809 cache_info->reference_count++;
4810 UnlockSemaphoreInfo(cache_info->semaphore);
4836MagickPrivate
void ResetPixelCacheChannels(Image *image)
4839 *magick_restrict cache_info;
4841 assert(image != (
const Image *) NULL);
4842 assert(image->signature == MagickCoreSignature);
4843 assert(image->cache != (Cache) NULL);
4844 cache_info=(CacheInfo *) image->cache;
4845 assert(cache_info->signature == MagickCoreSignature);
4846 cache_info->number_channels=GetPixelChannels(image);
4867MagickPrivate
void ResetCacheAnonymousMemory(
void)
4869 cache_anonymous_memory=0;
4901MagickExport MagickBooleanType ReshapePixelCache(Image *image,
4902 const size_t columns,
const size_t rows,ExceptionInfo *exception)
4910 assert(image != (Image *) NULL);
4911 assert(image->signature == MagickCoreSignature);
4912 if (IsEventLogging() != MagickFalse)
4913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4914 assert(image->cache != (
void *) NULL);
4915 extent=(MagickSizeType) columns*rows;
4916 if (extent > ((MagickSizeType) image->columns*image->rows))
4917 ThrowBinaryException(ImageError,
"WidthOrHeightExceedsLimit",
4919 image->columns=columns;
4921 cache_info=(CacheInfo *) image->cache;
4922 cache_info->columns=columns;
4923 cache_info->rows=rows;
4924 return(SyncImagePixelCache(image,exception));
4951MagickPrivate
void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
4954 *magick_restrict cache_info;
4956 GetOneAuthenticPixelFromHandler
4957 get_one_authentic_pixel_from_handler;
4959 GetOneVirtualPixelFromHandler
4960 get_one_virtual_pixel_from_handler;
4965 assert(cache != (Cache) NULL);
4966 assert(cache_methods != (CacheMethods *) NULL);
4967 cache_info=(CacheInfo *) cache;
4968 assert(cache_info->signature == MagickCoreSignature);
4969 if (IsEventLogging() != MagickFalse)
4970 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",
4971 cache_info->filename);
4972 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4973 cache_info->methods.get_virtual_pixel_handler=
4974 cache_methods->get_virtual_pixel_handler;
4975 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4976 cache_info->methods.destroy_pixel_handler=
4977 cache_methods->destroy_pixel_handler;
4978 if (cache_methods->get_virtual_metacontent_from_handler !=
4979 (GetVirtualMetacontentFromHandler) NULL)
4980 cache_info->methods.get_virtual_metacontent_from_handler=
4981 cache_methods->get_virtual_metacontent_from_handler;
4982 if (cache_methods->get_authentic_pixels_handler !=
4983 (GetAuthenticPixelsHandler) NULL)
4984 cache_info->methods.get_authentic_pixels_handler=
4985 cache_methods->get_authentic_pixels_handler;
4986 if (cache_methods->queue_authentic_pixels_handler !=
4987 (QueueAuthenticPixelsHandler) NULL)
4988 cache_info->methods.queue_authentic_pixels_handler=
4989 cache_methods->queue_authentic_pixels_handler;
4990 if (cache_methods->sync_authentic_pixels_handler !=
4991 (SyncAuthenticPixelsHandler) NULL)
4992 cache_info->methods.sync_authentic_pixels_handler=
4993 cache_methods->sync_authentic_pixels_handler;
4994 if (cache_methods->get_authentic_pixels_from_handler !=
4995 (GetAuthenticPixelsFromHandler) NULL)
4996 cache_info->methods.get_authentic_pixels_from_handler=
4997 cache_methods->get_authentic_pixels_from_handler;
4998 if (cache_methods->get_authentic_metacontent_from_handler !=
4999 (GetAuthenticMetacontentFromHandler) NULL)
5000 cache_info->methods.get_authentic_metacontent_from_handler=
5001 cache_methods->get_authentic_metacontent_from_handler;
5002 get_one_virtual_pixel_from_handler=
5003 cache_info->methods.get_one_virtual_pixel_from_handler;
5004 if (get_one_virtual_pixel_from_handler !=
5005 (GetOneVirtualPixelFromHandler) NULL)
5006 cache_info->methods.get_one_virtual_pixel_from_handler=
5007 cache_methods->get_one_virtual_pixel_from_handler;
5008 get_one_authentic_pixel_from_handler=
5009 cache_methods->get_one_authentic_pixel_from_handler;
5010 if (get_one_authentic_pixel_from_handler !=
5011 (GetOneAuthenticPixelFromHandler) NULL)
5012 cache_info->methods.get_one_authentic_pixel_from_handler=
5013 cache_methods->get_one_authentic_pixel_from_handler;
5054static inline MagickBooleanType AcquireCacheNexusPixels(
5055 const CacheInfo *magick_restrict cache_info,
const MagickSizeType length,
5056 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5058 if (length != (MagickSizeType) ((
size_t) length))
5060 (void) ThrowMagickException(exception,GetMagickModule(),
5061 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5062 cache_info->filename);
5063 return(MagickFalse);
5065 nexus_info->length=0;
5066 nexus_info->mapped=MagickFalse;
5067 if (cache_anonymous_memory <= 0)
5069 nexus_info->cache=(Quantum *) MagickAssumeAligned(AcquireAlignedMemory(1,
5071 if (nexus_info->cache != (Quantum *) NULL)
5072 (void) memset(nexus_info->cache,0,(
size_t) length);
5076 nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(
size_t) length);
5077 if (nexus_info->cache != (Quantum *) NULL)
5078 nexus_info->mapped=MagickTrue;
5080 if (nexus_info->cache == (Quantum *) NULL)
5082 (void) ThrowMagickException(exception,GetMagickModule(),
5083 ResourceLimitError,
"PixelCacheAllocationFailed",
"`%s'",
5084 cache_info->filename);
5085 return(MagickFalse);
5087 nexus_info->length=length;
5091static inline void PrefetchPixelCacheNexusPixels(
const NexusInfo *nexus_info,
5094 if (nexus_info->length < CACHE_LINE_SIZE)
5096 if (mode == ReadMode)
5098 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
5102 MagickCachePrefetch((
unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
5105static Quantum *SetPixelCacheNexusPixels(
5106 const CacheInfo *magick_restrict cache_info,
const MapMode mode,
5107 const ssize_t x,
const ssize_t y,
const size_t width,
const size_t height,
5108 const MagickBooleanType buffered,NexusInfo *magick_restrict nexus_info,
5109 ExceptionInfo *exception)
5118 assert(cache_info != (
const CacheInfo *) NULL);
5119 assert(cache_info->signature == MagickCoreSignature);
5120 if (cache_info->type == UndefinedCache)
5121 return((Quantum *) NULL);
5122 assert(nexus_info->signature == MagickCoreSignature);
5123 (void) memset(&nexus_info->region,0,
sizeof(nexus_info->region));
5124 if ((width == 0) || (height == 0))
5126 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5127 "NoPixelsDefinedInCache",
"`%s'",cache_info->filename);
5128 return((Quantum *) NULL);
5130 if (((MagickSizeType) width > cache_info->width_limit) ||
5131 ((MagickSizeType) height > cache_info->height_limit))
5133 (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5134 "WidthOrHeightExceedsLimit",
"`%s'",cache_info->filename);
5135 return((Quantum *) NULL);
5137 if ((IsValidPixelOffset(x,width) == MagickFalse) ||
5138 (IsValidPixelOffset(y,height) == MagickFalse))
5140 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
5141 "InvalidPixel",
"`%s'",cache_info->filename);
5142 return((Quantum *) NULL);
5144 if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5145 (buffered == MagickFalse))
5147 if (((x >= 0) && (y >= 0) &&
5148 (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5149 (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5150 (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5158 if (IsValidPixelOffset(y,cache_info->columns) == MagickFalse)
5159 return((Quantum *) NULL);
5160 offset=y*(MagickOffsetType) cache_info->columns+x;
5161 nexus_info->pixels=cache_info->pixels+(MagickOffsetType)
5162 cache_info->number_channels*offset;
5163 nexus_info->metacontent=(
void *) NULL;
5164 if (cache_info->metacontent_extent != 0)
5165 nexus_info->metacontent=(
unsigned char *) cache_info->metacontent+
5166 offset*(MagickOffsetType) cache_info->metacontent_extent;
5167 nexus_info->region.width=width;
5168 nexus_info->region.height=height;
5169 nexus_info->region.x=x;
5170 nexus_info->region.y=y;
5171 nexus_info->authentic_pixel_cache=MagickTrue;
5172 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5173 return(nexus_info->pixels);
5179 number_pixels=(MagickSizeType) width*height;
5180 length=MagickMax(number_pixels,MagickMax(cache_info->columns,
5181 cache_info->rows))*cache_info->number_channels*
sizeof(*nexus_info->pixels);
5182 if (cache_info->metacontent_extent != 0)
5183 length+=number_pixels*cache_info->metacontent_extent;
5185 if (nexus_info->cache == (Quantum *) NULL)
5186 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5188 if (nexus_info->length < length)
5190 RelinquishCacheNexusPixels(nexus_info);
5191 status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5193 if (status == MagickFalse)
5194 return((Quantum *) NULL);
5195 nexus_info->pixels=nexus_info->cache;
5196 nexus_info->metacontent=(
void *) NULL;
5197 if (cache_info->metacontent_extent != 0)
5198 nexus_info->metacontent=(
void *) (nexus_info->pixels+
5199 cache_info->number_channels*number_pixels);
5200 nexus_info->region.width=width;
5201 nexus_info->region.height=height;
5202 nexus_info->region.x=x;
5203 nexus_info->region.y=y;
5204 nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5205 MagickTrue : MagickFalse;
5206 PrefetchPixelCacheNexusPixels(nexus_info,mode);
5207 return(nexus_info->pixels);
5240static MagickBooleanType SetCacheAlphaChannel(Image *image,
const Quantum alpha,
5241 ExceptionInfo *exception)
5244 *magick_restrict image_view;
5252 assert(image != (Image *) NULL);
5253 assert(image->signature == MagickCoreSignature);
5254 if (IsEventLogging() != MagickFalse)
5255 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5256 assert(image->cache != (Cache) NULL);
5257 image->alpha_trait=BlendPixelTrait;
5259 image_view=AcquireVirtualCacheView(image,exception);
5260#if defined(MAGICKCORE_OPENMP_SUPPORT)
5261 #pragma omp parallel for schedule(static) shared(status) \
5262 magick_number_threads(image,image,image->rows,2)
5264 for (y=0; y < (ssize_t) image->rows; y++)
5272 if (status == MagickFalse)
5274 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5275 if (q == (Quantum *) NULL)
5280 for (x=0; x < (ssize_t) image->columns; x++)
5282 SetPixelAlpha(image,alpha,q);
5283 q+=(ptrdiff_t) GetPixelChannels(image);
5285 status=SyncCacheViewAuthenticPixels(image_view,exception);
5287 image_view=DestroyCacheView(image_view);
5291MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5292 const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5295 *magick_restrict cache_info;
5300 assert(image != (Image *) NULL);
5301 assert(image->signature == MagickCoreSignature);
5302 if (IsEventLogging() != MagickFalse)
5303 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
5304 assert(image->cache != (Cache) NULL);
5305 cache_info=(CacheInfo *) image->cache;
5306 assert(cache_info->signature == MagickCoreSignature);
5307 method=cache_info->virtual_pixel_method;
5308 cache_info->virtual_pixel_method=virtual_pixel_method;
5309 if ((image->columns != 0) && (image->rows != 0))
5310 switch (virtual_pixel_method)
5312 case BackgroundVirtualPixelMethod:
5314 if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
5315 ((image->alpha_trait & BlendPixelTrait) == 0))
5316 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5317 if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5318 (IsGrayColorspace(image->colorspace) != MagickFalse))
5319 (void) SetImageColorspace(image,sRGBColorspace,exception);
5322 case TransparentVirtualPixelMethod:
5324 if ((image->alpha_trait & BlendPixelTrait) == 0)
5325 (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5334#if defined(MAGICKCORE_OPENCL_SUPPORT)
5359static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5361 assert(cache_info != (CacheInfo *) NULL);
5362 assert(cache_info->signature == MagickCoreSignature);
5363 if ((cache_info->type != MemoryCache) ||
5364 (cache_info->opencl == (MagickCLCacheInfo) NULL))
5369 LockSemaphoreInfo(cache_info->semaphore);
5370 cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5371 UnlockSemaphoreInfo(cache_info->semaphore);
5374MagickPrivate
void SyncAuthenticOpenCLBuffer(
const Image *image)
5377 *magick_restrict cache_info;
5379 assert(image != (
const Image *) NULL);
5380 cache_info=(CacheInfo *) image->cache;
5381 CopyOpenCLBuffer(cache_info);
5414MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5415 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5418 *magick_restrict cache_info;
5426 assert(image != (Image *) NULL);
5427 assert(image->signature == MagickCoreSignature);
5428 if (image->cache == (Cache) NULL)
5429 ThrowBinaryException(CacheError,
"PixelCacheIsNotOpen",image->filename);
5430 cache_info=(CacheInfo *) image->cache;
5431 assert(cache_info->signature == MagickCoreSignature);
5432 if (cache_info->type == UndefinedCache)
5433 return(MagickFalse);
5434 if (image->mask_trait != UpdatePixelTrait)
5436 if (((image->channels & WriteMaskChannel) != 0) &&
5437 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5438 return(MagickFalse);
5439 if (((image->channels & CompositeMaskChannel) != 0) &&
5440 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5441 return(MagickFalse);
5443 if (nexus_info->authentic_pixel_cache != MagickFalse)
5445 if (image->taint == MagickFalse)
5446 image->taint=MagickTrue;
5449 assert(cache_info->signature == MagickCoreSignature);
5450 status=WritePixelCachePixels(cache_info,nexus_info,exception);
5451 if ((cache_info->metacontent_extent != 0) &&
5452 (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5453 return(MagickFalse);
5454 if ((status != MagickFalse) && (image->taint == MagickFalse))
5455 image->taint=MagickTrue;
5486static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5487 ExceptionInfo *exception)
5490 *magick_restrict cache_info;
5493 id = GetOpenMPThreadId();
5498 assert(image != (Image *) NULL);
5499 assert(image->signature == MagickCoreSignature);
5500 assert(image->cache != (Cache) NULL);
5501 cache_info=(CacheInfo *) image->cache;
5502 assert(cache_info->signature == MagickCoreSignature);
5503 assert(
id < (
int) cache_info->number_threads);
5504 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5536MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
5537 ExceptionInfo *exception)
5540 *magick_restrict cache_info;
5543 id = GetOpenMPThreadId();
5548 assert(image != (Image *) NULL);
5549 assert(image->signature == MagickCoreSignature);
5550 assert(image->cache != (Cache) NULL);
5551 cache_info=(CacheInfo *) image->cache;
5552 assert(cache_info->signature == MagickCoreSignature);
5553 if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5555 status=cache_info->methods.sync_authentic_pixels_handler(image,
5559 assert(
id < (
int) cache_info->number_threads);
5560 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[
id],
5592MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
5593 ExceptionInfo *exception)
5596 *magick_restrict cache_info;
5598 assert(image != (Image *) NULL);
5599 assert(exception != (ExceptionInfo *) NULL);
5600 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5601 return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5632static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5633 NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5652 if (cache_info->metacontent_extent == 0)
5653 return(MagickFalse);
5654 if (nexus_info->authentic_pixel_cache != MagickFalse)
5656 if (nexus_info->metacontent == (
unsigned char *) NULL)
5657 return(MagickFalse);
5658 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5659 return(MagickFalse);
5660 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5661 nexus_info->region.x;
5662 length=(MagickSizeType) nexus_info->region.width*
5663 cache_info->metacontent_extent;
5664 extent=(MagickSizeType) length*nexus_info->region.height;
5665 rows=nexus_info->region.height;
5667 p=(
unsigned char *) nexus_info->metacontent;
5668 switch (cache_info->type)
5679 if ((cache_info->columns == nexus_info->region.width) &&
5680 (extent == (MagickSizeType) ((
size_t) extent)))
5685 q=(
unsigned char *) cache_info->metacontent+offset*
5686 (MagickOffsetType) cache_info->metacontent_extent;
5687 for (y=0; y < (ssize_t) rows; y++)
5689 (void) memcpy(q,p,(
size_t) length);
5690 p+=(ptrdiff_t) nexus_info->region.width*cache_info->metacontent_extent;
5691 q+=(ptrdiff_t) cache_info->columns*cache_info->metacontent_extent;
5700 LockSemaphoreInfo(cache_info->file_semaphore);
5701 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5703 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5704 cache_info->cache_filename);
5705 UnlockSemaphoreInfo(cache_info->file_semaphore);
5706 return(MagickFalse);
5708 if ((cache_info->columns == nexus_info->region.width) &&
5709 (extent <= MagickMaxBufferExtent))
5714 extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5715 for (y=0; y < (ssize_t) rows; y++)
5717 count=WritePixelCacheRegion(cache_info,cache_info->offset+
5718 (MagickOffsetType) extent*(MagickOffsetType)
5719 cache_info->number_channels*(MagickOffsetType)
sizeof(Quantum)+offset*
5720 (MagickOffsetType) cache_info->metacontent_extent,length,
5721 (
const unsigned char *) p);
5722 if (count != (MagickOffsetType) length)
5724 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5725 offset+=(MagickOffsetType) cache_info->columns;
5727 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5728 (void) ClosePixelCacheOnDisk(cache_info);
5729 UnlockSemaphoreInfo(cache_info->file_semaphore);
5732 case DistributedCache:
5740 LockSemaphoreInfo(cache_info->file_semaphore);
5741 region=nexus_info->region;
5742 if ((cache_info->columns != nexus_info->region.width) ||
5743 (extent > MagickMaxBufferExtent))
5750 for (y=0; y < (ssize_t) rows; y++)
5752 count=WriteDistributePixelCacheMetacontent((DistributeCacheInfo *)
5753 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5754 if (count != (MagickOffsetType) length)
5756 p+=(ptrdiff_t) cache_info->metacontent_extent*nexus_info->region.width;
5759 UnlockSemaphoreInfo(cache_info->file_semaphore);
5765 if (y < (ssize_t) rows)
5767 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5768 cache_info->cache_filename);
5769 return(MagickFalse);
5771 if ((cache_info->debug != MagickFalse) &&
5772 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5773 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5774 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5775 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5776 nexus_info->region.x,(
double) nexus_info->region.y);
5808static MagickBooleanType WritePixelCachePixels(
5809 CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5810 ExceptionInfo *exception)
5829 if (nexus_info->authentic_pixel_cache != MagickFalse)
5831 if (IsValidPixelOffset(nexus_info->region.y,cache_info->columns) == MagickFalse)
5832 return(MagickFalse);
5833 offset=nexus_info->region.y*(MagickOffsetType) cache_info->columns+
5834 nexus_info->region.x;
5835 length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5837 extent=length*nexus_info->region.height;
5838 rows=nexus_info->region.height;
5840 p=nexus_info->pixels;
5841 switch (cache_info->type)
5852 if ((cache_info->columns == nexus_info->region.width) &&
5853 (extent == (MagickSizeType) ((
size_t) extent)))
5858 q=cache_info->pixels+(MagickOffsetType) cache_info->number_channels*
5860 for (y=0; y < (ssize_t) rows; y++)
5862 (void) memcpy(q,p,(
size_t) length);
5863 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5864 q+=(ptrdiff_t) cache_info->number_channels*cache_info->columns;
5873 LockSemaphoreInfo(cache_info->file_semaphore);
5874 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5876 ThrowFileException(exception,FileOpenError,
"UnableToOpenFile",
5877 cache_info->cache_filename);
5878 UnlockSemaphoreInfo(cache_info->file_semaphore);
5879 return(MagickFalse);
5881 if ((cache_info->columns == nexus_info->region.width) &&
5882 (extent <= MagickMaxBufferExtent))
5887 for (y=0; y < (ssize_t) rows; y++)
5889 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5890 (MagickOffsetType) cache_info->number_channels*(MagickOffsetType)
5891 sizeof(*p),length,(
const unsigned char *) p);
5892 if (count != (MagickOffsetType) length)
5894 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5895 offset+=(MagickOffsetType) cache_info->columns;
5897 if (IsFileDescriptorLimitExceeded() != MagickFalse)
5898 (void) ClosePixelCacheOnDisk(cache_info);
5899 UnlockSemaphoreInfo(cache_info->file_semaphore);
5902 case DistributedCache:
5910 LockSemaphoreInfo(cache_info->file_semaphore);
5911 region=nexus_info->region;
5912 if ((cache_info->columns != nexus_info->region.width) ||
5913 (extent > MagickMaxBufferExtent))
5920 for (y=0; y < (ssize_t) rows; y++)
5922 count=WriteDistributePixelCachePixels((DistributeCacheInfo *)
5923 cache_info->server_info,®ion,length,(
const unsigned char *) p);
5924 if (count != (MagickOffsetType) length)
5926 p+=(ptrdiff_t) cache_info->number_channels*nexus_info->region.width;
5929 UnlockSemaphoreInfo(cache_info->file_semaphore);
5935 if (y < (ssize_t) rows)
5937 ThrowFileException(exception,CacheError,
"UnableToWritePixelCache",
5938 cache_info->cache_filename);
5939 return(MagickFalse);
5941 if ((cache_info->debug != MagickFalse) &&
5942 (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5943 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
5944 "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(
double)
5945 nexus_info->region.width,(
double) nexus_info->region.height,(
double)
5946 nexus_info->region.x,(
double) nexus_info->region.y);