[gimp] Bug 674391 - Indexed colours not exported when save a .bmp



commit 56f065321ce42f907879dfa4a76e57de18b058eb
Author: Téo Mazars <teo mazars ensimag fr>
Date:   Sat Apr 13 17:16:56 2013 +0200

    Bug 674391 - Indexed colours not exported when save a .bmp
    
    It's about importing in fact.
    
    Parse BITMAPV4HEADER / BITMAPV5HEADER and use GIMP's BMP
    implementation instead of using gdk_pixbuf.
    
    Also, remove an old hack about 32bits bmp v3 + alpha. The alpha
    channel is already ignored in that case.

 plug-ins/file-bmp/bmp-read.c |  199 +++++++++++++++++++-----------------------
 1 files changed, 91 insertions(+), 108 deletions(-)
---
diff --git a/plug-ins/file-bmp/bmp-read.c b/plug-ins/file-bmp/bmp-read.c
index 335378e..27f8622 100644
--- a/plug-ins/file-bmp/bmp-read.c
+++ b/plug-ins/file-bmp/bmp-read.c
@@ -55,6 +55,58 @@ static gint32 ReadImage (FILE                  *fd,
                          GError               **error);
 
 
+static void
+setMasksDefault (gushort biBitCnt, Bitmap_Channel *masks)
+{
+  switch (biBitCnt)
+    {
+    case 32:
+      masks[0].mask     = 0x00ff0000;
+      masks[0].shiftin  = 16;
+      masks[0].max_value= (gfloat)255.0;
+      masks[1].mask     = 0x0000ff00;
+      masks[1].shiftin  = 8;
+      masks[1].max_value= (gfloat)255.0;
+      masks[2].mask     = 0x000000ff;
+      masks[2].shiftin  = 0;
+      masks[2].max_value= (gfloat)255.0;
+      masks[3].mask     = 0x00000000;
+      masks[3].shiftin  = 0;
+      masks[3].max_value= (gfloat)0.0;
+      break;
+    case 24:
+      masks[0].mask     = 0xff0000;
+      masks[0].shiftin  = 16;
+      masks[0].max_value= (gfloat)255.0;
+      masks[1].mask     = 0x00ff00;
+      masks[1].shiftin  = 8;
+      masks[1].max_value= (gfloat)255.0;
+      masks[2].mask     = 0x0000ff;
+      masks[2].shiftin  = 0;
+      masks[2].max_value= (gfloat)255.0;
+      masks[3].mask     = 0x0;
+      masks[3].shiftin  = 0;
+      masks[3].max_value= (gfloat)0.0;
+      break;
+    case 16:
+      masks[0].mask     = 0x7c00;
+      masks[0].shiftin  = 10;
+      masks[0].max_value= (gfloat)31.0;
+      masks[1].mask     = 0x03e0;
+      masks[1].shiftin  = 5;
+      masks[1].max_value= (gfloat)31.0;
+      masks[2].mask     = 0x001f;
+      masks[2].shiftin  = 0;
+      masks[2].max_value= (gfloat)31.0;
+      masks[3].mask     = 0x0;
+      masks[3].shiftin  = 0;
+      masks[3].max_value= (gfloat)0.0;
+      break;
+    default:
+      break;
+    }
+}
+
 static gint32
 ToL (const guchar *puffer)
 {
@@ -137,7 +189,7 @@ ReadBMP (const gchar  *name,
          GError      **error)
 {
   FILE     *fd;
-  guchar    buffer[64];
+  guchar    buffer[124];
   gint      ColormapSize, rowbytes, Maps;
   gboolean  Grey = FALSE;
   guchar    ColorMap[256][3];
@@ -257,7 +309,7 @@ ReadBMP (const gchar  *name,
 
       Bitmap_Head.biWidth   = ToL (&buffer[0x00]);      /* 12 */
       Bitmap_Head.biHeight  = ToL (&buffer[0x04]);      /* 16 */
-      Bitmap_Head.biPlanes  = ToS (&buffer[0x08]);       /* 1A */
+      Bitmap_Head.biPlanes  = ToS (&buffer[0x08]);      /* 1A */
       Bitmap_Head.biBitCnt  = ToS (&buffer[0x0A]);      /* 1C */
       Bitmap_Head.biCompr   = ToL (&buffer[0x0C]);      /* 1E */
       Bitmap_Head.biSizeIm  = ToL (&buffer[0x10]);      /* 22 */
@@ -290,55 +342,9 @@ ReadBMP (const gchar  *name,
         }
       else if (Bitmap_Head.biCompr == BI_RGB)
         {
-          switch (Bitmap_Head.biBitCnt)
-            {
-            case 32:
-              masks[0].mask     = 0x00ff0000;
-              masks[0].shiftin  = 16;
-              masks[0].max_value= (gfloat)255.0;
-              masks[1].mask     = 0x0000ff00;
-              masks[1].shiftin  = 8;
-              masks[1].max_value= (gfloat)255.0;
-              masks[2].mask     = 0x000000ff;
-              masks[2].shiftin  = 0;
-              masks[2].max_value= (gfloat)255.0;
-              masks[3].mask     = 0x00000000;
-              masks[3].shiftin  = 0;
-              masks[3].max_value= (gfloat)0.0;
-              break;
-            case 24:
-              masks[0].mask     = 0xff0000;
-              masks[0].shiftin  = 16;
-              masks[0].max_value= (gfloat)255.0;
-              masks[1].mask     = 0x00ff00;
-              masks[1].shiftin  = 8;
-              masks[1].max_value= (gfloat)255.0;
-              masks[2].mask     = 0x0000ff;
-              masks[2].shiftin  = 0;
-              masks[2].max_value= (gfloat)255.0;
-              masks[3].mask     = 0x0;
-              masks[3].shiftin  = 0;
-              masks[3].max_value= (gfloat)0.0;
-              break;
-            case 16:
-              masks[0].mask     = 0x7c00;
-              masks[0].shiftin  = 10;
-              masks[0].max_value= (gfloat)31.0;
-              masks[1].mask     = 0x03e0;
-              masks[1].shiftin  = 5;
-              masks[1].max_value= (gfloat)31.0;
-              masks[2].mask     = 0x001f;
-              masks[2].shiftin  = 0;
-              masks[2].max_value= (gfloat)31.0;
-              masks[3].mask     = 0x0;
-              masks[3].shiftin  = 0;
-              masks[3].max_value= (gfloat)0.0;
-              break;
-            default:
-              break;
-            }
+          setMasksDefault (Bitmap_Head.biBitCnt, masks);
         }
-      else
+      else if ((Bitmap_Head.biCompr != BI_RLE4) && (Bitmap_Head.biCompr != BI_RLE8))
         {
           /* BI_ALPHABITFIELDS, etc. */
           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
@@ -376,38 +382,51 @@ ReadBMP (const gchar  *name,
       Maps = 4;
       ReadChannelMasks (&Bitmap_Head.masks[0], masks, 4);
     }
-  else
+  else if (Bitmap_File_Head.biSize == 108 || Bitmap_File_Head.biSize == 124)
+    /* BMP Version 4 or 5 */
     {
-      GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
-
-      if (pixbuf)
+      if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4))
         {
-          gint32 layer_ID;
 
-          image_ID = gimp_image_new (gdk_pixbuf_get_width (pixbuf),
-                                     gdk_pixbuf_get_height (pixbuf),
-                                     GIMP_RGB);
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("Error reading BMP file header from '%s'"),
+                       gimp_filename_to_utf8 (filename));
+          return -1;
+        }
 
-          layer_ID = gimp_layer_new_from_pixbuf (image_ID, _("Background"),
-                                                 pixbuf,
-                                                 100.,
-                                                 GIMP_NORMAL_MODE, 0, 0);
-          g_object_unref (pixbuf);
+      Bitmap_Head.biWidth   = ToL (&buffer[0x00]);
+      Bitmap_Head.biHeight  = ToL (&buffer[0x04]);
+      Bitmap_Head.biPlanes  = ToS (&buffer[0x08]);
+      Bitmap_Head.biBitCnt  = ToS (&buffer[0x0A]);
+      Bitmap_Head.biCompr   = ToL (&buffer[0x0C]);
+      Bitmap_Head.biSizeIm  = ToL (&buffer[0x10]);
+      Bitmap_Head.biXPels   = ToL (&buffer[0x14]);
+      Bitmap_Head.biYPels   = ToL (&buffer[0x18]);
+      Bitmap_Head.biClrUsed = ToL (&buffer[0x1C]);
+      Bitmap_Head.biClrImp  = ToL (&buffer[0x20]);
+      Bitmap_Head.masks[0]  = ToL (&buffer[0x24]);
+      Bitmap_Head.masks[1]  = ToL (&buffer[0x28]);
+      Bitmap_Head.masks[2]  = ToL (&buffer[0x2C]);
+      Bitmap_Head.masks[3]  = ToL (&buffer[0x30]);
 
-          gimp_image_set_filename (image_ID, filename);
-          gimp_image_insert_layer (image_ID, layer_ID, -1, -1);
+      Maps = 4;
 
-          return image_ID;
+      if (Bitmap_Head.biCompr == BI_BITFIELDS)
+        {
+          ReadChannelMasks (&Bitmap_Head.masks[0], masks, 4);
         }
-      else
+      else if (Bitmap_Head.biCompr == BI_RGB)
         {
-
-          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                       _("Error reading BMP file header from '%s'"),
-                       gimp_filename_to_utf8 (filename));
-          return -1;
+          setMasksDefault (Bitmap_Head.biBitCnt, masks);
         }
     }
+  else
+    {
+      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                   _("Error reading BMP file header from '%s'"),
+                   gimp_filename_to_utf8 (filename));
+      return -1;
+    }
 
   /* Valid bit depth is 1, 4, 8, 16, 24, 32 */
   /* 16 is awful, we should probably shoot whoever invented it */
@@ -697,42 +716,6 @@ ReadImage (FILE                  *fd,
               gimp_progress_update ((gdouble) cur_progress /
                                     (gdouble) max_progress);
           }
-
-        if (channels == 4)
-          {
-            gboolean  has_alpha = FALSE;
-
-            /* at least one pixel should have nonzero alpha */
-            for (ypos = 0; ypos < height; ypos++)
-              {
-                temp = dest + (ypos * rowstride);
-                for (xpos = 0; xpos < width; xpos++)
-                  {
-                    if (temp[3])
-                      {
-                        has_alpha = TRUE;
-                        break;
-                      }
-                    temp += 4;
-                  }
-                if (has_alpha)
-                  break;
-              }
-
-            /* workaround unwanted behaviour when all alpha pixels are zero */
-            if (!has_alpha)
-              {
-                for (ypos = 0; ypos < height; ypos++)
-                  {
-                    temp = dest + (ypos * rowstride);
-                    for (xpos = 0; xpos < width; xpos++)
-                      {
-                        temp[3] = 255;
-                        temp += 4;
-                      }
-                  }
-              }
-          }
       }
       break;
 


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