Fix for Bug 159947 - saving 1bpp PCX files
+Allows user to save indexed 1bpp and 4bpp PCX files automatically, depending on the number of colors used. +Creates a general function with parameters for both bpp and # of planes, to handle more PCX file types (1bpp, 2planes; 1bpp, 2planes; 4bpp, 1plane). +Removes assumption when loading colormap that 1bpp files are black & white only; loads both colors from PCX palette header instead. https://bugzilla.gnome.org/show_bug.cgi?id=159947
This commit is contained in:
@ -60,15 +60,10 @@ static void load_4 (FILE *fp,
|
|||||||
gint height,
|
gint height,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
guint16 bytes);
|
guint16 bytes);
|
||||||
static void load_by_bpp (FILE *fp,
|
static void load_sub_8 (FILE *fp,
|
||||||
gint width,
|
gint width,
|
||||||
gint height,
|
gint height,
|
||||||
gint bpp,
|
gint bpp,
|
||||||
guchar *buf,
|
|
||||||
guint16 bytes);
|
|
||||||
static void load_by_plane (FILE *fp,
|
|
||||||
gint width,
|
|
||||||
gint height,
|
|
||||||
gint plane,
|
gint plane,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
guint16 bytes);
|
guint16 bytes);
|
||||||
@ -473,39 +468,39 @@ load_image (const gchar *filename,
|
|||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_1 (fd, width, height, dest, bytesperline);
|
load_1 (fd, width, height, dest, bytesperline);
|
||||||
gimp_image_set_colormap (image, mono, 2);
|
gimp_image_set_colormap (image, pcx_header.colormap, 2);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 2 && pcx_header.bpp == 1)
|
else if (pcx_header.bpp == 1 && pcx_header.planes == 2)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_by_plane (fd, width, height, 2, dest, bytesperline);
|
load_sub_8 (fd, width, height, 1, 2, dest, bytesperline);
|
||||||
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
gimp_image_set_colormap (image, pcx_header.colormap, 4);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 1 && pcx_header.bpp == 2)
|
else if (pcx_header.bpp == 2 && pcx_header.planes == 1)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_by_bpp (fd, width, height, 2, dest, bytesperline);
|
load_sub_8 (fd, width, height, 2, 1, dest, bytesperline);
|
||||||
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
gimp_image_set_colormap (image, pcx_header.colormap, 4);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 3 && pcx_header.bpp == 1)
|
else if (pcx_header.bpp == 1 && pcx_header.planes == 3)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_by_plane (fd, width, height, 3, dest, bytesperline);
|
load_sub_8 (fd, width, height, 1, 3, dest, bytesperline);
|
||||||
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
gimp_image_set_colormap (image, pcx_header.colormap, 8);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 4 && pcx_header.bpp == 1)
|
else if (pcx_header.bpp == 1 && pcx_header.planes == 4)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_4 (fd, width, height, dest, bytesperline);
|
load_4 (fd, width, height, dest, bytesperline);
|
||||||
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 1 && pcx_header.bpp == 4)
|
else if (pcx_header.bpp == 4 && pcx_header.planes == 1)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_by_bpp (fd, width, height, 4, dest, bytesperline);
|
load_sub_8 (fd, width, height, 4, 1, dest, bytesperline);
|
||||||
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
gimp_image_set_colormap (image, pcx_header.colormap, 16);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 1 && pcx_header.bpp == 8)
|
else if (pcx_header.bpp == 8 && pcx_header.planes == 1)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height);
|
dest = g_new (guchar, ((gsize) width) * height);
|
||||||
load_8 (fd, width, height, dest, bytesperline);
|
load_8 (fd, width, height, dest, bytesperline);
|
||||||
@ -513,7 +508,7 @@ load_image (const gchar *filename,
|
|||||||
fread (cmap, 768, 1, fd);
|
fread (cmap, 768, 1, fd);
|
||||||
gimp_image_set_colormap (image, cmap, 256);
|
gimp_image_set_colormap (image, cmap, 256);
|
||||||
}
|
}
|
||||||
else if (pcx_header.planes == 3 && pcx_header.bpp == 8)
|
else if (pcx_header.bpp == 8 && pcx_header.planes == 3)
|
||||||
{
|
{
|
||||||
dest = g_new (guchar, ((gsize) width) * height * 3);
|
dest = g_new (guchar, ((gsize) width) * height * 3);
|
||||||
load_24 (fd, width, height, dest, bytesperline);
|
load_24 (fd, width, height, dest, bytesperline);
|
||||||
@ -639,47 +634,18 @@ load_4 (FILE *fp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_by_bpp (FILE *fp,
|
load_sub_8 (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 width,
|
||||||
gint height,
|
gint height,
|
||||||
|
gint bpp,
|
||||||
gint plane,
|
gint plane,
|
||||||
guchar *buf,
|
guchar *buf,
|
||||||
guint16 bytes)
|
guint16 bytes)
|
||||||
{
|
{
|
||||||
gint x, y, c;
|
gint x, y, c, b;
|
||||||
guchar *line = g_new (guchar, bytes);
|
guchar *line = g_new (guchar, bytes);
|
||||||
|
gint real_bpp = bpp - 1;
|
||||||
|
gint current_bit = 0;
|
||||||
|
|
||||||
for (y = 0; y < height; buf += width, ++y)
|
for (y = 0; y < height; buf += width, ++y)
|
||||||
{
|
{
|
||||||
@ -690,8 +656,12 @@ load_by_plane (FILE *fp,
|
|||||||
readline(fp, line, bytes);
|
readline(fp, line, bytes);
|
||||||
for (x = 0; x < width; ++x)
|
for (x = 0; x < width; ++x)
|
||||||
{
|
{
|
||||||
if (line[x / 8] & (128 >> (x % 8)))
|
for (b = 0; b < bpp; b++)
|
||||||
buf[x] += (1 << c);
|
{
|
||||||
|
current_bit = bpp * x + b;
|
||||||
|
if (line[current_bit / 8] & (128 >> (current_bit % 8)))
|
||||||
|
buf[x] += (1 << (real_bpp - b + c));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gimp_progress_update ((double) y / (double) height);
|
gimp_progress_update ((double) y / (double) height);
|
||||||
@ -794,7 +764,7 @@ save_image (const gchar *filename,
|
|||||||
|
|
||||||
if(colors <= 16)
|
if(colors <= 16)
|
||||||
{
|
{
|
||||||
for(i = 0; i < colors * 3; i++)
|
for(i = 0; i < (colors * 3); i++)
|
||||||
{
|
{
|
||||||
pcx_header.colormap[i] = cmap[i];
|
pcx_header.colormap[i] = cmap[i];
|
||||||
}
|
}
|
||||||
@ -823,6 +793,12 @@ save_image (const gchar *filename,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bytes per Line must be an even number, according to spec */
|
||||||
|
if (pcx_header.bytesperline % 2 != 0)
|
||||||
|
{
|
||||||
|
pcx_header.bytesperline++;
|
||||||
|
}
|
||||||
|
|
||||||
pixels = (guchar *) g_malloc (width * height * pcx_header.planes);
|
pixels = (guchar *) g_malloc (width * height * pcx_header.planes);
|
||||||
|
|
||||||
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
|
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
|
||||||
@ -949,19 +925,19 @@ save_less_than_8 (FILE *fp,
|
|||||||
|
|
||||||
line = (guchar *) g_malloc (((width + 7) / 8) * bpp);
|
line = (guchar *) g_malloc (((width + 7) / 8) * bpp);
|
||||||
|
|
||||||
for(gint x = 0; x < buf_size; x++)
|
for (gint x = 0; x < buf_size; x++)
|
||||||
{
|
{
|
||||||
byte_to_write |= (buf[x] << j);
|
byte_to_write |= (buf[x] << j);
|
||||||
j -= bpp;
|
j -= bpp;
|
||||||
|
|
||||||
if(j < 0 || (x % width == line_end))
|
if (j < 0 || (x % width == line_end))
|
||||||
{
|
{
|
||||||
line[count] = byte_to_write;
|
line[count] = byte_to_write;
|
||||||
count++;
|
count++;
|
||||||
byte_to_write = 0x00;
|
byte_to_write = 0x00;
|
||||||
j = bit_limit;
|
j = bit_limit;
|
||||||
|
|
||||||
if((x % width == line_end))
|
if ((x % width == line_end))
|
||||||
{
|
{
|
||||||
writeline (fp, line, count);
|
writeline (fp, line, count);
|
||||||
count = 0;
|
count = 0;
|
||||||
@ -969,6 +945,7 @@ save_less_than_8 (FILE *fp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g_free (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user