[gimp/soc-2011-seamless-clone2] file-fits: add support for high bit depths



commit 8e74b2b856444587796b18ea3e3254963c06d6c9
Author: Michael Henning <drawoc darkrefraction com>
Date:   Sun Feb 17 18:32:08 2013 -0500

    file-fits: add support for high bit depths

 plug-ins/file-fits/fits-io.c |  439 +++++++++++++++++++++---------------------
 plug-ins/file-fits/fits.c    |  106 ++++++++--
 2 files changed, 307 insertions(+), 238 deletions(-)
---
diff --git a/plug-ins/file-fits/fits-io.c b/plug-ins/file-fits/fits-io.c
index 5d99904..42d2760 100644
--- a/plug-ins/file-fits/fits-io.c
+++ b/plug-ins/file-fits/fits-io.c
@@ -1970,8 +1970,7 @@ fits_read_pixel (FitsFile         *ff,
   gdouble  datadiff, pixdiff;
   guchar   pixbuffer[4096];
   guchar  *pix;
-  guchar  *cdata;
-  guchar   creplace;
+  glong    creplace;
   gint     transcount = 0;
   glong    tdata, tmin, tmax;
   gint     maxelem;
@@ -1979,8 +1978,8 @@ fits_read_pixel (FitsFile         *ff,
   if (ff->openmode != 'r')
     return -1;   /* Not open for reading */
 
-  if (trans->dsttyp != 'c')
-    return -1;  /* Currently we only return chars */
+  if (trans->dsttyp != 'k')
+    return -1;  /* Currently we only return types equavalent to the image format */
 
   if (npix <= 0)
     return npix;
@@ -1994,278 +1993,282 @@ fits_read_pixel (FitsFile         *ff,
   tmin = (glong) trans->datamin;
   tmax = (glong) trans->datamax;
 
-  if (tmin < 0)
-    tmin = 0;
-  else if (tmin > 255)
-    tmin = 255;
-
-  if (tmax < 0)
-    tmax = 0;
-  else if (tmax > 255)
-    tmax = 255;
-
-  cdata    = (guchar *) buf;
-  creplace = (guchar) trans->replacement;
+  creplace = (glong) trans->replacement;
 
   switch (hdulist->bitpix)
     {
     case 8:
-      while (npix > 0)  /* For all pixels to read */
-        {
-          FitsBitpix8 bp8, bp8blank;
+      {
+        guchar *cdata = (guchar *) buf;
+        while (npix > 0)  /* For all pixels to read */
+          {
+            FitsBitpix8 bp8, bp8blank;
 
-          maxelem = sizeof (pixbuffer) / hdulist->bpp;
-          if (maxelem > npix)
-            maxelem = npix;
+            maxelem = sizeof (pixbuffer) / hdulist->bpp;
+            if (maxelem > npix)
+              maxelem = npix;
 
-          if (fread ((gchar *) pixbuffer, hdulist->bpp,
-                     maxelem, ff->fp) != maxelem)
-            return -1;
+            if (fread ((gchar *) pixbuffer, hdulist->bpp,
+                       maxelem, ff->fp) != maxelem)
+              return -1;
 
-          npix -= maxelem;
+            npix -= maxelem;
 
-          pix = pixbuffer;
+            pix = pixbuffer;
 
-          if (hdulist->used.blank)
-            {
-              bp8blank = (FitsBitpix8) hdulist->blank;
+            if (hdulist->used.blank)
+              {
+                bp8blank = (FitsBitpix8) hdulist->blank;
 
-              while (maxelem--)
-                {
-                  bp8 = (FitsBitpix8) * (pix++);
+                while (maxelem--)
+                  {
+                    bp8 = (FitsBitpix8) * (pix++);
 
-                  if (bp8 == bp8blank)      /* Is it a blank pixel ? */
-                    {
-                      *(cdata++) = creplace;
-                    }
-                  else                      /* Do transform */
-                    {
-                      tdata = (glong) (bp8 * scale + offs);
-                      tdata = CLAMP (tdata, tmin, tmax);
+                    if (bp8 == bp8blank)      /* Is it a blank pixel ? */
+                      {
+                        *(cdata++) = (guchar) creplace;
+                      }
+                    else                      /* Do transform */
+                      {
+                        tdata = (glong) (bp8 * scale + offs);
+                        tdata = CLAMP (tdata, tmin, tmax);
 
-                      *(cdata++) = (guchar) tdata;
-                    }
+                        *(cdata++) = (guchar) tdata;
+                      }
 
-                  transcount++;
-                }
-            }
-          else
-            {
-              while (maxelem--)
-                {
-                  bp8 = (FitsBitpix8) * (pix++);
+                    transcount++;
+                  }
+              }
+            else
+              {
+                while (maxelem--)
+                  {
+                    bp8 = (FitsBitpix8) * (pix++);
 
-                  tdata = (glong) (bp8 * scale + offs);
-                  tdata = CLAMP (tdata, tmin, tmax);
+                    tdata = (glong) (bp8 * scale + offs);
+                    tdata = CLAMP (tdata, tmin, tmax);
 
-                  *(cdata++) = (guchar) tdata;
+                    *(cdata++) = (guchar) tdata;
 
-                  transcount++;
-                }
-            }
-        }
+                    transcount++;
+                  }
+              }
+          }
+      }
       break;
 
     case 16:
-      while (npix > 0)  /* For all pixels to read */
-        {
-          FitsBitpix16 bp16, bp16blank;
+      {
+        FitsBitpix16 *cdata = (FitsBitpix16 *) buf;
+        while (npix > 0)  /* For all pixels to read */
+          {
+            FitsBitpix16 bp16, bp16blank;
 
-          maxelem = sizeof (pixbuffer) / hdulist->bpp;
-          if (maxelem > npix)
-            maxelem = npix;
+            maxelem = sizeof (pixbuffer) / hdulist->bpp;
+            if (maxelem > npix)
+              maxelem = npix;
 
-          if (fread ((gchar *) pixbuffer, hdulist->bpp,
-                     maxelem, ff->fp) != maxelem)
-            return -1;
+            if (fread ((gchar *) pixbuffer, hdulist->bpp,
+                       maxelem, ff->fp) != maxelem)
+              return -1;
 
-          npix -= maxelem;
+            npix -= maxelem;
 
-          pix = pixbuffer;
-          if (hdulist->used.blank)
-            {
-              bp16blank = (FitsBitpix16) hdulist->blank;
+            pix = pixbuffer;
+            if (hdulist->used.blank)
+              {
+                bp16blank = (FitsBitpix16) hdulist->blank;
 
-              while (maxelem--)
-                {
-                  FITS_GETBITPIX16 (pix, bp16);
-
-                  if (bp16 == bp16blank)
-                    {
-                      *(cdata++) = creplace;
-                    }
-                  else
-                    {
-                      tdata = (glong) (bp16 * scale + offs);
-
-                      if (tdata < tmin)
-                        tdata = tmin;
-                      else if (tdata > tmax)
-                        tdata = tmax;
-
-                      *(cdata++) = (guchar) tdata;
-                    }
-
-                  transcount++;
-                  pix += 2;
-                }
-            }
-          else
-            {
-              while (maxelem--)
-                {
-                  FITS_GETBITPIX16 (pix, bp16);
+                while (maxelem--)
+                  {
+                    FITS_GETBITPIX16 (pix, bp16);
+
+                    if (bp16 == bp16blank)
+                      {
+                        *(cdata++) = (FitsBitpix16) creplace;
+                      }
+                    else
+                      {
+                        tdata = (glong) (bp16 * scale + offs);
 
-                  tdata = (glong) (bp16 * scale + offs);
-                  if (tdata < tmin)
-                    tdata = tmin;
-                  else if (tdata > tmax)
-                    tdata = tmax;
+                        if (tdata < tmin)
+                          tdata = tmin;
+                        else if (tdata > tmax)
+                          tdata = tmax;
 
-                  *(cdata++) = (guchar) tdata;
+                        *(cdata++) = (FitsBitpix16) tdata;
+                      }
 
-                  transcount++;
-                  pix += 2;
-                }
-            }
-        }
+                    transcount++;
+                    pix += 2;
+                  }
+              }
+            else
+              {
+                while (maxelem--)
+                  {
+                    FITS_GETBITPIX16 (pix, bp16);
+
+                    tdata = (glong) (bp16 * scale + offs);
+                    if (tdata < tmin)
+                      tdata = tmin;
+                    else if (tdata > tmax)
+                      tdata = tmax;
+
+                    *(cdata++) = (FitsBitpix16) tdata;
+
+                    transcount++;
+                    pix += 2;
+                  }
+              }
+          }
+      }
       break;
 
     case 32:
-      while (npix > 0)  /* For all pixels to read */
-        {
-          FitsBitpix32 bp32, bp32blank;
+      {
+        FitsBitpix32 *cdata = (FitsBitpix32 *) buf;
+        while (npix > 0)  /* For all pixels to read */
+          {
+            FitsBitpix32 bp32, bp32blank;
 
-          maxelem = sizeof (pixbuffer) / hdulist->bpp;
-          if (maxelem > npix)
-            maxelem = npix;
+            maxelem = sizeof (pixbuffer) / hdulist->bpp;
+            if (maxelem > npix)
+              maxelem = npix;
 
-          if (fread ((gchar *) pixbuffer, hdulist->bpp,
-                     maxelem, ff->fp) != maxelem)
-            return -1;
+            if (fread ((gchar *) pixbuffer, hdulist->bpp,
+                       maxelem, ff->fp) != maxelem)
+              return -1;
 
-          npix -= maxelem;
+            npix -= maxelem;
 
-          pix = pixbuffer;
-          if (hdulist->used.blank)
-            {
-              bp32blank = (FitsBitpix32) hdulist->blank;
+            pix = pixbuffer;
+            if (hdulist->used.blank)
+              {
+                bp32blank = (FitsBitpix32) hdulist->blank;
 
-              while (maxelem--)
-                {
-                  FITS_GETBITPIX32 (pix, bp32);
-
-                  if (bp32 == bp32blank)
-                    {
-                      *(cdata++) = creplace;
-                    }
-                  else
-                    {
-                      tdata = (glong) (bp32 * scale + offs);
-                      if (tdata < tmin)
-                        tdata = tmin;
-                      else if (tdata > tmax)
-                        tdata = tmax;
-
-                      *(cdata++) = (guchar) tdata;
-                    }
-
-                  transcount++;
-                  pix += 4;
-                }
-            }
-          else
-            {
-              while (maxelem--)
-                {
-                  FITS_GETBITPIX32 (pix, bp32);
+                while (maxelem--)
+                  {
+                    FITS_GETBITPIX32 (pix, bp32);
 
-                  tdata = (glong) (bp32 * scale + offs);
-                  tdata = CLAMP (tdata, tmin, tmax);
+                    if (bp32 == bp32blank)
+                      {
+                        *(cdata++) = (FitsBitpix32) creplace;
+                      }
+                    else
+                      {
+                        tdata = (glong) (bp32 * scale + offs);
+                        if (tdata < tmin)
+                          tdata = tmin;
+                        else if (tdata > tmax)
+                          tdata = tmax;
 
-                  *(cdata++) = (guchar) tdata;
+                        *(cdata++) = (FitsBitpix32) tdata;
+                      }
 
-                  transcount++;
-                  pix += 4;
-                }
-            }
-        }
+                    transcount++;
+                    pix += 4;
+                  }
+              }
+            else
+              {
+                while (maxelem--)
+                  {
+                    FITS_GETBITPIX32 (pix, bp32);
+
+                    tdata = (glong) (bp32 * scale + offs);
+                    tdata = CLAMP (tdata, tmin, tmax);
+
+                    *(cdata++) = (FitsBitpix32) tdata;
+
+                    transcount++;
+                    pix += 4;
+                  }
+              }
+          }
+      }
       break;
 
     case -32:
-      while (npix > 0)  /* For all pixels to read */
-        {
-          FitsBitpixM32 bpm32 = 0;
+      {
+        FitsBitpixM32 *cdata = (FitsBitpixM32 *) buf;
+        while (npix > 0)  /* For all pixels to read */
+          {
+            FitsBitpixM32 bpm32 = 0;
 
-          maxelem = sizeof (pixbuffer) / hdulist->bpp;
-          if (maxelem > npix)
-            maxelem = npix;
+            maxelem = sizeof (pixbuffer) / hdulist->bpp;
+            if (maxelem > npix)
+              maxelem = npix;
 
-          if (fread ((gchar *) pixbuffer, hdulist->bpp,
-                     maxelem, ff->fp) != maxelem)
-            return -1;
+            if (fread ((gchar *) pixbuffer, hdulist->bpp,
+                       maxelem, ff->fp) != maxelem)
+              return -1;
 
-          npix -= maxelem;
+            npix -= maxelem;
 
-          pix = pixbuffer;
-          while (maxelem--)
-            {
-              if (fits_nan_32 (pix))    /* An IEEE special value ? */
-                {
-                  *(cdata++) = creplace;
-                }
-              else                      /* Do transform */
-                {
-                  FITS_GETBITPIXM32 (pix, bpm32);
+            pix = pixbuffer;
+            while (maxelem--)
+              {
+                if (fits_nan_32 (pix))    /* An IEEE special value ? */
+                  {
+                    *(cdata++) = trans->replacement;
+                  }
+                else                      /* Do transform */
+                  {
+                    FITS_GETBITPIXM32 (pix, bpm32);
 
-                  tdata = (glong) (bpm32 * scale + offs);
-                  tdata = CLAMP (tdata, tmin, tmax);
+                    bpm32 = bpm32 * scale + offs;
+                    bpm32 = CLAMP (bpm32, trans->datamin, trans->datamax);
 
-                  *(cdata++) = (guchar) tdata;
-                }
+                    *(cdata++) = bpm32;
+                  }
 
-              transcount++;
-              pix += 4;
-            }
-        }
+                transcount++;
+                pix += 4;
+              }
+          }
+      }
       break;
 
     case -64:
-      while (npix > 0)  /* For all pixels to read */
-        {
-          FitsBitpixM64 bpm64;
+      {
+        FitsBitpixM64 *cdata = (FitsBitpixM64 *) buf;
+        while (npix > 0)  /* For all pixels to read */
+          {
+            FitsBitpixM64 bpm64;
 
-          maxelem = sizeof (pixbuffer) / hdulist->bpp;
-          if (maxelem > npix)
-            maxelem = npix;
+            maxelem = sizeof (pixbuffer) / hdulist->bpp;
+            if (maxelem > npix)
+              maxelem = npix;
 
-          if (fread ((gchar *) pixbuffer, hdulist->bpp,
-                     maxelem, ff->fp) != maxelem)
-            return -1;
+            if (fread ((gchar *) pixbuffer, hdulist->bpp,
+                       maxelem, ff->fp) != maxelem)
+              return -1;
 
-          npix -= maxelem;
+            npix -= maxelem;
 
-          pix = pixbuffer;
-          while (maxelem--)
-            {
-              if (fits_nan_64 (pix))
-                {
-                  *(cdata++) = creplace;
-                }
-              else
-                {
-                  FITS_GETBITPIXM64 (pix, bpm64);
+            pix = pixbuffer;
+            while (maxelem--)
+              {
+                if (fits_nan_64 (pix))
+                  {
+                    *(cdata++) = trans->replacement;
+                  }
+                else
+                  {
+                    FITS_GETBITPIXM64 (pix, bpm64);
 
-                  tdata = (glong) (bpm64 * scale + offs);
-                  tdata = CLAMP (tdata, tmin, tmax);
+                    bpm64 = bpm64 * scale + offs;
+                    bpm64 = CLAMP (bpm64, trans->datamin, trans->datamax);
 
-                  *(cdata++) = (guchar) tdata;
-                }
+                    *(cdata++) = bpm64;
+                  }
 
-              transcount++;
-              pix += 8;
-            }
-        }
+                transcount++;
+                pix += 8;
+              }
+          }
+      }
       break;
     }
 
diff --git a/plug-ins/file-fits/fits.c b/plug-ins/file-fits/fits.c
index 43e8a90..fd82530 100644
--- a/plug-ins/file-fits/fits.c
+++ b/plug-ins/file-fits/fits.c
@@ -94,6 +94,7 @@ static gint32        create_new_image   (const gchar        *filename,
                                          guint               height,
                                          GimpImageBaseType   itype,
                                          GimpImageType       dtype,
+                                         GimpPrecision       iprecision,
                                          gint32             *layer_ID,
                                          GeglBuffer        **buffer);
 
@@ -502,13 +503,15 @@ create_new_image (const gchar        *filename,
                   guint               height,
                   GimpImageBaseType   itype,
                   GimpImageType       dtype,
+                  GimpPrecision       iprecision,
                   gint32             *layer_ID,
                   GeglBuffer        **buffer)
 {
   gint32  image_ID;
   char   *tmp;
 
-  image_ID = gimp_image_new (width, height, itype);
+  image_ID = gimp_image_new_with_precision (width, height, itype, iprecision);
+
   if ((tmp = g_malloc (strlen (filename) + 64)) != NULL)
     {
       sprintf (tmp, "%s-img%ld", filename, (long)pagenum);
@@ -548,9 +551,12 @@ load_fits (const gchar *filename,
   GeglBuffer        *buffer;
   GimpImageBaseType  itype;
   GimpImageType      dtype;
+  GimpPrecision      iprecision;
   gint               err = 0;
   FitsHduList       *hdulist;
   FitsPixTransform   trans;
+  double             datamax, replacetransform;
+  const Babl        *type, *format;
 
   hdulist = fits_seek_image (ifp, (int)picnum);
   if (hdulist == NULL)
@@ -559,38 +565,96 @@ load_fits (const gchar *filename,
   width  = hdulist->naxisn[0];  /* Set the size of the FITS image */
   height = hdulist->naxisn[1];
 
+  switch (hdulist->bitpix)
+    {
+    case 8:
+      iprecision = GIMP_PRECISION_U8;
+      type = babl_type ("u8");
+      datamax = 255.0;
+      replacetransform = 1.0;
+      break;
+    case 16:
+      iprecision = GIMP_PRECISION_U16;
+      type = babl_type ("u16");
+      datamax = 65535.0;
+      replacetransform = 257;
+      break;
+    case 32:
+      iprecision = GIMP_PRECISION_U32;
+      type = babl_type ("u32");
+      datamax = 4294967295.0;
+      replacetransform = 16843009;
+      break;
+    case -32:
+      iprecision = GIMP_PRECISION_FLOAT;
+      type = babl_type ("float");
+      datamax = 1.0;
+      replacetransform = 1.0 / 255.0;
+      break;
+    case -64:
+      iprecision = GIMP_PRECISION_FLOAT;
+      type = babl_type ("double");
+      datamax = 1.0;
+      replacetransform = 1.0 / 255.0;
+      break;
+    default:
+      return -1;
+    }
+
   if (ncompose == 2)
     {
       itype = GIMP_GRAY;
       dtype = GIMP_GRAYA_IMAGE;
+      format = babl_format_new (babl_model ("Y'A"),
+                                type,
+                                babl_component ("Y'"),
+                                babl_component ("A"),
+                                NULL);
     }
   else if (ncompose == 3)
     {
       itype = GIMP_RGB;
       dtype = GIMP_RGB_IMAGE;
+      format = babl_format_new (babl_model ("R'G'B'"),
+                                type,
+                                babl_component ("R'"),
+                                babl_component ("G'"),
+                                babl_component ("B'"),
+                                NULL);
     }
   else if (ncompose == 4)
     {
       itype = GIMP_RGB;
       dtype = GIMP_RGBA_IMAGE;
+      format = babl_format_new (babl_model ("R'G'B'A"),
+                                type,
+                                babl_component ("R'"),
+                                babl_component ("G'"),
+                                babl_component ("B'"),
+                                babl_component ("A"),
+                                NULL);
     }
   else
     {
       ncompose = 1;
       itype = GIMP_GRAY;
       dtype = GIMP_GRAY_IMAGE;
+      format = babl_format_new (babl_model ("Y'"),
+                                type,
+                                babl_component ("Y'"),
+                                NULL);
     }
 
-  image_ID = create_new_image (filename, picnum, width, height, itype, dtype,
+  image_ID = create_new_image (filename, picnum, width, height, itype, dtype, iprecision,
                                &layer_ID, &buffer);
 
   tile_height = gimp_tile_height ();
 
-  data = g_malloc (tile_height * width * ncompose);
+  data = g_malloc (tile_height * width * ncompose * hdulist->bpp);
   if (data == NULL)
     return -1;
 
-  data_end = data + tile_height * width * ncompose;
+  data_end = data + tile_height * width * ncompose * hdulist->bpp;
 
   /* If the transformation from pixel value to data value has been
    * specified, use it
@@ -614,9 +678,9 @@ load_fits (const gchar *filename,
     }
 
   trans.datamin     = 0.0;
-  trans.datamax     = 255.0;
-  trans.replacement = plvals.replace;
-  trans.dsttyp      = 'c';
+  trans.datamax     = datamax;
+  trans.replacement = plvals.replace * replacetransform;
+  trans.dsttyp      = 'k';
 
   /* FITS stores images with bottom row first. Therefore we have to
    * fill the image from bottom to top.
@@ -624,13 +688,13 @@ load_fits (const gchar *filename,
 
   if (ncompose == 1)
     {
-      dest = data + tile_height * width;
+      dest = data + tile_height * width * hdulist->bpp;
       scan_lines = 0;
 
       for (i = 0; i < height; i++)
         {
           /* Read FITS line */
-          dest -= width;
+          dest -= width * hdulist->bpp;
           if (fits_read_pixel (ifp, hdulist, width, &trans, dest) != width)
             {
               err = 1;
@@ -647,27 +711,28 @@ load_fits (const gchar *filename,
               gegl_buffer_set (buffer,
                                GEGL_RECTANGLE (0, height - i - 1,
                                                width, scan_lines), 0,
-                               NULL, dest, GEGL_AUTO_ROWSTRIDE);
+                               format, dest, GEGL_AUTO_ROWSTRIDE);
 
               scan_lines = 0;
-              dest = data + tile_height * width;
+              dest = data + tile_height * width * hdulist->bpp;
             }
 
           if (err)
             break;
         }
     }
+  /* XXX: Needs to be ported to high bit depths */
   else   /* multiple images to compose */
     {
       gint channel;
 
-      linebuf = g_malloc (width);
+      linebuf = g_malloc (width * hdulist->bpp);
       if (linebuf == NULL)
         return -1;
 
       for (channel = 0; channel < ncompose; channel++)
         {
-          dest = data + tile_height * width * ncompose + channel;
+          dest = data + tile_height * width * hdulist->bpp * ncompose + channel;
           scan_lines = 0;
 
           for (i = 0; i < height; i++)
@@ -683,12 +748,12 @@ load_fits (const gchar *filename,
                   gegl_buffer_get (buffer,
                                    GEGL_RECTANGLE (0, height - i - max_scan,
                                                    width, max_scan), 1.0,
-                                   NULL, data_end - max_scan * width * ncompose,
+                                   format, data_end - max_scan * width * hdulist->bpp * ncompose,
                                    GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
                 }
 
               /* Read FITS scanline */
-              dest -= width * ncompose;
+              dest -= width * ncompose * hdulist->bpp;
               if (fits_read_pixel (ifp, hdulist, width, &trans, linebuf) != width)
                 {
                   err = 1;
@@ -698,10 +763,11 @@ load_fits (const gchar *filename,
               src = linebuf;
               while (j--)
                 {
-                  *dest = *(src++);
-                  dest += ncompose;
+                  memcpy (dest, src, hdulist->bpp);
+                  src += hdulist->bpp;
+                  dest += ncompose * hdulist->bpp;
                 }
-              dest -= width * ncompose;
+              dest -= width * ncompose * hdulist->bpp;
               scan_lines++;
 
               if ((i % 20) == 0)
@@ -713,10 +779,10 @@ load_fits (const gchar *filename,
                   gegl_buffer_set (buffer,
                                    GEGL_RECTANGLE (0, height - i - 1,
                                                    width, scan_lines), 0,
-                                   NULL, dest - channel, GEGL_AUTO_ROWSTRIDE);
+                                   format, dest - channel * hdulist->bpp, GEGL_AUTO_ROWSTRIDE);
 
                   scan_lines = 0;
-                  dest = data + tile_height * width * ncompose + channel;
+                  dest = data + tile_height * width * ncompose * hdulist->bpp + channel * hdulist->bpp;
                 }
 
               if (err)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]