stb_image.h: Support 15/16bit per pixel RGB(A) TGAs

stbi__tga_* assumed that 16bit TGAs were Grayscale + Alpha.
However, if the TGA imagetype is not one of the gray ones, it's 16Bit
RGB data, with 5 Bits per channel. If the TGA image descriptor field
has alpha bits (the 3 least significant ones) set, the pixel's most
significant bit is for alpha: 1 for opaque and 0 for translucent.
Furthermore people claim that TGAs can also pretend to have 15bpp,
which is the same as 16bpp but definitely without alpha.

So 15/16bpp TGAs are now decoded to STBI_rgb(_alpha).
pull/208/head
Daniel Gibson 2015-12-05 23:23:12 +01:00
parent 64fa9a3d95
commit 7453e1bfa4
1 changed files with 52 additions and 16 deletions

View File

@ -4813,7 +4813,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
#ifndef STBI_NO_TGA
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
{
int tga_w, tga_h, tga_comp;
int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel;
int sz;
stbi__get8(s); // discard Offset
sz = stbi__get8(s); // color type
@ -4824,6 +4824,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
sz = stbi__get8(s); // image type
// only RGB or grey allowed, +/- RLE
if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0;
tga_image_type = sz;
stbi__skip(s,9);
tga_w = stbi__get16le(s);
if( tga_w < 1 ) {
@ -4835,16 +4836,24 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
stbi__rewind(s);
return 0; // test height
}
sz = stbi__get8(s); // bits per pixel
// only RGB or RGBA or grey allowed
if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) {
stbi__rewind(s);
return 0;
tga_bits_per_pixel = stbi__get8(s); // bits per pixel
sz = stbi__get8(s) & 15; // alpha bits
// only RGB or RGBA (incl. 16bit) or grey allowed
// FIXME: don't we have to use the colormap's bpp if indexed?
switch(tga_bits_per_pixel) {
case 8: tga_comp = STBI_grey; break;
case 15: tga_comp = STBI_rgb; break;
case 16:
if((tga_image_type == 3) || (tga_image_type == 11)) tga_comp = STBI_grey_alpha;
else tga_comp = sz ? STBI_rgb_alpha : STBI_rgb; // most signif. bit might be for alpha
break;
case 24: // fall-through
case 32: tga_comp = tga_bits_per_pixel/8; break;
default: stbi__rewind(s); return 0;
}
tga_comp = sz;
if (x) *x = tga_w;
if (y) *y = tga_h;
if (comp) *comp = tga_comp / 8;
if (comp) *comp = tga_comp;
return 1; // seems to have passed everything
}
@ -4865,7 +4874,7 @@ static int stbi__tga_test(stbi__context *s)
if ( stbi__get16be(s) < 1 ) return 0; // test width
if ( stbi__get16be(s) < 1 ) return 0; // test height
sz = stbi__get8(s); // bits per pixel
if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) )
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) )
res = 0;
else
res = 1;
@ -4888,8 +4897,9 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
int tga_width = stbi__get16le(s);
int tga_height = stbi__get16le(s);
int tga_bits_per_pixel = stbi__get8(s);
int tga_comp = tga_bits_per_pixel / 8;
int tga_comp, tga_rgb16=0;
int tga_inverted = stbi__get8(s);
int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits
// image data
unsigned char *tga_data;
unsigned char *tga_palette = NULL;
@ -4905,14 +4915,13 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
tga_image_type -= 8;
tga_is_RLE = 1;
}
/* int tga_alpha_bits = tga_inverted & 15; */
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
// error check
if ( //(tga_indexed) ||
(tga_width < 1) || (tga_height < 1) ||
(tga_image_type < 1) || (tga_image_type > 3) ||
((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) &&
((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 15) && (tga_bits_per_pixel != 16) &&
(tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32))
)
{
@ -4924,6 +4933,17 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
{
tga_comp = tga_palette_bits / 8;
}
else {
switch(tga_bits_per_pixel) {
case 8: tga_comp = STBI_grey; break;
case 15: tga_comp = STBI_rgb; tga_rgb16=1; break;
case 16:
if (tga_image_type == 3) tga_comp = STBI_grey_alpha;
else { tga_comp = tga_alpha_bits ? STBI_rgb_alpha : STBI_rgb; tga_rgb16=1; }
break;
default: tga_comp = tga_bits_per_pixel / 8; // incl. 24 and 32
}
}
// tga info
*x = tga_width;
@ -4936,7 +4956,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
// skip to the data's starting position (offset usually = 0)
stbi__skip(s, tga_offset );
if ( !tga_indexed && !tga_is_RLE) {
if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
for (i=0; i < tga_height; ++i) {
int row = tga_inverted ? tga_height -i - 1 : i;
stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
@ -4999,8 +5019,24 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
{
raw_data[j] = tga_palette[pal_idx+j];
}
} else
{
} else if(tga_rgb16) {
// convert from 16bit RGB(A) to 24/32bit RGB(A)
stbi__uint16 px = stbi__get16le(s);
stbi__uint16 fiveBitMask = 31;
// we have 3 channels with 5bits each
int r = (px >> 10) & fiveBitMask;
int g = (px >> 5) & fiveBitMask;
int b = px & fiveBitMask;
raw_data[0] = (r * 255)/31;
raw_data[1] = (g * 255)/31;
raw_data[2] = (b * 255)/31;
if(tga_comp == STBI_rgb_alpha) {
// most significant bit set to 1 for opaque, 0 for trans., according to
// http://www.imagemagick.org/discourse-server/viewtopic.php?t=27469
raw_data[3] = !(px & 0x8000) * 255;
}
} else {
// read in the data raw
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
{
@ -5043,7 +5079,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
}
// swap RGB
if (tga_comp >= 3)
if (tga_comp >= 3 && !tga_rgb16)
{
unsigned char* tga_pixel = tga_data;
for (i=0; i < tga_width * tga_height; ++i)