[gimp] Bug 159947 - saving 1bpp PCX Files



commit 8d4642f4bad38249d17cf977abbea15c76998193
Author: Nikc M <nikc gimp gmail com>
Date:   Wed May 10 07:56:28 2017 -0400

    Bug 159947 - saving 1bpp PCX Files
    
    Allows saving 1bpp and 4bpp indexed PCX files based on number of colors
    used in image. Also provides ability to load additional PCX formats:
    2bpp, 2 planes 1bpp, 3 planes 1bpp, 4bpp.

 plug-ins/common/file-pcx.c |  295 ++++++++++++++++++++++++++++++++++---------
 1 files changed, 233 insertions(+), 62 deletions(-)
---
diff --git a/plug-ins/common/file-pcx.c b/plug-ins/common/file-pcx.c
index 56267d7..a95c8de 100644
--- a/plug-ins/common/file-pcx.c
+++ b/plug-ins/common/file-pcx.c
@@ -40,57 +40,72 @@
 
 /* Declare local functions.  */
 
-static void   query      (void);
-static void   run        (const gchar      *name,
-                          gint              nparams,
-                          const GimpParam  *param,
-                          gint             *nreturn_vals,
-                          GimpParam       **return_vals);
-
-static gint32 load_image (const gchar      *filename,
-                          GError          **error);
-
-static void   load_1     (FILE             *fp,
-                          gint              width,
-                          gint              height,
-                          guchar           *buf,
-                          guint16           bytes);
-static void   load_4     (FILE             *fp,
-                          gint              width,
-                          gint              height,
-                          guchar           *buf,
-                          guint16           bytes);
-static void   load_8     (FILE             *fp,
-                          gint              width,
-                          gint              height,
-                          guchar           *buf,
-                          guint16           bytes);
-static void   load_24    (FILE             *fp,
-                          gint              width,
-                          gint              height,
-                          guchar           *buf,
-                          guint16           bytes);
-static void   readline   (FILE             *fp,
-                          guchar           *buf,
-                          gint              bytes);
-
-static gint   save_image (const gchar      *filename,
-                          gint32            image,
-                          gint32            layer,
-                          GError          **error);
-
-static void   save_8     (FILE             *fp,
-                          gint              width,
-                          gint              height,
-                          const guchar     *buf);
-static void   save_24    (FILE             *fp,
-                          gint              width,
-                          gint              height,
-                          const guchar     *buf);
-static void   writeline  (FILE             *fp,
-                          const guchar     *buf,
-                          gint              bytes);
-
+static void   query            (void);
+static void   run              (const gchar      *name,
+                                gint              nparams,
+                                const GimpParam  *param,
+                                gint             *nreturn_vals,
+                                GimpParam       **return_vals);
+
+static gint32 load_image       (const gchar      *filename,
+                                GError          **error);
+
+static void   load_1           (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                guchar           *buf,
+                                guint16           bytes);
+static void   load_4           (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                guchar           *buf,
+                                guint16           bytes);
+static void   load_by_bpp      (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                gint              bpp,
+                                guchar           *buf,
+                                guint16           bytes);
+static void   load_by_plane    (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                gint              plane,
+                                guchar           *buf,
+                                guint16           bytes);
+static void   load_8           (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                guchar           *buf,
+                                guint16           bytes);
+static void   load_24          (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                guchar           *buf,
+                                guint16           bytes);
+static void   readline         (FILE             *fp,
+                                guchar           *buf,
+                                gint              bytes);
+
+static gint   save_image       (const gchar      *filename,
+                                gint32            image,
+                                gint32            layer,
+                                GError          **error);
+static void   save_less_than_8 (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                const gint        bpp,
+                                const guchar       *buf);
+static void   save_8           (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                const guchar     *buf);
+static void   save_24          (FILE             *fp,
+                                gint              width,
+                                gint              height,
+                                const guchar     *buf);
+static void   writeline        (FILE             *fp,
+                                const guchar     *buf,
+                                gint              bytes);
 
 const GimpPlugInInfo PLUG_IN_INFO =
 {
@@ -460,12 +475,36 @@ load_image (const gchar  *filename,
       load_1 (fd, width, height, dest, bytesperline);
       gimp_image_set_colormap (image, mono, 2);
     }
+  else if (pcx_header.planes == 2 && pcx_header.bpp == 1)
+    {
+      dest = g_new (guchar, ((gsize) width) * height);
+      load_by_plane (fd, width, height, 2, dest, bytesperline);
+      gimp_image_set_colormap (image, pcx_header.colormap, 16);
+    }
+  else if (pcx_header.planes == 1 && pcx_header.bpp == 2)
+    {
+      dest = g_new (guchar, ((gsize) width) * height);
+      load_by_bpp (fd, width, height, 2, dest, bytesperline);
+      gimp_image_set_colormap (image, pcx_header.colormap, 16);
+    }
+  else if (pcx_header.planes == 3 && pcx_header.bpp == 1)
+    {
+      dest = g_new (guchar, ((gsize) width) * height);
+      load_by_plane (fd, width, height, 3, dest, bytesperline);
+      gimp_image_set_colormap (image, pcx_header.colormap, 16);
+    }
   else if (pcx_header.planes == 4 && pcx_header.bpp == 1)
     {
       dest = g_new (guchar, ((gsize) width) * height);
       load_4 (fd, width, height, dest, bytesperline);
       gimp_image_set_colormap (image, pcx_header.colormap, 16);
     }
+  else if (pcx_header.planes == 1 && pcx_header.bpp == 4)
+    {
+      dest = g_new (guchar, ((gsize) width) * height);
+      load_by_bpp (fd, width, height, 4, dest, bytesperline);
+      gimp_image_set_colormap (image, pcx_header.colormap, 16);
+    }
   else if (pcx_header.planes == 1 && pcx_header.bpp == 8)
     {
       dest = g_new (guchar, ((gsize) width) * height);
@@ -600,6 +639,68 @@ load_4 (FILE    *fp,
 }
 
 static void
+load_by_bpp (FILE    *fp,
+            gint     width,
+            gint     height,
+            gint     bpp,
+            guchar  *buf,
+            guint16  bytes)
+{
+  gint    x, y;
+  guchar *line = g_new (guchar, bytes);
+  gint real_bpp = bpp - 1;
+  gint current_bit = 0;
+
+  for (y = 0; y < height; buf += width, ++y)
+    {
+      readline (fp, line, bytes);
+      for (x = 0; x < width; ++x)
+        {
+          buf[x] = 0;
+          for(int c = 0; c < bpp; c++)
+            {
+              current_bit = bpp * x + c; 
+              if (line[current_bit / 8] & (128 >> (current_bit % 8)))
+                buf[x] += (1 << (real_bpp - c));
+            }
+        }
+      gimp_progress_update ((double) y / (double) height);
+    }
+
+  g_free (line);
+}
+
+static void
+load_by_plane (FILE    *fp,
+               gint     width,
+               gint     height,
+               gint     plane,
+               guchar  *buf,
+               guint16  bytes)
+{
+  gint    x, y, c;
+  guchar *line = g_new (guchar, bytes);
+
+  for (y = 0; y < height; buf += width, ++y)
+    {
+      for (x = 0; x < width; ++x)
+        buf[x] = 0;
+      for (c = 0; c < plane; ++c)
+        {
+          readline(fp, line, bytes);
+          for (x = 0; x < width; ++x)
+            {
+              if (line[x / 8] & (128 >> (x % 8)))
+                buf[x] += (1 << c);
+            }
+        }
+      gimp_progress_update ((double) y / (double) height);
+    }
+
+  g_free (line);
+}
+
+static void
 readline (FILE   *fp,
           guchar *buf,
           gint    bytes)
@@ -669,12 +770,36 @@ save_image (const gchar  *filename,
   switch (drawable_type)
     {
     case GIMP_INDEXED_IMAGE:
-      cmap                    = gimp_image_get_colormap (image, &colors);
-      pcx_header.bpp          = 8;
-      pcx_header.planes       = 1;
+      cmap                          = gimp_image_get_colormap (image, &colors);
+      if(colors > 16)
+        {
+          pcx_header.bpp            = 8;
+          pcx_header.planes         = 1;
+          pcx_header.bytesperline   = GUINT16_TO_LE (width);
+        }
+      else if(colors > 2)
+        {
+          pcx_header.bpp            = 4;
+          pcx_header.planes         = 1;
+          pcx_header.bytesperline   = GUINT16_TO_LE ((width + 1) / 2);
+        }
+      else
+       {
+          pcx_header.bpp            = 1;
+          pcx_header.planes         = 1;
+          pcx_header.bytesperline   = GUINT16_TO_LE ((width + 7) / 8);
+        }
       pcx_header.color        = GUINT16_TO_LE (1);
-      pcx_header.bytesperline = GUINT16_TO_LE (width);
       format                  = NULL;
+  
+      if(colors <= 16)
+        {
+        for(i = 0; i < colors * 3; i++)
+          {
+            pcx_header.colormap[i] = cmap[i];
+          }
+        }
+  
       break;
 
     case GIMP_RGB_IMAGE:
@@ -756,14 +881,21 @@ save_image (const gchar  *filename,
   switch (drawable_type)
     {
     case GIMP_INDEXED_IMAGE:
-      save_8 (fp, width, height, pixels);
-      fputc (0x0c, fp);
-      fwrite (cmap, colors, 3, fp);
-      for (i = colors; i < 256; i++)
+      if(colors > 16)
         {
-          fputc (0, fp);
-          fputc (0, fp);
-          fputc (0, fp);
+        save_8 (fp, width, height, pixels);
+        fputc (0x0c, fp);
+        fwrite (cmap, colors, 3, fp);
+        for (i = colors; i < 256; i++)
+          {
+            fputc (0, fp);
+            fputc (0, fp);
+            fputc (0, fp);
+          }
+        }
+      else /* Covers 1 and 4 bpp */
+        {
+          save_less_than_8 (fp, width, height, pcx_header.bpp, pixels);
         }
       break;
 
@@ -801,6 +933,45 @@ save_image (const gchar  *filename,
 }
 
 static void
+save_less_than_8 (FILE         *fp,
+                  gint          width,
+                  gint          height,
+                  const gint    bpp,
+                  const guchar *buf)
+{
+  const gint bit_limit     = (8 - bpp);
+  const gint buf_size      = width * height;
+  const gint line_end      = width - 1;
+  gint       j             = bit_limit;
+  gint       count         = 0;
+  guchar     byte_to_write = 0x00;
+  guchar    *line;
+
+  line = (guchar *) g_malloc (((width + 7) / 8) * bpp);
+
+  for(gint x = 0; x < buf_size; x++)
+    {
+      byte_to_write |= (buf[x] << j);
+      j -= bpp;
+
+      if(j < 0 || (x % width == line_end))
+        {
+          line[count] = byte_to_write;
+          count++;
+          byte_to_write = 0x00;
+          j = bit_limit;
+
+          if((x % width == line_end))
+            {
+              writeline (fp, line, count);
+              count = 0;
+              gimp_progress_update ((double) x / (double) buf_size);
+            } 
+        }
+    }
+}
+
+static void
 save_8 (FILE         *fp,
         gint          width,
         gint          height,


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