mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-20 19:43:01 +00:00
file-xwd: support 32bit (ARGB) xwd import
No saving for now...
This commit is contained in:
parent
293bf27346
commit
cfe5dd8bd4
|
@ -31,7 +31,7 @@
|
|||
* 2 | 1,...,8 | 8
|
||||
* 2 | 1,...,16 | 16
|
||||
* 2 | 1,...,24 | 24
|
||||
* 2 | 1,...,24 | 32
|
||||
* 2 | 1,...,32 | 32
|
||||
*/
|
||||
/* Event history:
|
||||
* PK = Peter Kirchgessner, ME = Mattias Engdegård
|
||||
|
@ -154,6 +154,7 @@ static gint32 create_new_image (const gchar *filename,
|
|||
guint width,
|
||||
guint height,
|
||||
GimpImageBaseType type,
|
||||
GimpImageType gdtype,
|
||||
gint32 *layer_ID,
|
||||
GimpDrawable **drawable,
|
||||
GimpPixelRgn *pixel_rgn);
|
||||
|
@ -188,6 +189,10 @@ static gint32 load_xwd_f2_d24_b32 (const gchar *,
|
|||
L_XWDFILEHEADER *,
|
||||
L_XWDCOLOR *,
|
||||
GError **);
|
||||
static gint32 load_xwd_f2_d32_b32 (const gchar *,
|
||||
FILE *,
|
||||
L_XWDFILEHEADER *,
|
||||
L_XWDCOLOR *);
|
||||
static gint32 load_xwd_f1_d24_b1 (const gchar *,
|
||||
FILE *,
|
||||
L_XWDFILEHEADER *,
|
||||
|
@ -565,6 +570,10 @@ load_image (const gchar *filename,
|
|||
image_ID = load_xwd_f2_d24_b32 (filename, ifp, &xwdhdr, xwdcolmap,
|
||||
error);
|
||||
}
|
||||
else if ((depth <= 32) && (bpp == 32))
|
||||
{
|
||||
image_ID = load_xwd_f2_d32_b32 (filename, ifp, &xwdhdr, xwdcolmap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
gimp_progress_update (1.0);
|
||||
|
@ -1186,28 +1195,12 @@ create_new_image (const gchar *filename,
|
|||
guint width,
|
||||
guint height,
|
||||
GimpImageBaseType type,
|
||||
GimpImageType gdtype,
|
||||
gint32 *layer_ID,
|
||||
GimpDrawable **drawable,
|
||||
GimpPixelRgn *pixel_rgn)
|
||||
{
|
||||
gint32 image_ID;
|
||||
GimpImageType gdtype;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GIMP_GRAY:
|
||||
gdtype = GIMP_GRAY_IMAGE;
|
||||
break;
|
||||
case GIMP_INDEXED:
|
||||
gdtype = GIMP_INDEXED_IMAGE;
|
||||
break;
|
||||
case GIMP_RGB:
|
||||
gdtype = GIMP_RGB_IMAGE;
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unknown image type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
image_ID = gimp_image_new (width, height, type);
|
||||
gimp_image_set_filename (image_ID, filename);
|
||||
|
@ -1253,7 +1246,8 @@ load_xwd_f2_d1_b1 (const gchar *filename,
|
|||
height = xwdhdr->l_pixmap_height;
|
||||
|
||||
image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
|
||||
&layer_ID, &drawable, &pixel_rgn);
|
||||
GIMP_INDEXED_IMAGE, &layer_ID, &drawable,
|
||||
&pixel_rgn);
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
data = g_malloc (tile_height * width);
|
||||
|
@ -1408,6 +1402,7 @@ load_xwd_f2_d8_b8 (const gchar *filename,
|
|||
|
||||
image_ID = create_new_image (filename, width, height,
|
||||
grayscale ? GIMP_GRAY : GIMP_INDEXED,
|
||||
grayscale ? GIMP_GRAY_IMAGE : GIMP_INDEXED_IMAGE,
|
||||
&layer_ID, &drawable, &pixel_rgn);
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
|
@ -1497,7 +1492,8 @@ load_xwd_f2_d16_b16 (const gchar *filename,
|
|||
height = xwdhdr->l_pixmap_height;
|
||||
|
||||
image_ID = create_new_image (filename, width, height, GIMP_RGB,
|
||||
&layer_ID, &drawable, &pixel_rgn);
|
||||
GIMP_RGB_IMAGE, &layer_ID, &drawable,
|
||||
&pixel_rgn);
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
data = g_malloc (tile_height * width * 3);
|
||||
|
@ -1695,7 +1691,8 @@ load_xwd_f2_d24_b32 (const gchar *filename,
|
|||
}
|
||||
|
||||
image_ID = create_new_image (filename, width, height, GIMP_RGB,
|
||||
&layer_ID, &drawable, &pixel_rgn);
|
||||
GIMP_RGB_IMAGE, &layer_ID, &drawable,
|
||||
&pixel_rgn);
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
data = g_malloc (tile_height * width * 3);
|
||||
|
@ -1836,6 +1833,163 @@ load_xwd_f2_d24_b32 (const gchar *filename,
|
|||
return err ? -1 : image_ID;
|
||||
}
|
||||
|
||||
/* Load XWD with pixmap_format 2, pixmap_depth up to 32, bits_per_pixel 32 */
|
||||
|
||||
static gint32
|
||||
load_xwd_f2_d32_b32 (const gchar *filename,
|
||||
FILE *ifp,
|
||||
L_XWDFILEHEADER *xwdhdr,
|
||||
L_XWDCOLOR *xwdcolmap)
|
||||
{
|
||||
register guchar *dest, lsbyte_first;
|
||||
gint width, height, linepad, i, j, c0, c1, c2, c3;
|
||||
gint tile_height, scan_lines;
|
||||
L_CARD32 pixelval;
|
||||
gint red, green, blue, alpha, ncols;
|
||||
gint maxred, maxgreen, maxblue, maxalpha;
|
||||
gulong redmask, greenmask, bluemask, alphamask;
|
||||
guint redshift, greenshift, blueshift, alphashift;
|
||||
guchar redmap[256], greenmap[256], bluemap[256], alphamap[256];
|
||||
guchar *data;
|
||||
PIXEL_MAP pixel_map;
|
||||
gint err = 0;
|
||||
gint32 layer_ID, image_ID;
|
||||
GimpPixelRgn pixel_rgn;
|
||||
GimpDrawable *drawable;
|
||||
|
||||
#ifdef XWD_DEBUG
|
||||
printf ("load_xwd_f2_d32_b32 (%s)\n", filename);
|
||||
#endif
|
||||
|
||||
width = xwdhdr->l_pixmap_width;
|
||||
height = xwdhdr->l_pixmap_height;
|
||||
|
||||
image_ID = create_new_image (filename, width, height, GIMP_RGB,
|
||||
GIMP_RGBA_IMAGE, &layer_ID, &drawable,
|
||||
&pixel_rgn);
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
data = g_malloc (tile_height * width * 4);
|
||||
|
||||
redmask = xwdhdr->l_red_mask;
|
||||
greenmask = xwdhdr->l_green_mask;
|
||||
bluemask = xwdhdr->l_blue_mask;
|
||||
|
||||
if (redmask == 0) redmask = 0xff0000;
|
||||
if (greenmask == 0) greenmask = 0x00ff00;
|
||||
if (bluemask == 0) bluemask = 0x0000ff;
|
||||
alphamask = 0xffffffff & ~(redmask | greenmask | bluemask);
|
||||
|
||||
/* How to shift RGB to be right aligned ? */
|
||||
/* (We rely on the the mask bits are grouped and not mixed) */
|
||||
redshift = greenshift = blueshift = alphashift = 0;
|
||||
|
||||
while (((1 << redshift) & redmask) == 0) redshift++;
|
||||
while (((1 << greenshift) & greenmask) == 0) greenshift++;
|
||||
while (((1 << blueshift) & bluemask) == 0) blueshift++;
|
||||
while (((1 << alphashift) & alphamask) == 0) alphashift++;
|
||||
|
||||
/* The bits_per_rgb may not be correct. Use redmask instead */
|
||||
|
||||
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
|
||||
maxred = (1 << maxred) - 1;
|
||||
|
||||
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
|
||||
maxgreen = (1 << maxgreen) - 1;
|
||||
|
||||
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
|
||||
maxblue = (1 << maxblue) - 1;
|
||||
|
||||
maxalpha = 0; while (alphamask >> (alphashift + maxalpha)) maxalpha++;
|
||||
maxalpha = (1 << maxalpha) - 1;
|
||||
|
||||
/* Set map-arrays for red, green, blue */
|
||||
for (red = 0; red <= maxred; red++)
|
||||
redmap[red] = (red * 255) / maxred;
|
||||
for (green = 0; green <= maxgreen; green++)
|
||||
greenmap[green] = (green * 255) / maxgreen;
|
||||
for (blue = 0; blue <= maxblue; blue++)
|
||||
bluemap[blue] = (blue * 255) / maxblue;
|
||||
for (alpha = 0; alpha <= maxalpha; alpha++)
|
||||
alphamap[alpha] = (alpha * 255) / maxalpha;
|
||||
|
||||
ncols = xwdhdr->l_colormap_entries;
|
||||
if (xwdhdr->l_ncolors < ncols)
|
||||
ncols = xwdhdr->l_ncolors;
|
||||
|
||||
set_pixelmap (ncols, xwdcolmap, &pixel_map);
|
||||
|
||||
/* What do we have to consume after a line has finished ? */
|
||||
linepad = xwdhdr->l_bytes_per_line
|
||||
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
|
||||
if (linepad < 0) linepad = 0;
|
||||
|
||||
lsbyte_first = (xwdhdr->l_byte_order == 0);
|
||||
|
||||
dest = data;
|
||||
scan_lines = 0;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
c0 = getc (ifp);
|
||||
c1 = getc (ifp);
|
||||
c2 = getc (ifp);
|
||||
c3 = getc (ifp);
|
||||
if (c3 < 0)
|
||||
{
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
if (lsbyte_first)
|
||||
pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
|
||||
else
|
||||
pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
|
||||
|
||||
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
|
||||
{
|
||||
/* FIXME: is it always transparent or encoded in an unknown way? */
|
||||
*(dest+3) = 0x00;
|
||||
dest += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(dest++) = redmap[(pixelval & redmask) >> redshift];
|
||||
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
|
||||
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
|
||||
*(dest++) = alphamap[(pixelval & alphamask) >> alphashift];
|
||||
}
|
||||
}
|
||||
scan_lines++;
|
||||
|
||||
if (err)
|
||||
break;
|
||||
|
||||
for (j = 0; j < linepad; j++)
|
||||
getc (ifp);
|
||||
|
||||
if ((i % 20) == 0)
|
||||
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
|
||||
|
||||
if ((scan_lines == tile_height) || ((i+1) == height))
|
||||
{
|
||||
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
|
||||
width, scan_lines);
|
||||
scan_lines = 0;
|
||||
dest = data;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (data);
|
||||
|
||||
if (err)
|
||||
g_message (_("EOF encountered on reading"));
|
||||
|
||||
gimp_drawable_flush (drawable);
|
||||
|
||||
return err ? -1 : image_ID;
|
||||
}
|
||||
|
||||
/* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
|
||||
|
||||
|
@ -1943,6 +2097,7 @@ load_xwd_f1_d24_b1 (const gchar *filename,
|
|||
|
||||
image_ID = create_new_image (filename, width, height,
|
||||
indexed ? GIMP_INDEXED : GIMP_RGB,
|
||||
indexed ? GIMP_INDEXED_IMAGE : GIMP_RGB_IMAGE,
|
||||
&layer_ID, &drawable, &pixel_rgn);
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
|
|
Loading…
Reference in a new issue