]> granicus.if.org Git - imagemagick/commitdiff
The CUBE image format returns a HALD image (e.g. cube:Vibrant.cube[7])
authorCristy <urban-warrior@imagemagick.org>
Fri, 21 Dec 2018 22:21:45 +0000 (17:21 -0500)
committerCristy <urban-warrior@imagemagick.org>
Fri, 21 Dec 2018 22:21:45 +0000 (17:21 -0500)
coders/cube.c
coders/hald.c
coders/jpeg.c
coders/pcd.c

index 7727f7ab079a90ee1613391b1890117460f8211a..08b574f91c6b6191809070689511ad9cd16f29ae 100644 (file)
 static Image *ReadCUBEImage(const ImageInfo *image_info,
   ExceptionInfo *exception)
 {
+#define MapHALD(level,b,g,r)  ((ssize_t) ((b)*(level)*(level)+(g)*(level)+(r)))
+
+  typedef struct _CubePixel
+  {
+    float
+      r,
+      g,
+      b;
+  } CubePixel;
+
   char
-    *cube_buffer,
-   token[MagickPathExtent],
-   value[MagickPathExtent];
+    *buffer,
+    token[MagickPathExtent],
+    value[MagickPathExtent];
+
+  CubePixel
+    *cube,
+    *hald;
 
   Image
     *image;
@@ -107,19 +121,21 @@ static Image *ReadCUBEImage(const ImageInfo *image_info,
   MagickBooleanType
     status;
 
+  MemoryInfo
+    *cube_info,
+    *hald_info;
+
   register char
     *p;
 
   size_t
-    length;
+    cube_level,
+    hald_level;
 
   ssize_t
-    blue_rows,
-    green_columns,
-    red_columns;
-
-  ssize_t
-    blue;
+    b,
+    i,
+    n;
 
   /*
     Create CUBE color lookup table image.
@@ -138,105 +154,188 @@ static Image *ReadCUBEImage(const ImageInfo *image_info,
       image=DestroyImageList(image);
       return((Image *) NULL);
     }
-  length=MagickPathExtent;
-  cube_buffer=(char *) AcquireQuantumMemory((size_t) length,
-    sizeof(*cube_buffer));
-  if (cube_buffer == (char *) NULL)
-    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-  red_columns=0;
-  green_columns=0;
-  blue_rows=0;
-  *cube_buffer='\0';
-  p=cube_buffer;
+  buffer=AcquireString("");
+  cube_level=0;
+  cube_info=(MemoryInfo *) NULL;
+  cube=(CubePixel *) NULL;
+  n=0;
+  *buffer='\0';
+  p=buffer;
   while (ReadBlobString(image,p) != (char *) NULL)
   {
     const char
       *q;
 
-    if ((*p == '#') && ((p == cube_buffer) || (*(p-1) == '\n')))
-      continue;
     q=p;
     GetNextToken(q,&q,MagickPathExtent,token);
+    if ((*token == '#') || (*token == '\0'))
+      continue;
     GetNextToken(q,&q,MagickPathExtent,value);
-    if (LocaleCompare(token,"LUT_1D_SIZE") == 0)
+    if ((LocaleCompare(token,"LUT_1D_SIZE") == 0) ||
+        (LocaleCompare(token,"LUT_3D_SIZE") == 0))
       {
-        red_columns=(ssize_t) StringToLong(value);
-        if ((red_columns < 0) || (red_columns > 65535))
-          {
-            cube_buffer=DestroyString(cube_buffer);
-            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
-          }
-        green_columns=1;
-        blue_rows=1;
+        cube_level=(size_t) StringToLong(value);
+        if ((cube_level < 2) || (cube_level > 65536))
+          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+        if (cube_info != (MemoryInfo *) NULL)
+          cube_info=RelinquishVirtualMemory(cube_info);
+        cube_info=AcquireVirtualMemory(cube_level*cube_level,cube_level*
+          sizeof(*cube));
+        if (cube_info == (MemoryInfo *) NULL)
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        cube=(CubePixel *) GetVirtualMemoryBlob(cube_info);
+        (void) memset(cube,0,cube_level*cube_level*cube_level*sizeof(*cube));
       }
-    if (LocaleCompare(token,"LUT_3D_SIZE") == 0)
-      {
-        red_columns=(ssize_t) StringToLong(value);
-        if ((red_columns < 0) || (red_columns > 256))
+    else
+      if (LocaleCompare(token,"TITLE ") == 0)
+        (void) SetImageProperty(image,"title",value,exception);
+      else
+        if (cube_level != 0)
           {
-            cube_buffer=DestroyString(cube_buffer);
-            ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+            char
+              *q;
+
+            q=buffer;
+            cube[n].r=StringToDouble(q,&q);
+            cube[n].g=StringToDouble(q,&q);
+            cube[n].b=StringToDouble(q,&q);
+            n++;
           }
-        green_columns=red_columns;
-        blue_rows=red_columns;
+        else
+          if (('+' < *buffer) && (*buffer < ':'))
+            break;
+  }
+  buffer=DestroyString(buffer);
+  if (cube_level == 0)
+    {
+      cube_info=RelinquishVirtualMemory(cube_info);
+      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+    }
+  /*
+    Create HALD image, interopolate from CUBE LUT.
+  */
+  hald_level=image_info->scene;
+  if ((hald_level < 2) || (hald_level > 256))
+    hald_level=8;
+  hald_info=AcquireVirtualMemory(hald_level*hald_level*hald_level,
+    hald_level*hald_level*hald_level*sizeof(*hald));
+  if (hald_info == (MemoryInfo *) NULL)
+    {
+      cube_info=RelinquishVirtualMemory(cube_info);
+      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+    }
+  hald=(CubePixel *) GetVirtualMemoryBlob(hald_info);
+  (void) memset(hald,0,hald_level*hald_level*hald_level*sizeof(*hald));
+  n=0;
+  for (b=0; b < (ssize_t) (hald_level*hald_level); b++)
+  {
+    register ssize_t
+      g;
+
+    for (g=0; g < (ssize_t) (hald_level*hald_level); g++)
+    {
+      register ssize_t
+        r;
+
+      for (r=0; r < (ssize_t) (hald_level*hald_level); r++)
+      {
+        CubePixel
+          index,
+          next,
+          offset,
+          scale;
+
+        offset.r=(PerceptibleReciprocal((double) (hald_level*hald_level)-1.0)*
+          r)*(cube_level-1.0);
+        index.r=floor(offset.r);
+        scale.r=offset.r-index.r;
+        next.r=index.r+1;
+        if ((size_t) index.r == (cube_level-1))
+          next.r=index.r;
+        offset.g=(PerceptibleReciprocal(((double) hald_level*hald_level)-1.0)*
+          g)*(cube_level-1.0);
+        index.g=floor(offset.g);
+        scale.g=offset.g-index.g;
+        next.g=index.g+1;
+        if ((size_t) index.g == (cube_level-1))
+          next.g=index.g;
+        offset.b=(PerceptibleReciprocal(((double) hald_level*hald_level)-1.0)*
+          b)*(cube_level-1.0);
+        index.b=floor(offset.b);
+        scale.b=offset.b-index.b;
+        next.b=index.b+1;
+        if ((size_t) index.b == (cube_level-1))
+          next.b=index.b;
+        hald[n].r=cube[MapHALD(cube_level,index.b,index.g,index.r)].r+scale.r*(
+          cube[MapHALD(cube_level,index.b,index.g,next.r)].r-
+          cube[MapHALD(cube_level,index.b,index.g,index.r)].r);
+        hald[n].g=cube[MapHALD(cube_level,index.b,index.g,index.r)].g+scale.g*(
+          cube[MapHALD(cube_level,index.b,next.g,index.r)].g-
+          cube[MapHALD(cube_level,index.b,index.g,index.r)].g);
+        hald[n].b=cube[MapHALD(cube_level,index.b,index.g,index.r)].b+scale.b*(
+          cube[MapHALD(cube_level,next.b,index.g,index.r)].b-
+          cube[MapHALD(cube_level,index.b,index.g,index.r)].b);
+        n++;
       }
-    if (LocaleCompare(token,"TITLE ") == 0)
-      (void) SetImageProperty(image,"title",value,exception);
-    if (('+' < *p) && (*p < ':'))
-      break;
+    }
   }
+  cube_info=RelinquishVirtualMemory(cube_info);
+  /*
+    Write HALD image.
+  */
   status=MagickTrue;
-  image->columns=(size_t) (red_columns*green_columns);
-  image->rows=(size_t) (blue_rows);
+  image->columns=(size_t) (hald_level*hald_level*hald_level);
+  image->rows=(size_t) (hald_level*hald_level*hald_level);
   status=SetImageExtent(image,image->columns,image->rows,exception);
   if (status == MagickFalse)
     {
-      cube_buffer=DestroyString(cube_buffer);
+      hald_info=RelinquishVirtualMemory(hald_info);
       return(DestroyImageList(image));
     }
-  for (blue=0; blue < blue_rows; blue++)
+  n=0;
+  for (b=0; b < (ssize_t) (hald_level*hald_level); b++)
   {
-    ssize_t
-      green,
-      red;
-
-    register Quantum
-      *magick_restrict q;
+    register ssize_t
+      g;
 
     if (status == MagickFalse)
       continue;
-    q=QueueAuthenticPixels(image,0,blue,(size_t) red_columns*green_columns,1,
-      exception);
-    if (q == (Quantum *) NULL)
-      {
-        status=MagickFalse;
-        continue;
-      }
-    for (green=0; green < green_columns; green++)
+    for (g=0; g < (ssize_t) (hald_level*hald_level); g++)
     {
-      for (red=0; red < red_columns; red++)
+      register ssize_t
+        r;
+
+      for (r=0; r < (ssize_t) (hald_level*hald_level); r++)
       {
-        char
-          *p;
+        register Quantum
+          *magick_restrict q;
 
-        p=cube_buffer;
-        SetPixelRed(image,ClampToQuantum(QuantumRange*StringToDouble(p,&p)),
-          q);
-        SetPixelGreen(image,ClampToQuantum(QuantumRange*StringToDouble(p,&p)),
-          q);
-        SetPixelBlue(image,ClampToQuantum(QuantumRange*StringToDouble(p,&p)),
-          q);
+        ssize_t
+          x,
+          y;
+
+        x=(g % hald_level)*(hald_level*hald_level)+r;
+        y=(b*hald_level)+((g/hald_level) % (hald_level*hald_level));
+        q=QueueAuthenticPixels(image,x,y,1,1,exception);
+        if (q == (Quantum *) NULL)
+          {
+            status=MagickFalse;
+            continue;
+          }
+        SetPixelRed(image,ClampToQuantum(QuantumRange*hald[n].r),q);
+        SetPixelGreen(image,ClampToQuantum(QuantumRange*hald[n].g),q);
+        SetPixelBlue(image,ClampToQuantum(QuantumRange*hald[n].b),q);
         SetPixelAlpha(image,OpaqueAlpha,q);
-        q+=GetPixelChannels(image);
-        while (ReadBlobString(image,cube_buffer) != (char *) NULL)
-          if (('+' < *cube_buffer) && (*cube_buffer < ':'))
-            break;
+        if (SyncAuthenticPixels(image,exception) == MagickFalse)
+          status=MagickFalse;
+        n++;
       }
     }
-    if (SyncAuthenticPixels(image,exception) == MagickFalse)
-      status=MagickFalse;
   }
-  cube_buffer=DestroyString(cube_buffer);
+  hald_info=RelinquishVirtualMemory(hald_info);
+  if (image_info->scene != 0)
+    for (i=0; i < (ssize_t) image_info->scene; i++)
+      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
   return(GetFirstImageInList(image));
 }
 \f
index 20091f6d0e663b5b9418d02a783b719051b198a4..ab4a303d1e19736b493fcbaf969a3b324ebb652d 100644 (file)
@@ -103,6 +103,7 @@ static Image *ReadHALDImage(const ImageInfo *image_info,
     level;
 
   ssize_t
+    i,
     y;
 
   /*
@@ -119,7 +120,9 @@ static Image *ReadHALDImage(const ImageInfo *image_info,
   level=0;
   if (*image_info->filename != '\0')
     level=StringToUnsignedLong(image_info->filename);
-  if (level < 2)
+  if (image_info->scene != 0)
+    level=image_info->scene;
+  if ((level < 2) || (level > 256))
     level=8;
   status=MagickTrue;
   cube_size=level*level;
@@ -162,6 +165,9 @@ static Image *ReadHALDImage(const ImageInfo *image_info,
     if (SyncAuthenticPixels(image,exception) == MagickFalse)
       status=MagickFalse;
   }
+  if (image_info->scene != 0)
+    for (i=0; i < (ssize_t) image_info->scene; i++)
+      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
   return(GetFirstImageInList(image));
 }
 \f
index f55b4e64320eef1fa42791b7ab0d48d499f976ca..5647140e276a649f19fbbbf495d21ed466081b78 100644 (file)
@@ -1381,15 +1381,15 @@ static Image *ReadJPEGImage(const ImageInfo *image_info,
   if (jpeg_info.arith_code == TRUE)
     (void) SetImageProperty(image,"jpeg:coding","arithmetic",exception);
 #endif
+  if ((dct_method == (const char *) NULL) && (image->quality > 0) &&
+      (image->quality <= 90))
+    jpeg_info.dct_method=JDCT_IFAST;
   if (image_info->ping != MagickFalse)
     {
       jpeg_destroy_decompress(&jpeg_info);
       (void) CloseBlob(image);
       return(GetFirstImageInList(image));
     }
-  if ((dct_method == (const char *) NULL) && (image->quality > 0) &&
-      (image->quality <= 90))
-    jpeg_info.dct_method=JDCT_IFAST;
   status=SetImageExtent(image,image->columns,image->rows,exception);
   if (status == MagickFalse)
     {
index e51073232e236fd1d52bfc34a91581be86068bb3..8eb8ac6526b40160d8f3c3244fa1c03f47fe896d 100644 (file)
@@ -873,15 +873,9 @@ static Image *ReadPCDImage(const ImageInfo *image_info,ExceptionInfo *exception)
   image->colorspace=YCCColorspace;
   if (LocaleCompare(image_info->magick,"PCDS") == 0)
     (void) SetImageColorspace(image,sRGBColorspace,exception);
-  if ((image_info->number_scenes != 0) && (image_info->scene != 0))
-    {
-      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
-      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
-      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
+  if (image_info->scene != 0)
+    for (i=0; i < (ssize_t) image_info->scene; i++)
       AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
-      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
-      AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
-    }
   return(GetFirstImageInList(image));
 }
 \f