[gimp] plug-ins: fix #5960 Gimp loads 16 bit DDS images with luminosity as 8 bit.
- From: Jacob Boerema <jboerema src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: fix #5960 Gimp loads 16 bit DDS images with luminosity as 8 bit.
- Date: Mon, 26 Apr 2021 21:36:00 +0000 (UTC)
commit fe228a6f6f6b4b1fef1dc1fb5e5cf409fa6a36be
Author: Jacob Boerema <jgboerema gmail com>
Date: Mon Apr 26 17:34:18 2021 -0400
plug-ins: fix #5960 Gimp loads 16 bit DDS images with luminosity as 8 bit.
So far all dds images were loaded as 8 bit per channel which makes
sense for most but not all dds formats.
This commit implements loading in 16 bit for "L16" - a 16 bit
luminance channel.
In addition to that we improve security a bit by not assuming
that L16 is the only left over case but instead explicitly
checking the correct value of rmask for L16.
For other cases we now set an error with enough details
to identify the type of DDS image that needs extra
handling.
plug-ins/file-dds/ddsread.c | 41 ++++++++++++++++++++++++++++++++++-------
1 file changed, 34 insertions(+), 7 deletions(-)
---
diff --git a/plug-ins/file-dds/ddsread.c b/plug-ins/file-dds/ddsread.c
index 2cd07d9d71..8acf616ee7 100644
--- a/plug-ins/file-dds/ddsread.c
+++ b/plug-ins/file-dds/ddsread.c
@@ -57,6 +57,7 @@ typedef struct
guchar rbits, gbits, bbits, abits;
guint rmask, gmask, bmask, amask;
guint bpp, gimp_bpp;
+ guint gimp_bps; /* bytes per sample */
gint tile_height;
guchar *palette;
} dds_load_info_t;
@@ -129,6 +130,7 @@ read_dds (GFile *file,
dds_load_info_t d;
GList *layers;
GimpImageBaseType type;
+ GimpPrecision precision;
gboolean read_mipmaps;
gboolean decode_images;
gint i, j;
@@ -215,6 +217,7 @@ read_dds (GFile *file,
hdr.pixelfmt.flags |= DDPF_ALPHAPIXELS;
}
+ d.gimp_bps = 1; /* Most formats will be converted to 1 byte per sample */
if (hdr.pixelfmt.flags & DDPF_FOURCC)
{
switch (GETL32 (hdr.pixelfmt.fourcc))
@@ -262,11 +265,22 @@ read_dds (GFile *file,
type = GIMP_RGB;
}
- else /* L16 */
+ else if (hdr.pixelfmt.rmask == 0xffff) /* L16 */
{
- d.gimp_bpp = 1;
+ d.gimp_bpp = 2;
+ d.gimp_bps = 2;
type = GIMP_GRAY;
}
+ else
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Unsupported uncompressed dds format: "
+ "bpp: %d, Rmask: %x, Gmask: %x, Bmask: %x, Amask: %x",
+ hdr.pixelfmt.bpp,
+ hdr.pixelfmt.rmask, hdr.pixelfmt.gmask,
+ hdr.pixelfmt.bmask, hdr.pixelfmt.amask);
+ return GIMP_PDB_EXECUTION_ERROR;
+ }
}
else
{
@@ -297,7 +311,16 @@ read_dds (GFile *file,
}
}
- image = gimp_image_new (hdr.width, hdr.height, type);
+ if (d.gimp_bps == 2)
+ {
+ precision = GIMP_PRECISION_U16_NON_LINEAR;
+ }
+ else
+ {
+ precision = GIMP_PRECISION_U8_NON_LINEAR;
+ }
+
+ image = gimp_image_new_with_precision (hdr.width, hdr.height, type, precision);
if (! image)
{
@@ -1009,10 +1032,10 @@ load_layer (FILE *fp,
type = (hdr->pixelfmt.amask == 0x8000) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
bablfmt = (hdr->pixelfmt.amask == 0x8000) ? babl_format ("R'G'B'A u8") : babl_format ("R'G'B' u8");
}
- else /* L16 */
+ else if (hdr->pixelfmt.rmask == 0xffff) /* L16 */
{
type = GIMP_GRAY_IMAGE;
- bablfmt = babl_format ("Y' u8");
+ bablfmt = babl_format ("Y' u16");
}
break;
case 3: type = GIMP_RGB_IMAGE; bablfmt = babl_format ("R'G'B' u8"); break;
@@ -1179,8 +1202,12 @@ load_layer (FILE *fp,
(pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
}
}
- else /* L16 */
- pixels[pos] = (guchar) (255 * ((float)(pixel & 0xffff) / 65535.0f));
+ else if (hdr->pixelfmt.rmask == 0xffff) /* L16 */
+ {
+ guint16 *pixels16 = (guint16 *) &pixels[pos];
+
+ *pixels16 = (guint16) (pixel & 0xffff);
+ }
}
else
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]