mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
55a70729ae
commit
56f065321c
|
@ -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,30 +382,10 @@ 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)
|
||||
{
|
||||
gint32 layer_ID;
|
||||
|
||||
image_ID = gimp_image_new (gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
GIMP_RGB);
|
||||
|
||||
layer_ID = gimp_layer_new_from_pixbuf (image_ID, _("Background"),
|
||||
pixbuf,
|
||||
100.,
|
||||
GIMP_NORMAL_MODE, 0, 0);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
gimp_image_set_filename (image_ID, filename);
|
||||
gimp_image_insert_layer (image_ID, layer_ID, -1, -1);
|
||||
|
||||
return image_ID;
|
||||
}
|
||||
else
|
||||
if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4))
|
||||
{
|
||||
|
||||
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
||||
|
@ -407,6 +393,39 @@ ReadBMP (const gchar *name,
|
|||
gimp_filename_to_utf8 (filename));
|
||||
return -1;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
Maps = 4;
|
||||
|
||||
if (Bitmap_Head.biCompr == BI_BITFIELDS)
|
||||
{
|
||||
ReadChannelMasks (&Bitmap_Head.masks[0], masks, 4);
|
||||
}
|
||||
else if (Bitmap_Head.biCompr == BI_RGB)
|
||||
{
|
||||
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 */
|
||||
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue