After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 142165 - Alpha extensions to BMP
Alpha extensions to BMP
Status: RESOLVED DUPLICATE of bug 306339
Product: GIMP
Classification: Other
Component: Plugins
git master
Other All
: Normal enhancement
: Future
Assigned To: GIMP Bugs
GIMP Bugs
Depends on:
Blocks:
 
 
Reported: 2004-05-09 03:59 UTC by Troy D. Gillette
Modified: 2005-06-05 22:33 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Diff file for the plug-ins bmp directory. (8.24 KB, patch)
2004-05-10 18:38 UTC, Troy D. Gillette
needs-work Details | Review
Possible cleaned up patch (4.51 KB, patch)
2004-07-17 21:43 UTC, Brion Vibber
none Details | Review
Sample PNG image with alpha channel (13.30 KB, image/png)
2004-07-18 03:59 UTC, Brion Vibber
  Details
Sample BMP image with transparency (created by ImageMagick) (256.12 KB, image/bmp)
2004-07-18 04:03 UTC, Brion Vibber
  Details
Partial support for bmp files with newer header format (10.43 KB, patch)
2004-07-23 08:52 UTC, Brion Vibber
accepted-commit_now Details | Review
Alternate patch for alpha support in BMP plugin. (3.85 KB, patch)
2005-05-15 04:02 UTC, Brandon
none Details | Review
BMP with alpha transparency created in Photoshop (36.05 KB, image/bmp)
2005-05-15 05:09 UTC, Brandon
  Details

Description Troy D. Gillette 2004-05-09 03:59:54 UTC
Since Windows XP uses 32 bit alpha channel BMPs we can assume it is now part of the spec.
Here's a patch to support it.
---------------------------------------------------
--- bmp/bmp.c	Tue Nov 25 05:49:15 2003
+++ /sw/src/gimp2-noprint-2.0.0-2/gimp-2.0.0/plug-ins/bmp/bmp.c
	Sat May  8 20:36:35 2004
@@ -27,7 +27,9 @@
 /*            06.05.2000 Overhaul for 16&24-bit   */
 /*                       plus better OS/2 code    */
 /*                       by njl195@zepler.org.uk  */
-
+/*            07.05.2004 Added 32 bit alpha       */
+/*                       extensions               */
+/*                       -Troy D. Gillette        */
 /*
  * The GIMP -- an image manipulation program
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
@@ -217,7 +219,8 @@
 	  export = gimp_export_image (&image_ID, &drawable_ID, "BMP",
 				      (GIMP_EXPORT_CAN_HANDLE_RGB |
 				       GIMP_EXPORT_CAN_HANDLE_GRAY |
-				       GIMP_EXPORT_CAN_HANDLE_INDEXED));
+				       GIMP_EXPORT_CAN_HANDLE_INDEXED |
+				       GIMP_EXPORT_CAN_HANDLE_ALPHA));
 	  if (export == GIMP_EXPORT_CANCEL)
 	    {
 	      values[0].data.d_status = GIMP_PDB_CANCEL;
--- bmp/bmpread.c	Mon Jan 19 03:13:32 2004
+++ /sw/src/gimp2-noprint-2.0.0-2/gimp-2.0.0/plug-ins/bmp/bmpread.c
	Sat May  8 20:35:57 2004
@@ -391,14 +391,22 @@
 
   /* Make a new image in the gimp */
 
-  if (bpp >= 16)
-    {
+  if (bpp == 32)
+  {
+      image = gimp_image_new (width, height, GIMP_RGB);
+      layer = gimp_layer_new (image, _("Background"),
+                              width, height,
+                              GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
+      channels = 4;
+  }
+  else if (bpp >= 16)
+  {
       image = gimp_image_new (width, height, GIMP_RGB);
       layer = gimp_layer_new (image, _("Background"),
                               width, height,
                               GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE);
       channels = 3;
-    }
+  }
   else if (grey)
     {
       image = gimp_image_new (width, height, GIMP_GRAY);
@@ -438,9 +446,10 @@
             temp = dest + (ypos * rowstride);
             for (xpos= 0; xpos < width; ++xpos)
               {
-                *(temp++)= buffer[xpos * 4 + 2];
-                *(temp++)= buffer[xpos * 4 + 1];
-                *(temp++)= buffer[xpos * 4];
+                *(temp++) = buffer[xpos * 4 + 2];
+                *(temp++) = buffer[xpos * 4 + 1];
+                *(temp++) = buffer[xpos * 4];
+                *(temp++) = buffer[xpos * 4 + 3]^0xff;
               }
             --ypos; /* next line */
             cur_progress++;
--- bmp/bmpwrite.c	Tue Jan 20 09:07:15 2004
+++ /sw/src/gimp2-noprint-2.0.0-2/gimp-2.0.0/plug-ins/bmp/bmpwrite.c
	Sat May  8 20:33:07 2004
@@ -49,7 +49,10 @@
 static gint cur_progress = 0;
 static gint max_progress = 0;
 static gint encoded      = 0;
-
+static gint bits32       = 0;
+static gint bits24       = 0;
+static gint alpha32      = 0;
+static GtkWidget *a32toggle;
 
 static  void      WriteImage  (FILE   *f,
                                guchar *src,
@@ -61,7 +64,7 @@
                                gint    spzeile,
                                gint    MapSize);
 static  gboolean  save_dialog (void);
-
+static  gboolean  save_dialogRGB (gboolean  alpha);
 
 static void
 FromL (gint32  wert,
@@ -131,23 +134,36 @@
   gimp_pixel_rgn_init (&pixel_rgn, drawable,
 		       0, 0, drawable->width, drawable->height, FALSE, FALSE);
 
-  if (gimp_drawable_has_alpha (drawable_ID))
-    {
-      g_message (_("Cannot save images with alpha channel."));
-      return GIMP_PDB_EXECUTION_ERROR;
-    }
-
+  if (BitsPerPixel >= 24)
+  {
+      if (! save_dialogRGB (drawable_type == GIMP_RGBA_IMAGE))
+		  return GIMP_PDB_CANCEL;
+  }
+  
   /* We can save it. So what colors do we use? */
 
   switch (drawable_type)
     {
-    case GIMP_RGB_IMAGE:
+  case GIMP_RGBA_IMAGE:
+      if(bits32) {
+          colors       = 0;
+          BitsPerPixel = 32;
+          MapSize      = 0;
+          channels     = 4;
+      } else {
+          colors       = 0;
+          BitsPerPixel = 24;
+          MapSize      = 0;
+          channels     = 4;
+      }
+      break;
+  case GIMP_RGB_IMAGE:
       colors       = 0;
       BitsPerPixel = 24;
       MapSize      = 0;
       channels     = 3;
       break;
-    case GIMP_GRAY_IMAGE:
+  case GIMP_GRAY_IMAGE:
       colors       = 256;
       BitsPerPixel = 8;
       MapSize      = 1024;
@@ -219,7 +235,7 @@
   rows = drawable->height;
 
   /* ... that we write to our headers. */
-  if ((BitsPerPixel != 24) &&
+  if ((BitsPerPixel < 24) &&
       (cols % (8/BitsPerPixel)))
     Spcols = (((cols / (8 / BitsPerPixel)) + 1) * (8 / BitsPerPixel));
   else
@@ -349,9 +365,38 @@
   xpos = 0;
   rowstride = width * channels;
 
-  /* We'll begin with the 24 bit Bitmaps, they are easy :-) */
+  /* We'll begin with the 32 and 24 bit Bitmaps, they are easy :-) */
 
-  if (bpp == 24)
+  if (bpp == 32)
+  {
+      for (ypos = height - 1; ypos >= 0; ypos--)  /* for each row   */
+        {
+          for (i = 0; i < width; i++)  /* for each pixel */
+          {
+              temp = src + (ypos * rowstride) + (xpos * channels);
+              buf[2] = (guchar) *temp;
+              temp++;
+              buf[1] = (guchar) *temp;
+              temp++;
+              buf[0] = (guchar) *temp;
+              temp++;
+              if(alpha32)
+                  buf[3] = (guchar) *temp^0xff;
+              else
+                  buf[3] = 0;
+              xpos++;
+              Write (f, buf, 4);
+          }
+          Write (f, &buf[4], spzeile - (width * 4));
+ 
+          cur_progress++;
+          if ((cur_progress % 5) == 0)
+              gimp_progress_update ((gdouble) cur_progress / (gdouble) max_progress);
+ 
+          xpos = 0;
+        }
+  }
+  else if (bpp == 24)
     {
       for (ypos = height - 1; ypos >= 0; ypos--)  /* for each row   */
 	{
@@ -577,6 +622,85 @@
   g_signal_connect (toggle, "toggled",
                     G_CALLBACK (gimp_toggle_button_update),
                     &encoded);
+
+  gtk_widget_show (vbox);
+  gtk_widget_show (frame);
+  gtk_widget_show (dlg);
+
+  run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);
+
+  gtk_widget_destroy (dlg);
+
+  return run;
+}
+
+void RGBdialog_callback( GtkWidget *widget,
+						 gpointer   callback_data )
+{
+char *str = (char *)callback_data;
+  if(str[0] == '3') {
+      bits24 = 1;
+      bits32 = 0;
+      gtk_widget_set_sensitive (a32toggle, FALSE);
+  } else {
+      bits24 = 0;
+      bits32 = 1;
+      gtk_widget_set_sensitive (a32toggle, TRUE);
+  }
+}
+
+static gboolean
+save_dialogRGB (gboolean  alpha)
+{
+  GtkWidget *dlg;
+  GtkWidget *radio;
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GSList *group;
+  gboolean   run;
+	
+  dlg = gimp_dialog_new (_("Save as BMP"), "bmp",
+                         NULL, 0,
+                         gimp_standard_help_func, "file-bmp-save",
+                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                         GTK_STOCK_OK,     GTK_RESPONSE_OK,
+                         NULL);
+
+  /*  parameter settings  */
+  frame = gtk_frame_new (_("Save Options"));
+  gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
+
+  vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+  radio = gtk_radio_button_new_with_mnemonic (NULL,_("_24 Bit"));
+  gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), bits24);
+  gtk_widget_show (radio);
+
+  g_signal_connect (radio, "toggled",
+                    G_CALLBACK (RGBdialog_callback),
+                    "3");
+
+  group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
+  radio = gtk_radio_button_new_with_mnemonic (group,_("_32 Bit"));
+  gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0);
+  gtk_widget_show (radio);
+
+  g_signal_connect (radio, "toggled",
+                    G_CALLBACK (RGBdialog_callback),
+                    "4");
+
+  a32toggle = gtk_check_button_new_with_mnemonic (_("Save Alpha Channel"));
+  gtk_box_pack_start (GTK_BOX (vbox), a32toggle, FALSE, FALSE, 0);
+  gtk_widget_set_sensitive (a32toggle, FALSE);
+  gtk_widget_show (a32toggle);
+
+  g_signal_connect (a32toggle, "toggled",
+                    G_CALLBACK (gimp_toggle_button_update),
+                    &alpha32);
 
   gtk_widget_show (vbox);
   gtk_widget_show (frame);
Comment 1 Sven Neumann 2004-05-10 11:04:17 UTC
Please do not paste patches into the comment field where they usually get
garbled. Can you please attach the diff to the bug report instead?
Comment 2 Troy D. Gillette 2004-05-10 18:38:38 UTC
Created attachment 27562 [details] [review]
Diff file for the plug-ins bmp directory.
Comment 3 Sven Neumann 2004-05-10 19:01:40 UTC
The patch doesn't follow the GIMP coding style, thus it will need some fixing
when it is applied. Also I don't understand the logic of the dialog. I only
looked the code but it seems that it gives the choice for 24 or 32 bit and adds
a check button on whether to save the alpha channel? Isn't that somewhat duplicated?

I am also missing changes to the plug-in registration code. It should announce
that it can now handle an alpha channel or it won't show up properly in the
file-save menu.
Comment 4 Sven Neumann 2004-05-17 11:14:59 UTC
Adding Nick Lamb to Cc: in the hope that he can comment on this change to the
BMP plug-in.
Comment 5 Sven Neumann 2004-06-05 20:24:33 UTC
Troy, are you going to answer my questions on your patch or did you loose interest?
Comment 6 Brion Vibber 2004-07-17 21:43:53 UTC
Created attachment 29612 [details] [review]
Possible cleaned up patch

Quick stab at a clean-up; this removes the dialog on save, and will simply save
an RGBA image as alpha. Also included is the plugin registration change to get
it to show up properly.

I'm not 100% sure it actually works, though; the specs on MSDN are really
vague, and I haven't found anything that's known to read and write 32-bit alpha
BMPs correctly, nor known-good sample files to test with.

The only sample files I've found are at
http://cgi.glyphlab.com/php/gl/articles/eight_bit_alpha1.php and *do not work*
with this patch, as the values for the alpha channel are inverted.

Vague MSDN specs for bitmap files:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_4v1h.asp
Comment 7 Brion Vibber 2004-07-18 03:59:04 UTC
Created attachment 29617 [details]
Sample PNG image with alpha channel
Comment 8 Brion Vibber 2004-07-18 04:03:37 UTC
Created attachment 29618 [details]
Sample BMP image with transparency (created by ImageMagick)

The above PNG image converted to BMP-with-alpha by ImageMagick 5.5.6.
This file does not load with the current patch, it looks like it uses the newer

version header (see MSDN link above) which is not handled.

If I try converting a 32-bit BMP as saved from gimp w/ the current patch
back to PNG via ImageMagick, the alpha channel is lost. This makes me
suspect that (at least for ImageMagick), alpha isn't really allowed except
with the newer header.
Comment 9 Brion Vibber 2004-07-23 08:52:16 UTC
Created attachment 29819 [details] [review]
Partial support for bmp files with newer header format

This is where I last left off; it will load the sample image created by
ImageMagick, but doesn't use the new header format on save, so ImageMagick will
ignore the GIMP-saved alpha channel.

Without some known good sample files or apps to interoperate with, it's hard to
test this. :)
Comment 10 Dave Neary 2004-08-09 14:15:47 UTC
Comment on attachment 27562 [details] [review]
Diff file for the plug-ins bmp directory.

This patch was obsoleted by patch #29612
Comment 11 Dave Neary 2004-08-09 14:17:54 UTC
Comment on attachment 29819 [details] [review]
Partial support for bmp files with newer header format


I propose that attachment #29819 [details] (Brion Vibber's last patch) be committed,
since it doesn't break existing support, and adds some support for a more
esoteric BMP filetype.

That should close this bug FIXED.
Comment 12 Brion Vibber 2004-08-09 18:11:08 UTC
I would not recommend committing the patch as is; I'm pretty sure it doesn't save in the correct format.
Comment 13 Sven Neumann 2004-10-26 15:28:47 UTC
Moving from the 2.2 milestone to Future then. We should try to get this done in
the next development cycle.
Comment 14 Federico Mena Quintero 2005-02-28 18:42:39 UTC
http://netghost.narod.ru/gff/graphics/summary/micbmp.htm is a good reference of
various BMP versions.
Comment 15 Raphaël Quinet 2005-03-01 15:20:54 UTC
See also the links mentioned in bug #168628.  Those pages seem to load faster, at
least.
Comment 16 Brandon 2005-05-15 04:02:07 UTC
Created attachment 46443 [details] [review]
Alternate patch for alpha support in BMP plugin.

I added alpha functionality to the BMP plugin several months back for my use in
a Windows app with the intent to submit the patch.  So I finally got around to
submitting it.	It's been tested against some images created by Photoshop and
this plugin holds more closely to the specs I found than does Photoshop.  I'll
attach some of the images I was working with.
Comment 17 Brandon 2005-05-15 05:09:20 UTC
Created attachment 46444 [details]
BMP with alpha transparency created in Photoshop

As promised, here is a bitmap with alpha channel.  I also forgot to mention
that patch 46443 is for version 2.2.7 of The Gimp.  It also contains two lines
of code that I posted in bug 303972 regarding the bitmap resolution.
Comment 18 Sven Neumann 2005-06-05 22:33:43 UTC
Brandon opened a new bug report on this issue and attached and updated patched
there. Closing this report as duplicate of the new one.

*** This bug has been marked as a duplicate of 306339 ***