mirror of https://github.com/GNOME/gimp.git
Applied a patch from Brion Vibber that fixes corruption when saving
2004-07-17 Philip Lafleur <plafleur@cvs.gnome.org> * plug-ins/bmp/bmpwrite.c (WriteImage): Applied a patch from Brion Vibber that fixes corruption when saving RLE-encoded BMPs on big endian hosts. Fixes bug #147759.
This commit is contained in:
parent
7ddb6a6a9e
commit
a23024eb2b
|
@ -1,3 +1,9 @@
|
|||
2004-07-17 Philip Lafleur <plafleur@cvs.gnome.org>
|
||||
|
||||
* plug-ins/bmp/bmpwrite.c (WriteImage): Applied a patch from
|
||||
Brion Vibber that fixes corruption when saving RLE-encoded
|
||||
BMPs on big endian hosts. Fixes bug #147759.
|
||||
|
||||
2004-07-17 Shlomi Fish <shlomif@iglu.org.il>
|
||||
|
||||
* plug-ins/gimpressionist/: normalized the identifiers of
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* bmpwrite.c Writes Bitmap files. Even RLE encoded ones. */
|
||||
/* (Windows (TM) doesn't read all of those, but who */
|
||||
/* cares? ;-) */
|
||||
/* bmpwrite.c Writes Bitmap files. Even RLE encoded ones. */
|
||||
/* (Windows (TM) doesn't read all of those, but who */
|
||||
/* cares? ;-) */
|
||||
/* I changed a few things over the time, so perhaps */
|
||||
/* it dos now, but now there's no Windows left on */
|
||||
/* my computer... */
|
||||
|
||||
/* Alexander.Schulz@stud.uni-karlsruhe.de */
|
||||
/* Alexander.Schulz@stud.uni-karlsruhe.de */
|
||||
|
||||
/*
|
||||
* The GIMP -- an image manipulation program
|
||||
|
@ -83,10 +83,10 @@ FromS (gint16 wert,
|
|||
|
||||
static void
|
||||
WriteColorMap (FILE *f,
|
||||
gint red[MAXCOLORS],
|
||||
gint green[MAXCOLORS],
|
||||
gint blue[MAXCOLORS],
|
||||
gint size)
|
||||
gint red[MAXCOLORS],
|
||||
gint green[MAXCOLORS],
|
||||
gint blue[MAXCOLORS],
|
||||
gint size)
|
||||
{
|
||||
gchar trgb[4];
|
||||
gint i;
|
||||
|
@ -104,8 +104,8 @@ WriteColorMap (FILE *f,
|
|||
|
||||
GimpPDBStatusType
|
||||
WriteBMP (const gchar *filename,
|
||||
gint32 image,
|
||||
gint32 drawable_ID)
|
||||
gint32 image,
|
||||
gint32 drawable_ID)
|
||||
{
|
||||
FILE *outfile;
|
||||
gint Red[MAXCOLORS];
|
||||
|
@ -129,7 +129,7 @@ WriteBMP (const gchar *filename,
|
|||
drawable_type = gimp_drawable_type (drawable_ID);
|
||||
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable,
|
||||
0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
||||
0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
||||
|
||||
if (gimp_drawable_has_alpha (drawable_ID))
|
||||
{
|
||||
|
@ -153,11 +153,11 @@ WriteBMP (const gchar *filename,
|
|||
MapSize = 1024;
|
||||
channels = 1;
|
||||
for (i = 0; i < colors; i++)
|
||||
{
|
||||
Red[i] = i;
|
||||
Green[i] = i;
|
||||
Blue[i] = i;
|
||||
}
|
||||
{
|
||||
Red[i] = i;
|
||||
Green[i] = i;
|
||||
Blue[i] = i;
|
||||
}
|
||||
break;
|
||||
case GIMP_INDEXED_IMAGE:
|
||||
cmap = gimp_image_get_cmap (image, &colors);
|
||||
|
@ -165,18 +165,18 @@ WriteBMP (const gchar *filename,
|
|||
channels = 1;
|
||||
|
||||
if (colors > 16)
|
||||
BitsPerPixel = 8;
|
||||
BitsPerPixel = 8;
|
||||
else if (colors > 2)
|
||||
BitsPerPixel = 4;
|
||||
BitsPerPixel = 4;
|
||||
else
|
||||
BitsPerPixel = 1;
|
||||
BitsPerPixel = 1;
|
||||
|
||||
for (i = 0; i < colors; i++)
|
||||
{
|
||||
Red[i] = *cmap++;
|
||||
Green[i] = *cmap++;
|
||||
Blue[i] = *cmap++;
|
||||
}
|
||||
{
|
||||
Red[i] = *cmap++;
|
||||
Green[i] = *cmap++;
|
||||
Blue[i] = *cmap++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_message (_("Cannot operate on unknown image types."));
|
||||
|
@ -188,7 +188,7 @@ WriteBMP (const gchar *filename,
|
|||
if ((BitsPerPixel == 8 || BitsPerPixel == 4) && interactive_bmp)
|
||||
{
|
||||
if (! save_dialog ())
|
||||
return GIMP_PDB_CANCEL;
|
||||
return GIMP_PDB_CANCEL;
|
||||
}
|
||||
|
||||
/* Let's take some file */
|
||||
|
@ -203,7 +203,7 @@ WriteBMP (const gchar *filename,
|
|||
/* fetch the image */
|
||||
pixels = g_new (guchar, drawable->width * drawable->height * channels);
|
||||
gimp_pixel_rgn_get_rect (&pixel_rgn, pixels,
|
||||
0, 0, drawable->width, drawable->height);
|
||||
0, 0, drawable->width, drawable->height);
|
||||
|
||||
/* And let's begin the progress */
|
||||
temp_buf = g_strdup_printf (_("Saving '%s'..."),
|
||||
|
@ -258,17 +258,17 @@ WriteBMP (const gchar *filename,
|
|||
gimp_image_get_resolution (image, &xresolution, &yresolution);
|
||||
|
||||
if (xresolution > GIMP_MIN_RESOLUTION &&
|
||||
yresolution > GIMP_MIN_RESOLUTION)
|
||||
yresolution > GIMP_MIN_RESOLUTION)
|
||||
{
|
||||
/*
|
||||
* xresolution and yresolution are in dots per inch.
|
||||
* the BMP spec says that biXPels and biYPels are in
|
||||
* pixels per meter as long ints (actually, "DWORDS"),
|
||||
* so...
|
||||
* n dots inch 100 cm m dots
|
||||
* ------ * ------- * ------ = ------
|
||||
* inch 2.54 cm m inch
|
||||
*/
|
||||
/*
|
||||
* xresolution and yresolution are in dots per inch.
|
||||
* the BMP spec says that biXPels and biYPels are in
|
||||
* pixels per meter as long ints (actually, "DWORDS"),
|
||||
* so...
|
||||
* n dots inch 100 cm m dots
|
||||
* ------ * ------- * ------ = ------
|
||||
* inch 2.54 cm m inch
|
||||
*/
|
||||
Bitmap_Head.biXPels = (long int) xresolution * 100.0 / 2.54;
|
||||
Bitmap_Head.biYPels = (long int) yresolution * 100.0 / 2.54;
|
||||
}
|
||||
|
@ -316,8 +316,8 @@ WriteBMP (const gchar *filename,
|
|||
/* After that is done, we write the image ... */
|
||||
|
||||
WriteImage (outfile,
|
||||
pixels, cols, rows,
|
||||
encoded, channels, BitsPerPixel, SpZeile, MapSize);
|
||||
pixels, cols, rows,
|
||||
encoded, channels, BitsPerPixel, SpZeile, MapSize);
|
||||
|
||||
/* ... and exit normally */
|
||||
|
||||
|
@ -330,21 +330,22 @@ WriteBMP (const gchar *filename,
|
|||
|
||||
static void
|
||||
WriteImage (FILE *f,
|
||||
guchar *src,
|
||||
gint width,
|
||||
gint height,
|
||||
gint encoded,
|
||||
gint channels,
|
||||
gint bpp,
|
||||
gint spzeile,
|
||||
gint MapSize)
|
||||
guchar *src,
|
||||
gint width,
|
||||
gint height,
|
||||
gint encoded,
|
||||
gint channels,
|
||||
gint bpp,
|
||||
gint spzeile,
|
||||
gint MapSize)
|
||||
{
|
||||
guchar buf[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};
|
||||
guchar puffer[8];
|
||||
guchar *temp, v;
|
||||
guchar *Zeile, *ketten;
|
||||
gint xpos, ypos, i, j, rowstride, laenge, thiswidth;
|
||||
gint breite, n, k;
|
||||
gint breite, k;
|
||||
guchar n;
|
||||
|
||||
xpos = 0;
|
||||
rowstride = width * channels;
|
||||
|
@ -354,189 +355,189 @@ WriteImage (FILE *f,
|
|||
if (bpp == 24)
|
||||
{
|
||||
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;
|
||||
xpos++;
|
||||
Write (f, buf, 3);
|
||||
}
|
||||
Write (f, &buf[3], spzeile - (width * 3));
|
||||
{
|
||||
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;
|
||||
xpos++;
|
||||
Write (f, buf, 3);
|
||||
}
|
||||
Write (f, &buf[3], spzeile - (width * 3));
|
||||
|
||||
cur_progress++;
|
||||
if ((cur_progress % 5) == 0)
|
||||
gimp_progress_update ((gdouble) cur_progress /
|
||||
(gdouble) max_progress);
|
||||
cur_progress++;
|
||||
if ((cur_progress % 5) == 0)
|
||||
gimp_progress_update ((gdouble) cur_progress /
|
||||
(gdouble) max_progress);
|
||||
|
||||
xpos = 0;
|
||||
}
|
||||
xpos = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (encoded) /* now it gets more difficult */
|
||||
{ /* uncompressed 1,4 and 8 bit */
|
||||
case 0:
|
||||
{
|
||||
thiswidth = (width / (8 / bpp));
|
||||
if (width % (8 / bpp))
|
||||
thiswidth++;
|
||||
{ /* uncompressed 1,4 and 8 bit */
|
||||
case 0:
|
||||
{
|
||||
thiswidth = (width / (8 / bpp));
|
||||
if (width % (8 / bpp))
|
||||
thiswidth++;
|
||||
|
||||
for (ypos = height - 1; ypos >= 0; ypos--) /* for each row */
|
||||
{
|
||||
for (xpos = 0; xpos < width;) /* for each _byte_ */
|
||||
{
|
||||
v = 0;
|
||||
for (i = 1;
|
||||
(i <= (8 / bpp)) && (xpos < width);
|
||||
i++, xpos++) /* for each pixel */
|
||||
{
|
||||
temp = src + (ypos * rowstride) + (xpos * channels);
|
||||
v=v | ((guchar) *temp << (8 - (i * bpp)));
|
||||
}
|
||||
Write (f, &v, 1);
|
||||
}
|
||||
Write (f, &buf[3], spzeile - thiswidth);
|
||||
xpos = 0;
|
||||
for (ypos = height - 1; ypos >= 0; ypos--) /* for each row */
|
||||
{
|
||||
for (xpos = 0; xpos < width;) /* for each _byte_ */
|
||||
{
|
||||
v = 0;
|
||||
for (i = 1;
|
||||
(i <= (8 / bpp)) && (xpos < width);
|
||||
i++, xpos++) /* for each pixel */
|
||||
{
|
||||
temp = src + (ypos * rowstride) + (xpos * channels);
|
||||
v=v | ((guchar) *temp << (8 - (i * bpp)));
|
||||
}
|
||||
Write (f, &v, 1);
|
||||
}
|
||||
Write (f, &buf[3], spzeile - thiswidth);
|
||||
xpos = 0;
|
||||
|
||||
cur_progress++;
|
||||
if ((cur_progress % 5) == 0)
|
||||
gimp_progress_update ((gdouble) cur_progress /
|
||||
(gdouble) max_progress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{ /* Save RLE encoded file, quite difficult */
|
||||
laenge = 0;
|
||||
buf[12] = 0;
|
||||
buf[13] = 1;
|
||||
buf[14] = 0;
|
||||
buf[15] = 0;
|
||||
Zeile = (guchar *) g_malloc (width / (8 / bpp) + 10);
|
||||
ketten = (guchar *) g_malloc (width / (8 / bpp) + 10);
|
||||
for (ypos = height - 1; ypos >= 0; ypos--)
|
||||
{ /* each row separately */
|
||||
j = 0;
|
||||
/* first copy the pixels to a buffer,
|
||||
* making one byte from two 4bit pixels
|
||||
*/
|
||||
for (xpos = 0; xpos < width;)
|
||||
{
|
||||
v = 0;
|
||||
for (i = 1;
|
||||
(i <= (8 / bpp)) && (xpos < width);
|
||||
i++, xpos++)
|
||||
{ /* for each pixel */
|
||||
temp = src + (ypos * rowstride) + (xpos * channels);
|
||||
v = v | ((guchar) * temp << (8 - (i * bpp)));
|
||||
}
|
||||
Zeile[j++] = v;
|
||||
}
|
||||
breite = width / (8 / bpp);
|
||||
if (width % (8 / bpp))
|
||||
breite++;
|
||||
/* then check for strings of equal bytes */
|
||||
for (i = 0; i < breite;)
|
||||
{
|
||||
j = 0;
|
||||
while ((i + j < breite) &&
|
||||
(j < (255 / (8 / bpp))) &&
|
||||
(Zeile[i + j] == Zeile[i]))
|
||||
j++;
|
||||
cur_progress++;
|
||||
if ((cur_progress % 5) == 0)
|
||||
gimp_progress_update ((gdouble) cur_progress /
|
||||
(gdouble) max_progress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{ /* Save RLE encoded file, quite difficult */
|
||||
laenge = 0;
|
||||
buf[12] = 0;
|
||||
buf[13] = 1;
|
||||
buf[14] = 0;
|
||||
buf[15] = 0;
|
||||
Zeile = (guchar *) g_malloc (width / (8 / bpp) + 10);
|
||||
ketten = (guchar *) g_malloc (width / (8 / bpp) + 10);
|
||||
for (ypos = height - 1; ypos >= 0; ypos--)
|
||||
{ /* each row separately */
|
||||
j = 0;
|
||||
/* first copy the pixels to a buffer,
|
||||
* making one byte from two 4bit pixels
|
||||
*/
|
||||
for (xpos = 0; xpos < width;)
|
||||
{
|
||||
v = 0;
|
||||
for (i = 1;
|
||||
(i <= (8 / bpp)) && (xpos < width);
|
||||
i++, xpos++)
|
||||
{ /* for each pixel */
|
||||
temp = src + (ypos * rowstride) + (xpos * channels);
|
||||
v = v | ((guchar) * temp << (8 - (i * bpp)));
|
||||
}
|
||||
Zeile[j++] = v;
|
||||
}
|
||||
breite = width / (8 / bpp);
|
||||
if (width % (8 / bpp))
|
||||
breite++;
|
||||
/* then check for strings of equal bytes */
|
||||
for (i = 0; i < breite;)
|
||||
{
|
||||
j = 0;
|
||||
while ((i + j < breite) &&
|
||||
(j < (255 / (8 / bpp))) &&
|
||||
(Zeile[i + j] == Zeile[i]))
|
||||
j++;
|
||||
|
||||
ketten[i] = j;
|
||||
i += j;
|
||||
}
|
||||
ketten[i] = j;
|
||||
i += j;
|
||||
}
|
||||
|
||||
/* then write the strings and the other pixels to the file */
|
||||
for (i = 0; i < breite;)
|
||||
{
|
||||
if (ketten[i] < 3)
|
||||
/* strings of different pixels ... */
|
||||
{
|
||||
j = 0;
|
||||
while ((i + j < breite) &&
|
||||
(j < (255 / (8 / bpp))) &&
|
||||
(ketten[i + j] < 3))
|
||||
j += ketten[i + j];
|
||||
/* then write the strings and the other pixels to the file */
|
||||
for (i = 0; i < breite;)
|
||||
{
|
||||
if (ketten[i] < 3)
|
||||
/* strings of different pixels ... */
|
||||
{
|
||||
j = 0;
|
||||
while ((i + j < breite) &&
|
||||
(j < (255 / (8 / bpp))) &&
|
||||
(ketten[i + j] < 3))
|
||||
j += ketten[i + j];
|
||||
|
||||
/* this can only happen if j jumps over
|
||||
* the end with a 2 in ketten[i+j]
|
||||
*/
|
||||
if (j > (255 / (8 / bpp)))
|
||||
j -= 2;
|
||||
/* 00 01 and 00 02 are reserved */
|
||||
if (j > 2)
|
||||
{
|
||||
Write (f, &buf[12], 1);
|
||||
n = j * (8 / bpp);
|
||||
if (n + i * (8 / bpp) > width)
|
||||
n--;
|
||||
Write (f, &n, 1);
|
||||
laenge += 2;
|
||||
Write (f, &Zeile[i], j);
|
||||
laenge += j;
|
||||
if ((j) % 2)
|
||||
{
|
||||
Write (f, &buf[12], 1);
|
||||
laenge++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k = i; k < i + j; k++)
|
||||
{
|
||||
n = (8 / bpp);
|
||||
if (n + i * (8 / bpp) > width)
|
||||
n--;
|
||||
Write (f, &n, 1);
|
||||
Write (f, &Zeile[k], 1);
|
||||
/*printf("%i.#|",n); */
|
||||
laenge += 2;
|
||||
}
|
||||
}
|
||||
i += j;
|
||||
}
|
||||
else
|
||||
/* strings of equal pixels */
|
||||
{
|
||||
n = ketten[i] * (8 / bpp);
|
||||
if (n + i * (8 / bpp) > width)
|
||||
n--;
|
||||
Write (f, &n, 1);
|
||||
Write (f, &Zeile[i], 1);
|
||||
i += ketten[i];
|
||||
laenge += 2;
|
||||
}
|
||||
}
|
||||
Write (f, &buf[14], 2); /* End of row */
|
||||
laenge += 2;
|
||||
/* this can only happen if j jumps over
|
||||
* the end with a 2 in ketten[i+j]
|
||||
*/
|
||||
if (j > (255 / (8 / bpp)))
|
||||
j -= 2;
|
||||
/* 00 01 and 00 02 are reserved */
|
||||
if (j > 2)
|
||||
{
|
||||
Write (f, &buf[12], 1);
|
||||
n = j * (8 / bpp);
|
||||
if (n + i * (8 / bpp) > width)
|
||||
n--;
|
||||
Write (f, &n, 1);
|
||||
laenge += 2;
|
||||
Write (f, &Zeile[i], j);
|
||||
laenge += j;
|
||||
if ((j) % 2)
|
||||
{
|
||||
Write (f, &buf[12], 1);
|
||||
laenge++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k = i; k < i + j; k++)
|
||||
{
|
||||
n = (8 / bpp);
|
||||
if (n + i * (8 / bpp) > width)
|
||||
n--;
|
||||
Write (f, &n, 1);
|
||||
Write (f, &Zeile[k], 1);
|
||||
/*printf("%i.#|",n); */
|
||||
laenge += 2;
|
||||
}
|
||||
}
|
||||
i += j;
|
||||
}
|
||||
else
|
||||
/* strings of equal pixels */
|
||||
{
|
||||
n = ketten[i] * (8 / bpp);
|
||||
if (n + i * (8 / bpp) > width)
|
||||
n--;
|
||||
Write (f, &n, 1);
|
||||
Write (f, &Zeile[i], 1);
|
||||
i += ketten[i];
|
||||
laenge += 2;
|
||||
}
|
||||
}
|
||||
Write (f, &buf[14], 2); /* End of row */
|
||||
laenge += 2;
|
||||
|
||||
cur_progress++;
|
||||
if ((cur_progress % 5) == 0)
|
||||
gimp_progress_update ((gdouble) cur_progress /
|
||||
(gdouble) max_progress);
|
||||
}
|
||||
fseek (f, -2, SEEK_CUR); /* Overwrite last End of row ... */
|
||||
Write (f, &buf[12], 2); /* ... with End of file */
|
||||
cur_progress++;
|
||||
if ((cur_progress % 5) == 0)
|
||||
gimp_progress_update ((gdouble) cur_progress /
|
||||
(gdouble) max_progress);
|
||||
}
|
||||
fseek (f, -2, SEEK_CUR); /* Overwrite last End of row ... */
|
||||
Write (f, &buf[12], 2); /* ... with End of file */
|
||||
|
||||
fseek (f, 0x22, SEEK_SET); /* Write length of image */
|
||||
FromL (laenge, puffer);
|
||||
Write (f, puffer, 4);
|
||||
fseek (f, 0x02, SEEK_SET); /* Write length of file */
|
||||
laenge += (0x36 + MapSize);
|
||||
FromL (laenge, puffer);
|
||||
Write (f, puffer, 4);
|
||||
g_free (ketten);
|
||||
g_free (Zeile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fseek (f, 0x22, SEEK_SET); /* Write length of image */
|
||||
FromL (laenge, puffer);
|
||||
Write (f, puffer, 4);
|
||||
fseek (f, 0x02, SEEK_SET); /* Write length of file */
|
||||
laenge += (0x36 + MapSize);
|
||||
FromL (laenge, puffer);
|
||||
Write (f, puffer, 4);
|
||||
g_free (ketten);
|
||||
g_free (Zeile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gimp_progress_update (1);
|
||||
|
@ -552,12 +553,12 @@ save_dialog (void)
|
|||
|
||||
dlg = gimp_dialog_new (_("Save as BMP"), "bmp",
|
||||
NULL, 0,
|
||||
gimp_standard_help_func, "file-bmp-save",
|
||||
gimp_standard_help_func, "file-bmp-save",
|
||||
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
||||
|
||||
NULL);
|
||||
NULL);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
|
||||
|
|
Loading…
Reference in New Issue