[gimp] plug-ins: support more cases of grayscale raw data.



commit 55790d7bb26e5367181d68a051bb2dfaa4009620
Author: Jehan <jehan girinstud io>
Date:   Mon Jun 20 19:02:35 2022 +0200

    plug-ins: support more cases of grayscale raw data.
    
    - rename raw_load_gray16() into raw_load_gray_8_plus() and make it
      handle all full-byte grayscale data. Move 8-bit grayscale data to use
      this function as well.
    - As a consequence of the previous point, we can also easily support
      32-bit grayscale images (little/big endian, signed/unsigned).
    - Make preview image code more generic as well.
    
    Also I improve a bit code from previous commit in raw_load_rgb565(). The
    allocated and read code didn't need to be the size of the full line
    stride. Just the tile rectangle width was enough.

 plug-ins/common/file-raw-data.c | 195 ++++++++++++++++++++++++++--------------
 1 file changed, 128 insertions(+), 67 deletions(-)
---
diff --git a/plug-ins/common/file-raw-data.c b/plug-ins/common/file-raw-data.c
index c829b04595..177cd41dd8 100644
--- a/plug-ins/common/file-raw-data.c
+++ b/plug-ins/common/file-raw-data.c
@@ -96,10 +96,16 @@ typedef enum
   RAW_GRAY_8BPP,
   RAW_INDEXED,      /* Indexed image */
   RAW_INDEXEDA,     /* Indexed image with an Alpha channel */
+
   RAW_GRAY_16BPP_BE,
   RAW_GRAY_16BPP_LE,
   RAW_GRAY_16BPP_SBE,
   RAW_GRAY_16BPP_SLE,
+
+  RAW_GRAY_32BPP_BE,
+  RAW_GRAY_32BPP_LE,
+  RAW_GRAY_32BPP_SBE,
+  RAW_GRAY_32BPP_SLE,
 } RawType;
 
 typedef enum
@@ -160,9 +166,10 @@ static gboolean         raw_load_standard    (RawGimpData          *data,
                                               gint                  height,
                                               gint                  offset,
                                               gint                  bpp);
-static gboolean         raw_load_gray16      (RawGimpData          *data,
+static gboolean         raw_load_gray_8_plus (RawGimpData          *data,
                                               gint                  width,
                                               gint                  height,
+                                              gint                  bpp,
                                               gint                  offset,
                                               RawType               type);
 static gboolean         raw_load_gray        (RawGimpData          *data,
@@ -330,7 +337,7 @@ raw_create_procedure (GimpPlugIn  *plug_in,
       GIMP_PROC_ARG_INT (procedure, "pixel-format",
                          "Pixel _format",
                          "How color pixel data are stored { RAW_PLANAR_CONTIGUOUS (0), RAW_PLANAR_SEPARATE 
(1) }",
-                         RAW_RGB, RAW_GRAY_16BPP_SLE, RAW_RGB,
+                         RAW_RGB, RAW_GRAY_32BPP_SLE, RAW_RGB,
                          G_PARAM_READWRITE);
 
       /* Properties for palette data. */
@@ -721,58 +728,71 @@ raw_load_standard (RawGimpData *data,
 }
 
 static gboolean
-raw_load_gray16 (RawGimpData *data,
-                 gint         width,
-                 gint         height,
-                 gint         offset,
-                 RawType      type)
+raw_load_gray_8_plus (RawGimpData *data,
+                      gint         width,
+                      gint         height,
+                      gint         bpp,
+                      gint         offset,
+                      RawType      type)
 {
-  guint16 *in_raw = NULL;
-  guint16 *out_raw = NULL;
-  gsize    in_size;
-  gsize    out_size;
-  gsize    i;
+  GeglBufferIterator *iter;
+  guchar             *in = NULL;
+  gint                input_stride;
 
-  in_size  = width * height;
-  out_size = width * height * 3 * sizeof (*out_raw);
+  input_stride = width * bpp;
 
-  in_raw = g_try_malloc (in_size * sizeof (*in_raw));
-  if (! in_raw)
-    return FALSE;
+  iter = gegl_buffer_iterator_new (data->buffer, GEGL_RECTANGLE (0, 0, width, height),
+                                   0, NULL, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1);
 
-  out_raw = g_try_malloc0 (out_size);
-  if (! out_raw)
+  while (gegl_buffer_iterator_next (iter))
     {
-      g_free (in_raw);
-      return FALSE;
-    }
-
-  raw_read_row (data->fp, (guchar*) in_raw, offset,
-                in_size * sizeof (*in_raw));
+      const GeglRectangle *roi = &iter->items[0].roi;
+      guchar              *out = iter->items[0].data;
+      gint                 line;
+      gint                 in_size;
 
-  for (i = 0; i < in_size; i++)
-    {
-      gint pixel_val;
-
-      if (type == RAW_GRAY_16BPP_BE)
-        pixel_val = GUINT16_FROM_BE (in_raw[i]);
-      else if (type == RAW_GRAY_16BPP_LE)
-        pixel_val = GUINT16_FROM_LE (in_raw[i]);
-      else if (type == RAW_GRAY_16BPP_SBE)
-        pixel_val = GINT16_FROM_BE (in_raw[i]) - G_MININT16;
-      else /* if (type == RAW_GRAY_16BPP_SLE)*/
-        pixel_val = GINT16_FROM_LE (in_raw[i]) - G_MININT16;
-
-      out_raw[3 * i + 0] = pixel_val;
-      out_raw[3 * i + 1] = pixel_val;
-      out_raw[3 * i + 2] = pixel_val;
+      in_size  = roi->width * bpp;
+      in = g_realloc (in, in_size);
+      for (line = 0; line < roi->height; line++)
+        {
+          raw_read_row (data->fp, in,
+                        offset + ((roi->y + line) * input_stride) + roi->x * bpp,
+                        in_size);
+          for (gint x = 0; x < roi->width; x++)
+            {
+              gint pixel_val;
+
+              if (type == RAW_GRAY_8BPP)
+                pixel_val = (gint) in[x];
+              else if (type == RAW_GRAY_16BPP_BE)
+                pixel_val = GUINT16_FROM_BE (((guint16 *) in)[x]);
+              else if (type == RAW_GRAY_16BPP_LE)
+                pixel_val = GUINT16_FROM_LE (((guint16 *) in)[x]);
+              else if (type == RAW_GRAY_16BPP_SBE)
+                pixel_val = GINT16_FROM_BE (((guint16 *) in)[x]) - G_MININT16;
+              else if (type == RAW_GRAY_16BPP_SLE)
+                pixel_val = GINT16_FROM_LE (((guint16 *) in)[x]) - G_MININT16;
+              else if (type == RAW_GRAY_32BPP_BE)
+                pixel_val = GUINT32_FROM_BE (((guint32 *) in)[x]);
+              else if (type == RAW_GRAY_32BPP_LE)
+                pixel_val = GUINT32_FROM_LE (((guint32 *) in)[x]);
+              else if (type == RAW_GRAY_32BPP_SBE)
+                pixel_val = GINT32_FROM_BE (((guint32 *) in)[x]) - G_MININT32;
+              else /* if (type == RAW_GRAY_32BPP_SLE) */
+                pixel_val = GINT32_FROM_LE (((guint32 *) in)[x]) - G_MININT32;
+
+              if (bpp == 4)
+                ((guint32*) out)[x] = (guint32) pixel_val;
+              else if (bpp == 2)
+                ((guint16*) out)[x] = (guint16) pixel_val;
+              else
+                out[x] = (gchar) pixel_val;
+            }
+          out += in_size;
+        }
     }
 
-  gegl_buffer_set (data->buffer, GEGL_RECTANGLE (0, 0, width, height),
-                   0, NULL, out_raw, GEGL_AUTO_ROWSTRIDE);
-
-  g_free (in_raw);
-  g_free (out_raw);
+  g_free (in);
 
   return TRUE;
 }
@@ -880,12 +900,12 @@ raw_load_rgb565 (RawGimpData *data,
       guchar              *out = iter->items[0].data;
       gint                 line;
 
-      in = g_realloc (in, iter->length * 2);
+      in = g_realloc (in, roi->width * 2);
       for (line = 0; line < roi->height; line++)
         {
           raw_read_row (data->fp, (guchar *) in,
                         offset + ((roi->y + line) * width * 2) + roi->x * 2,
-                        iter->length * 2);
+                        roi->width * 2);
           rgb_565_to_888 (in, out + line * roi->width * 3, roi->width, type);
         }
     }
@@ -1276,6 +1296,13 @@ get_bpp (GimpProcedureConfig *config,
         case RAW_GRAY_16BPP_SLE:
           *bpp   = 2;
           break;
+
+        case RAW_GRAY_32BPP_BE:
+        case RAW_GRAY_32BPP_LE:
+        case RAW_GRAY_32BPP_SBE:
+        case RAW_GRAY_32BPP_SLE:
+          *bpp   = 4;
+          break;
         }
     }
 }
@@ -1452,8 +1479,8 @@ load_image (GFile                *file,
       break;
     case RAW_GRAY_8BPP:
       bpp   = 1;
-      ltype = GIMP_RGB_IMAGE;
-      itype = GIMP_RGB;
+      ltype = GIMP_GRAY_IMAGE;
+      itype = GIMP_GRAY;
       break;
 
     case RAW_INDEXED:         /* Indexed */
@@ -1473,8 +1500,17 @@ load_image (GFile                *file,
     case RAW_GRAY_16BPP_SBE:
     case RAW_GRAY_16BPP_SLE:
       bpp   = 2;
-      ltype = GIMP_RGB_IMAGE;
-      itype = GIMP_RGB;
+      ltype = GIMP_GRAY_IMAGE;
+      itype = GIMP_GRAY;
+      break;
+
+    case RAW_GRAY_32BPP_BE:
+    case RAW_GRAY_32BPP_LE:
+    case RAW_GRAY_32BPP_SBE:
+    case RAW_GRAY_32BPP_SLE:
+      bpp   = 4;
+      ltype = GIMP_GRAY_IMAGE;
+      itype = GIMP_GRAY;
       break;
     }
 
@@ -1482,7 +1518,10 @@ load_image (GFile                *file,
   if (height > (size / width / bpp * 8 / bitspp))
     height = size / width / bpp * 8 / bitspp;
 
-  if (pixel_format >= RAW_GRAY_16BPP_BE)
+  if (pixel_format >= RAW_GRAY_32BPP_BE)
+    data->image = gimp_image_new_with_precision (width, height, itype,
+                                                 GIMP_PRECISION_U32_NON_LINEAR);
+  else if (pixel_format >= RAW_GRAY_16BPP_BE)
     data->image = gimp_image_new_with_precision (width, height, itype,
                                                  GIMP_PRECISION_U16_NON_LINEAR);
   else
@@ -1522,9 +1561,6 @@ load_image (GFile                *file,
     case RAW_GRAY_4BPP:
       raw_load_gray (data, width, height, offset, bpp, bitspp);
       break;
-    case RAW_GRAY_8BPP:
-      raw_load_gray (data, width, height, offset, bpp, bitspp);
-      break;
 
     case RAW_INDEXED:
     case RAW_INDEXEDA:
@@ -1532,11 +1568,16 @@ load_image (GFile                *file,
       raw_load_standard (data, width, height, offset, bpp);
       break;
 
+    case RAW_GRAY_8BPP:
     case RAW_GRAY_16BPP_BE:
     case RAW_GRAY_16BPP_LE:
     case RAW_GRAY_16BPP_SBE:
     case RAW_GRAY_16BPP_SLE:
-      raw_load_gray16 (data, width, height, offset, pixel_format);
+    case RAW_GRAY_32BPP_BE:
+    case RAW_GRAY_32BPP_LE:
+    case RAW_GRAY_32BPP_SBE:
+    case RAW_GRAY_32BPP_SLE:
+      raw_load_gray_8_plus (data, width, height, bpp, offset, pixel_format);
       break;
     }
 
@@ -1862,31 +1903,47 @@ preview_update (GimpPreviewArea *preview,
     case RAW_GRAY_16BPP_LE:
     case RAW_GRAY_16BPP_SBE:
     case RAW_GRAY_16BPP_SLE:
+      bitspp = 16;
+    case RAW_GRAY_32BPP_BE:
+    case RAW_GRAY_32BPP_LE:
+    case RAW_GRAY_32BPP_SBE:
+    case RAW_GRAY_32BPP_SLE:
+      if (bitspp == 0)
+        bitspp = 32;
+
         {
-        guint16 *r_row = g_new (guint16, width);
-        guchar  *row   = g_malloc (width);
+        guchar *r_row = g_new (guchar, width * bitspp / 8);
+        guchar *row   = g_malloc (width);
 
         for (y = 0; y < height; y++)
           {
             gint j;
 
             pos = (offset + (y * width * 2));
-            mmap_read (preview_fd, (guchar*) r_row, 2 * width, pos, width);
+            mmap_read (preview_fd, (guchar*) r_row, (bitspp / 8) * width, pos, width);
 
             for (j = 0; j < width; j++)
               {
                 gint pixel_val;
 
                 if (pixel_format == RAW_GRAY_16BPP_BE)
-                  pixel_val = GUINT16_FROM_BE (r_row[j]);
+                  pixel_val = GUINT16_FROM_BE (((guint16 *) r_row)[j]);
                 else if (pixel_format == RAW_GRAY_16BPP_LE)
-                  pixel_val = GUINT16_FROM_LE (r_row[j]);
+                  pixel_val = GUINT16_FROM_LE (((guint16 *) r_row)[j]);
                 else if (pixel_format == RAW_GRAY_16BPP_SBE)
-                  pixel_val = GINT16_FROM_BE (r_row[j]) - G_MININT16;
-                else /* if (pixel_format == RAW_GRAY_16BPP_SLE)*/
-                  pixel_val = GINT16_FROM_LE (r_row[j]) - G_MININT16;
-
-                row[j] = pixel_val / 257;
+                  pixel_val = GINT16_FROM_BE (((guint16 *) r_row)[j]) - G_MININT16;
+                else if (pixel_format == RAW_GRAY_16BPP_SLE)
+                  pixel_val = GINT16_FROM_LE (((guint16 *) r_row)[j]) - G_MININT16;
+                else if (pixel_format == RAW_GRAY_32BPP_BE)
+                  pixel_val = GUINT32_FROM_BE (((guint32 *) r_row)[j]);
+                else if (pixel_format == RAW_GRAY_32BPP_LE)
+                  pixel_val = GUINT32_FROM_LE (((guint32 *) r_row)[j]);
+                else if (pixel_format == RAW_GRAY_32BPP_SBE)
+                  pixel_val = GINT32_FROM_BE (((guint32 *) r_row)[j]) - G_MININT32;
+                else /* if (pixel_format == RAW_GRAY_32BPP_SLE)*/
+                  pixel_val = GINT32_FROM_LE (((guint32 *) r_row)[j]) - G_MININT32;
+
+                row[j] = pixel_val / pow (2, bitspp - 8);
               }
 
             gimp_preview_area_draw (preview, 0, y, width, 1,
@@ -2141,6 +2198,10 @@ load_dialog (GFile         *file,
                                   _("Gray unsigned 16 bit Little Endian"), RAW_GRAY_16BPP_LE,
                                   _("Gray 16 bit Big Endian"),             RAW_GRAY_16BPP_SBE,
                                   _("Gray 16 bit Little Endian"),          RAW_GRAY_16BPP_SLE,
+                                  _("Gray unsigned 32 bit Big Endian"),    RAW_GRAY_32BPP_BE,
+                                  _("Gray unsigned 32 bit Little Endian"), RAW_GRAY_32BPP_LE,
+                                  _("Gray 32 bit Big Endian"),             RAW_GRAY_32BPP_SBE,
+                                  _("Gray 32 bit Little Endian"),          RAW_GRAY_32BPP_SLE,
                                   NULL);
       gimp_procedure_dialog_get_int_combo (GIMP_PROCEDURE_DIALOG (dialog),
                                            "pixel-format",


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