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.
This commit is contained in:
@ -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
|
||||
{
|
||||
|
Reference in New Issue
Block a user