[gimp] file-xwd: support 32bit (ARGB) xwd import



commit cfe5dd8bd4b9306e2fce6360a1301057d1bb6eb7
Author: KÅvÃgÃ, ZoltÃn <DirtY iCE hu gmail com>
Date:   Tue Aug 7 15:56:58 2012 +0200

    file-xwd: support 32bit (ARGB) xwd import
    
    No saving for now...

 plug-ins/common/file-xwd.c |  197 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 176 insertions(+), 21 deletions(-)
---
diff --git a/plug-ins/common/file-xwd.c b/plug-ins/common/file-xwd.c
index f91d757..445133e 100644
--- a/plug-ins/common/file-xwd.c
+++ b/plug-ins/common/file-xwd.c
@@ -31,7 +31,7 @@
  *          2       |    1,...,8   |       8
  *          2       |    1,...,16  |      16
  *          2       |    1,...,24  |      24
- *          2       |    1,...,24  |      32
+ *          2       |    1,...,32  |      32
  */
 /* Event history:
  * PK = Peter Kirchgessner, ME = Mattias Engdegå
@@ -154,6 +154,7 @@ static gint32 create_new_image    (const gchar      *filename,
                                    guint             width,
                                    guint             height,
                                    GimpImageBaseType type,
+                                   GimpImageType     gdtype,
                                    gint32           *layer_ID,
                                    GimpDrawable    **drawable,
                                    GimpPixelRgn     *pixel_rgn);
@@ -188,6 +189,10 @@ static gint32 load_xwd_f2_d24_b32 (const gchar *,
                                    L_XWDFILEHEADER *,
                                    L_XWDCOLOR *,
                                    GError **);
+static gint32 load_xwd_f2_d32_b32 (const gchar *,
+                                   FILE *,
+                                   L_XWDFILEHEADER *,
+                                   L_XWDCOLOR *);
 static gint32 load_xwd_f1_d24_b1  (const gchar *,
                                    FILE *,
                                    L_XWDFILEHEADER *,
@@ -565,6 +570,10 @@ load_image (const gchar  *filename,
           image_ID = load_xwd_f2_d24_b32 (filename, ifp, &xwdhdr, xwdcolmap,
                                           error);
         }
+      else if ((depth <= 32) && (bpp == 32))
+        {
+          image_ID = load_xwd_f2_d32_b32 (filename, ifp, &xwdhdr, xwdcolmap);
+        }
       break;
     }
   gimp_progress_update (1.0);
@@ -1186,28 +1195,12 @@ create_new_image (const gchar         *filename,
                   guint                width,
                   guint                height,
                   GimpImageBaseType    type,
+                  GimpImageType        gdtype,
                   gint32              *layer_ID,
                   GimpDrawable       **drawable,
                   GimpPixelRgn        *pixel_rgn)
 {
   gint32        image_ID;
-  GimpImageType gdtype;
-
-  switch (type)
-    {
-    case GIMP_GRAY:
-      gdtype = GIMP_GRAY_IMAGE;
-      break;
-    case GIMP_INDEXED:
-      gdtype = GIMP_INDEXED_IMAGE;
-      break;
-    case GIMP_RGB:
-      gdtype = GIMP_RGB_IMAGE;
-      break;
-    default:
-      g_warning ("Unknown image type");
-      return -1;
-    }
 
   image_ID = gimp_image_new (width, height, type);
   gimp_image_set_filename (image_ID, filename);
@@ -1253,7 +1246,8 @@ load_xwd_f2_d1_b1 (const gchar     *filename,
   height = xwdhdr->l_pixmap_height;
 
   image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
-                               &layer_ID, &drawable, &pixel_rgn);
+                               GIMP_INDEXED_IMAGE, &layer_ID, &drawable,
+                               &pixel_rgn);
 
   tile_height = gimp_tile_height ();
   data = g_malloc (tile_height * width);
@@ -1408,6 +1402,7 @@ load_xwd_f2_d8_b8 (const gchar     *filename,
 
   image_ID = create_new_image (filename, width, height,
                                grayscale ? GIMP_GRAY : GIMP_INDEXED,
+                               grayscale ? GIMP_GRAY_IMAGE : GIMP_INDEXED_IMAGE,
                                &layer_ID, &drawable, &pixel_rgn);
 
   tile_height = gimp_tile_height ();
@@ -1497,7 +1492,8 @@ load_xwd_f2_d16_b16 (const gchar     *filename,
   height = xwdhdr->l_pixmap_height;
 
   image_ID = create_new_image (filename, width, height, GIMP_RGB,
-                               &layer_ID, &drawable, &pixel_rgn);
+                               GIMP_RGB_IMAGE, &layer_ID, &drawable,
+                               &pixel_rgn);
 
   tile_height = gimp_tile_height ();
   data = g_malloc (tile_height * width * 3);
@@ -1695,7 +1691,8 @@ load_xwd_f2_d24_b32 (const gchar      *filename,
     }
 
   image_ID = create_new_image (filename, width, height, GIMP_RGB,
-                               &layer_ID, &drawable, &pixel_rgn);
+                               GIMP_RGB_IMAGE, &layer_ID, &drawable,
+                               &pixel_rgn);
 
   tile_height = gimp_tile_height ();
   data = g_malloc (tile_height * width * 3);
@@ -1836,6 +1833,163 @@ load_xwd_f2_d24_b32 (const gchar      *filename,
   return err ? -1 : image_ID;
 }
 
+/* Load XWD with pixmap_format 2, pixmap_depth up to 32, bits_per_pixel 32 */
+
+static gint32
+load_xwd_f2_d32_b32 (const gchar     *filename,
+                     FILE            *ifp,
+                     L_XWDFILEHEADER *xwdhdr,
+                     L_XWDCOLOR      *xwdcolmap)
+{
+  register guchar *dest, lsbyte_first;
+  gint             width, height, linepad, i, j, c0, c1, c2, c3;
+  gint             tile_height, scan_lines;
+  L_CARD32         pixelval;
+  gint             red, green, blue, alpha, ncols;
+  gint             maxred, maxgreen, maxblue, maxalpha;
+  gulong           redmask, greenmask, bluemask, alphamask;
+  guint            redshift, greenshift, blueshift, alphashift;
+  guchar           redmap[256], greenmap[256], bluemap[256], alphamap[256];
+  guchar          *data;
+  PIXEL_MAP        pixel_map;
+  gint             err = 0;
+  gint32           layer_ID, image_ID;
+  GimpPixelRgn     pixel_rgn;
+  GimpDrawable    *drawable;
+
+#ifdef XWD_DEBUG
+  printf ("load_xwd_f2_d32_b32 (%s)\n", filename);
+#endif
+
+  width  = xwdhdr->l_pixmap_width;
+  height = xwdhdr->l_pixmap_height;
+
+  image_ID = create_new_image (filename, width, height, GIMP_RGB,
+                               GIMP_RGBA_IMAGE, &layer_ID, &drawable,
+                               &pixel_rgn);
+
+  tile_height = gimp_tile_height ();
+  data = g_malloc (tile_height * width * 4);
+
+  redmask   = xwdhdr->l_red_mask;
+  greenmask = xwdhdr->l_green_mask;
+  bluemask  = xwdhdr->l_blue_mask;
+
+  if (redmask   == 0) redmask   = 0xff0000;
+  if (greenmask == 0) greenmask = 0x00ff00;
+  if (bluemask  == 0) bluemask  = 0x0000ff;
+  alphamask = 0xffffffff & ~(redmask | greenmask | bluemask);
+
+  /* How to shift RGB to be right aligned ? */
+  /* (We rely on the the mask bits are grouped and not mixed) */
+  redshift = greenshift = blueshift = alphashift = 0;
+
+  while (((1 << redshift)   & redmask)   == 0) redshift++;
+  while (((1 << greenshift) & greenmask) == 0) greenshift++;
+  while (((1 << blueshift)  & bluemask)  == 0) blueshift++;
+  while (((1 << alphashift) & alphamask) == 0) alphashift++;
+
+  /* The bits_per_rgb may not be correct. Use redmask instead */
+
+  maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
+  maxred = (1 << maxred) - 1;
+
+  maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
+  maxgreen = (1 << maxgreen) - 1;
+
+  maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
+  maxblue = (1 << maxblue) - 1;
+
+  maxalpha = 0; while (alphamask >> (alphashift + maxalpha)) maxalpha++;
+  maxalpha = (1 << maxalpha) - 1;
+
+  /* Set map-arrays for red, green, blue */
+  for (red = 0; red <= maxred; red++)
+    redmap[red] = (red * 255) / maxred;
+  for (green = 0; green <= maxgreen; green++)
+    greenmap[green] = (green * 255) / maxgreen;
+  for (blue = 0; blue <= maxblue; blue++)
+    bluemap[blue] = (blue * 255) / maxblue;
+  for (alpha = 0; alpha <= maxalpha; alpha++)
+    alphamap[alpha] = (alpha * 255) / maxalpha;
+
+  ncols = xwdhdr->l_colormap_entries;
+  if (xwdhdr->l_ncolors < ncols)
+    ncols = xwdhdr->l_ncolors;
+
+  set_pixelmap (ncols, xwdcolmap, &pixel_map);
+
+  /* What do we have to consume after a line has finished ? */
+  linepad =   xwdhdr->l_bytes_per_line
+    - (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
+  if (linepad < 0) linepad = 0;
+
+  lsbyte_first = (xwdhdr->l_byte_order == 0);
+
+  dest = data;
+  scan_lines = 0;
+
+  for (i = 0; i < height; i++)
+    {
+      for (j = 0; j < width; j++)
+        {
+          c0 = getc (ifp);
+          c1 = getc (ifp);
+          c2 = getc (ifp);
+          c3 = getc (ifp);
+          if (c3 < 0)
+            {
+              err = 1;
+              break;
+            }
+          if (lsbyte_first)
+            pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
+          else
+            pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
+
+          if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
+            {
+              /* FIXME: is it always transparent or encoded in an unknown way? */
+              *(dest+3) = 0x00;
+              dest += 4;
+            }
+          else
+            {
+              *(dest++) = redmap[(pixelval & redmask) >> redshift];
+              *(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
+              *(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
+              *(dest++) = alphamap[(pixelval & alphamask) >> alphashift];
+            }
+        }
+      scan_lines++;
+
+      if (err)
+        break;
+
+      for (j = 0; j < linepad; j++)
+        getc (ifp);
+
+      if ((i % 20) == 0)
+        gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
+
+      if ((scan_lines == tile_height) || ((i+1) == height))
+        {
+          gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
+                                   width, scan_lines);
+          scan_lines = 0;
+          dest = data;
+        }
+    }
+
+  g_free (data);
+
+  if (err)
+    g_message (_("EOF encountered on reading"));
+
+  gimp_drawable_flush (drawable);
+
+  return err ? -1 : image_ID;
+}
 
 /* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
 
@@ -1943,6 +2097,7 @@ load_xwd_f1_d24_b1 (const gchar      *filename,
 
   image_ID = create_new_image (filename, width, height,
                                indexed ? GIMP_INDEXED : GIMP_RGB,
+                               indexed ? GIMP_INDEXED_IMAGE : GIMP_RGB_IMAGE,
                                &layer_ID, &drawable, &pixel_rgn);
 
   tile_height = gimp_tile_height ();



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