]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/cache.c
(no commit message)
[imagemagick] / MagickCore / cache.c
index b894a76585138af26c14dc6ba3adfdb4caf07f90..ac76101ea9ef00ffb4d5e3a19560bd571e463dd3 100644 (file)
@@ -185,7 +185,7 @@ MagickExport Cache AcquirePixelCache(const size_t number_threads)
   CacheInfo
     *cache_info;
 
-  cache_info=(CacheInfo *) AcquireMagickMemory(sizeof(*cache_info));
+  cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
   if (cache_info == (CacheInfo *) NULL)
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
@@ -254,7 +254,7 @@ MagickExport NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
   register ssize_t
     i;
 
-  nexus_info=(NexusInfo **) AcquireQuantumMemory(number_threads,
+  nexus_info=(NexusInfo **) AcquireAlignedMemory(number_threads,
     sizeof(*nexus_info));
   if (nexus_info == (NexusInfo **) NULL)
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
@@ -782,7 +782,7 @@ static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info,
   */
   if (cache_info->debug != MagickFalse)
     (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
-  blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
+  blob=(unsigned char *) AcquireAlignedMemory(MagickMaxBufferExtent,
     sizeof(*blob));
   if (blob == (unsigned char *) NULL)
     {
@@ -948,7 +948,7 @@ static MagickBooleanType UnoptimizedPixelCacheClone(CacheInfo *clone_info,
   length=(size_t) MagickMax(MagickMax(cache_info->number_channels,
     clone_info->number_channels)*sizeof(Quantum),MagickMax(
     cache_info->metacontent_extent,clone_info->metacontent_extent));
-  blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob));
+  blob=(unsigned char *) AcquireAlignedMemory(length,sizeof(*blob));
   if (blob == (unsigned char *) NULL)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),
@@ -1026,8 +1026,7 @@ static MagickBooleanType UnoptimizedPixelCacheClone(CacheInfo *clone_info,
               blob,length);
           else
             {
-              count=WritePixelCacheRegion(clone_info,clone_offset,length,
-                blob);
+              count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
               if ((MagickSizeType) count != length)
                 {
                   status=MagickFalse;
@@ -1145,8 +1144,7 @@ static MagickBooleanType UnoptimizedPixelCacheClone(CacheInfo *clone_info,
               blob,length);
           else
             {
-              count=WritePixelCacheRegion(clone_info,clone_offset,length,
-                blob);
+              count=WritePixelCacheRegion(clone_info,clone_offset,length,blob);
               if ((MagickSizeType) count != length)
                 {
                   status=MagickFalse;
@@ -1484,7 +1482,7 @@ MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
     if (nexus_info[i]->cache != (Quantum *) NULL)
       RelinquishCacheNexusPixels(nexus_info[i]);
     nexus_info[i]->signature=(~MagickSignature);
-    nexus_info[i]=(NexusInfo *) RelinquishAlignedMemory(nexus_info[i]);
+    nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]);
   }
   nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info);
   return(nexus_info);
@@ -1959,6 +1957,7 @@ MagickExport MagickSizeType GetImageExtent(const Image *image)
 %    o exception: return any errors or warnings in this structure.
 %
 */
+
 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
 {
   CacheInfo
@@ -1970,6 +1969,7 @@ static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
   cache_info=(CacheInfo *) image->cache;
   if ((image->storage_class != cache_info->storage_class) ||
       (image->colorspace != cache_info->colorspace) ||
+      (image->matte != cache_info->matte) ||
       (image->columns != cache_info->columns) ||
       (image->rows != cache_info->rows) ||
       (image->number_channels != cache_info->number_channels) ||
@@ -1996,7 +1996,7 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
     time_limit = 0;
 
   static time_t
-    cache_genesis = 0;
+    cache_timestamp = 0;
 
   status=MagickTrue;
   LockSemaphoreInfo(image->semaphore);
@@ -2026,10 +2026,10 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
         Set the exire time in seconds.
       */
       time_limit=GetMagickResourceLimit(TimeResource);
-      cache_genesis=time((time_t *) NULL);
+      cache_timestamp=time((time_t *) NULL);
     }
   if ((time_limit != MagickResourceInfinity) &&
-      ((MagickSizeType) (time((time_t *) NULL)-cache_genesis) >= time_limit))
+      ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
     ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
@@ -2060,6 +2060,8 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
                 status=ClonePixelCachePixels(clone_info,cache_info,exception);
               if (status != MagickFalse)
                 {
+                  if (cache_info->mode == ReadMode)
+                    cache_info->nexus_info=(NexusInfo **) NULL;
                   destroy=MagickTrue;
                   image->cache=clone_image.cache;
                 }
@@ -2077,7 +2079,7 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
       */
       image->taint=MagickTrue;
       image->type=UndefinedType;
-      if (image->colorspace == GRAYColorspace)
+      if (1 && image->colorspace == GRAYColorspace)
         image->colorspace=RGBColorspace;
       if (ValidatePixelCacheMorphology(image) == MagickFalse)
         status=OpenPixelCache(image,IOMode,exception);
@@ -2934,8 +2936,8 @@ static const void *GetVirtualMetacontentFromCache(const Image *image)
 %    o nexus_info: the cache nexus to return the meta-content.
 %
 */
-MagickExport const void *GetVirtualMetacontentFromNexus(
-  const Cache cache,NexusInfo *nexus_info)
+MagickExport const void *GetVirtualMetacontentFromNexus(const Cache cache,
+  NexusInfo *nexus_info)
 {
   CacheInfo
     *cache_info;
@@ -3105,19 +3107,19 @@ static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
   return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
 }
 
-/*
-  VirtualPixelModulo() computes the remainder of dividing offset by extent.  It
-  returns not only the quotient (tile the offset falls in) but also the positive
-  remainer within that tile such that 0 <= remainder < extent.  This method is
-  essentially a ldiv() using a floored modulo division rather than the normal
-  default truncated modulo division.
-*/
 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
   const size_t extent)
 {
   MagickModulo
     modulo;
 
+  /*
+    Compute the remainder of dividing offset by extent.  It returns not only
+    the quotient (tile the offset falls in) but also the positive remainer
+    within that tile such that 0 <= remainder < extent.  This method is
+    essentially a ldiv() using a floored modulo division rather than the
+    normal default truncated modulo division.
+  */
   modulo.quotient=offset/(ssize_t) extent;
   if (offset < 0L)
     modulo.quotient--;
@@ -3145,7 +3147,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
 
   Quantum
     *pixels,
-    *virtual_pixel;
+    virtual_pixel[MaxPixelChannels];
 
   RectangleInfo
     region;
@@ -3160,14 +3162,17 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
     *restrict q;
 
   register ssize_t
-    u,
-    v;
+    i,
+    u;
 
   register unsigned char
     *restrict s;
 
+  ssize_t
+    v;
+
   void
-    *virtual_associated_pixel;
+    *virtual_metacontent;
 
   /*
     Acquire pixels.
@@ -3228,8 +3233,9 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
         "UnableToGetCacheNexus","`%s'",image->filename);
       return((const Quantum *) NULL);
     }
-  virtual_pixel=(Quantum *) NULL;
-  virtual_associated_pixel=(void *) NULL;
+  (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
+    sizeof(*virtual_pixel));
+  virtual_metacontent=(void *) NULL;
   switch (virtual_pixel_method)
   {
     case BackgroundVirtualPixelMethod:
@@ -3243,68 +3249,52 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
     case HorizontalTileVirtualPixelMethod:
     case VerticalTileVirtualPixelMethod:
     {
-      /*
-        Acquire virtual pixel and associated channels.
-      */
-      virtual_pixel=(Quantum *) AcquireQuantumMemory(
-        cache_info->number_channels,sizeof(*virtual_pixel));
-      if (virtual_pixel == (Quantum *) NULL)
-        {
-          virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
-          (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
-            "UnableToGetCacheNexus","`%s'",image->filename);
-          return((const Quantum *) NULL);
-        }
-      (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels*
-        sizeof(*virtual_pixel));
       if (cache_info->metacontent_extent != 0)
         {
-          virtual_associated_pixel=(void *) AcquireMagickMemory(
+          /*
+            Acquire a metacontent buffer.
+          */
+          virtual_metacontent=(void *) AcquireAlignedMemory(1,
             cache_info->metacontent_extent);
-          if (virtual_associated_pixel == (void *) NULL)
+          if (virtual_metacontent == (void *) NULL)
             {
-              virtual_pixel=(Quantum *) RelinquishMagickMemory(
-                virtual_pixel);
               virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
               (void) ThrowMagickException(exception,GetMagickModule(),
                 CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
               return((const Quantum *) NULL);
             }
-          (void) ResetMagickMemory(virtual_associated_pixel,0,
+          (void) ResetMagickMemory(virtual_metacontent,0,
             cache_info->metacontent_extent);
         }
       switch (virtual_pixel_method)
       {
         case BlackVirtualPixelMethod:
         {
-          SetPixelRed(image,0,virtual_pixel);
-          SetPixelGreen(image,0,virtual_pixel);
-          SetPixelBlue(image,0,virtual_pixel);
+          for (i=0; i < (ssize_t) cache_info->number_channels; i++)
+            SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
           break;
         }
         case GrayVirtualPixelMethod:
         {
-          SetPixelRed(image,QuantumRange/2,virtual_pixel);
-          SetPixelGreen(image,QuantumRange/2,virtual_pixel);
-          SetPixelBlue(image,QuantumRange/2,virtual_pixel);
+          for (i=0; i < (ssize_t) cache_info->number_channels; i++)
+            SetPixelChannel(image,(PixelChannel) i,QuantumRange/2,
+              virtual_pixel);
           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
           break;
         }
         case TransparentVirtualPixelMethod:
         {
-          SetPixelRed(image,0,virtual_pixel);
-          SetPixelGreen(image,0,virtual_pixel);
-          SetPixelBlue(image,0,virtual_pixel);
+          for (i=0; i < (ssize_t) cache_info->number_channels; i++)
+            SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel);
           SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
           break;
         }
         case MaskVirtualPixelMethod:
         case WhiteVirtualPixelMethod:
         {
-          SetPixelRed(image,(Quantum) QuantumRange,virtual_pixel);
-          SetPixelGreen(image,(Quantum) QuantumRange,virtual_pixel);
-          SetPixelBlue(image,(Quantum) QuantumRange,virtual_pixel);
+          for (i=0; i < (ssize_t) cache_info->number_channels; i++)
+            SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
           SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
           break;
         }
@@ -3313,6 +3303,8 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
           SetPixelRed(image,image->background_color.red,virtual_pixel);
           SetPixelGreen(image,image->background_color.green,virtual_pixel);
           SetPixelBlue(image,image->background_color.blue,virtual_pixel);
+          if (image->colorspace == CMYKColorspace)
+            SetPixelBlack(image,image->background_color.black,virtual_pixel);
           SetPixelAlpha(image,image->background_color.alpha,virtual_pixel);
           break;
         }
@@ -3420,7 +3412,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
             case WhiteVirtualPixelMethod:
             {
               p=virtual_pixel;
-              r=virtual_associated_pixel;
+              r=virtual_metacontent;
               break;
             }
             case EdgeVirtualPixelMethod:
@@ -3431,7 +3423,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
               if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
                 {
                   p=virtual_pixel;
-                  r=virtual_associated_pixel;
+                  r=virtual_metacontent;
                   break;
                 }
               p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
@@ -3445,7 +3437,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
               if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows))
                 {
                   p=virtual_pixel;
-                  r=virtual_associated_pixel;
+                  r=virtual_metacontent;
                   break;
                 }
               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
@@ -3461,7 +3453,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
               if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns))
                 {
                   p=virtual_pixel;
-                  r=virtual_associated_pixel;
+                  r=virtual_metacontent;
                   break;
                 }
               x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
@@ -3478,8 +3470,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
           (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
             sizeof(*p));
           q+=cache_info->number_channels;
-          if ((s != (void *) NULL) &&
-              (r != (const void *) NULL))
+          if ((s != (void *) NULL) && (r != (const void *) NULL))
             {
               (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
               s+=cache_info->metacontent_extent;
@@ -3496,7 +3487,7 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
       r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
       (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
       q+=length*cache_info->number_channels;
-      if ((s != (void *) NULL) && (r != (const void *) NULL))
+      if ((r != (void *) NULL) && (s != (const void *) NULL))
         {
           (void) memcpy(s,r,(size_t) length);
           s+=length*cache_info->metacontent_extent;
@@ -3506,11 +3497,8 @@ MagickExport const Quantum *GetVirtualPixelsFromNexus(const Image *image,
   /*
     Free resources.
   */
-  if (virtual_associated_pixel != (void *) NULL)
-    virtual_associated_pixel=(void *) RelinquishMagickMemory(
-      virtual_associated_pixel);
-  if (virtual_pixel != (Quantum *) NULL)
-    virtual_pixel=(Quantum *) RelinquishMagickMemory(virtual_pixel);
+  if (virtual_metacontent != (void *) NULL)
+    virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
   virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
   return(pixels);
 }
@@ -4009,7 +3997,6 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if ((image->columns == 0) || (image->rows == 0))
     ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
-  StandardPixelChannelMap(image);
   cache_info=(CacheInfo *) image->cache;
   assert(cache_info->signature == MagickSignature);
   source_info=(*cache_info);
@@ -4018,11 +4005,13 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
     image->filename,(double) GetImageIndexInList(image));
   cache_info->storage_class=image->storage_class;
   cache_info->colorspace=image->colorspace;
-  cache_info->mode=mode;
+  cache_info->matte=image->matte;
   cache_info->rows=image->rows;
   cache_info->columns=image->columns;
+  InitializePixelChannelMap(image);
   cache_info->number_channels=GetPixelChannels(image);
   cache_info->metacontent_extent=image->metacontent_extent;
+  cache_info->mode=mode;
   if (image->ping != MagickFalse)
     {
       cache_info->type=PingCache;
@@ -4290,8 +4279,7 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
       (cache_info->reference_count == 1))
     {
       LockSemaphoreInfo(cache_info->semaphore);
-      if ((cache_info->mode != ReadMode) &&
-          (cache_info->type != MemoryCache) &&
+      if ((cache_info->mode != ReadMode) && (cache_info->type != MemoryCache) &&
           (cache_info->reference_count == 1))
         {
           int
@@ -5330,6 +5318,45 @@ MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   S y n c I m a g e P i x e l C a c h e                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
+%  The method returns MagickTrue if the pixel region is flushed, otherwise
+%  MagickFalse.
+%
+%  The format of the SyncImagePixelCache() method is:
+%
+%      MagickBooleanType SyncImagePixelCache(Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType SyncImagePixelCache(Image *image,
+  ExceptionInfo *exception)
+{
+  CacheInfo
+    *cache_info;
+
+  assert(image != (Image *) NULL);
+  assert(exception != (ExceptionInfo *) NULL);
+  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
+  return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   W r i t e P i x e l C a c h e M e t a c o n t e n t                       %
 %                                                                             %
 %                                                                             %