stb_image.h: Fix TGA colormap support
* Calculate correct stb format (incl. proper 16bit support) also when using a colormap (palette) * Create colormap with tga_comp, to correctly support 16bit RGB (instead of using tga_palette_bits/8 and just copying the data) * For TGAs with colormap, the TGA bits per pixel field specifies the size of an index to the colormap - the "real" color depth of the image is saved in the color map specification's bits per pixel field. I think only 8 and 16bit indices make sense (16 should be supported, otherwise the colormap length could be u8 instead of u16), so I added support for both. * Helper functions stbi__tga_get_comp() to calculate stb pixelformat and stbi__tga_read_rgb16() to read one 16bit pixel and convert it to 24/32bit RGB(A) - for less duplicate code
This commit is contained in:
parent
57409c3d15
commit
d235049322
134
stb_image.h
134
stb_image.h
@ -4811,6 +4811,26 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// Targa Truevision - TGA
|
// Targa Truevision - TGA
|
||||||
// by Jonathan Dummer
|
// by Jonathan Dummer
|
||||||
#ifndef STBI_NO_TGA
|
#ifndef STBI_NO_TGA
|
||||||
|
// returns STBI_rgb or whatever, 0 on error
|
||||||
|
static int stbi__tga_get_comp(int bits_per_pixel, int alpha_bits, int is_grey, int* is_rgb16)
|
||||||
|
{
|
||||||
|
// only RGB or RGBA (incl. 16bit) or grey allowed
|
||||||
|
if(is_rgb16) *is_rgb16 = 0;
|
||||||
|
switch(bits_per_pixel) {
|
||||||
|
case 8: return STBI_grey;
|
||||||
|
case 15: if(is_rgb16) *is_rgb16 = 1; return STBI_rgb;
|
||||||
|
case 16:
|
||||||
|
if(is_grey) return STBI_grey_alpha;
|
||||||
|
else {
|
||||||
|
if(is_rgb16) *is_rgb16 = 1;
|
||||||
|
return alpha_bits ? STBI_rgb_alpha : STBI_rgb; // most signif. bit might be for alpha
|
||||||
|
}
|
||||||
|
case 24: // fall-through
|
||||||
|
case 32: return bits_per_pixel/8;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
||||||
{
|
{
|
||||||
int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
|
int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
|
||||||
@ -4854,6 +4874,7 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
|||||||
return 0; // test height
|
return 0; // test height
|
||||||
}
|
}
|
||||||
tga_bits_per_pixel = stbi__get8(s); // bits per pixel
|
tga_bits_per_pixel = stbi__get8(s); // bits per pixel
|
||||||
|
sz = stbi__get8(s) & 15; // alpha bits
|
||||||
if (tga_colormap_bpp != 0) {
|
if (tga_colormap_bpp != 0) {
|
||||||
if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
|
if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
|
||||||
// when using a colormap, tga_bits_per_pixel is the size of the indexes
|
// when using a colormap, tga_bits_per_pixel is the size of the indexes
|
||||||
@ -4861,20 +4882,13 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
|||||||
stbi__rewind(s);
|
stbi__rewind(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
tga_bits_per_pixel = tga_colormap_bpp; // make sure colormap's bpp are tested for tga_comp
|
tga_comp = stbi__tga_get_comp(tga_colormap_bpp, sz, 0, NULL);
|
||||||
|
} else {
|
||||||
|
tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, sz, (tga_image_type == 3) || (tga_image_type == 11), NULL);
|
||||||
}
|
}
|
||||||
sz = stbi__get8(s) & 15; // alpha bits
|
if(!tga_comp) {
|
||||||
// only RGB or RGBA (incl. 16bit) or grey allowed
|
stbi__rewind(s);
|
||||||
switch(tga_bits_per_pixel) {
|
return 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (x) *x = tga_w;
|
if (x) *x = tga_w;
|
||||||
if (y) *y = tga_h;
|
if (y) *y = tga_h;
|
||||||
@ -4913,6 +4927,27 @@ errorEnd:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read 16bit value and convert to 24/32bit RGB(A)
|
||||||
|
void stbi__tga_read_rgb16(stbi__context *s, int has_alpha, stbi_uc* out)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
// Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
|
||||||
|
out[0] = (r * 255)/31;
|
||||||
|
out[1] = (g * 255)/31;
|
||||||
|
out[2] = (b * 255)/31;
|
||||||
|
|
||||||
|
if(has_alpha) {
|
||||||
|
// most significant bit set to 1 for opaque, 0 for trans., according to
|
||||||
|
// http://www.imagemagick.org/discourse-server/viewtopic.php?t=27469
|
||||||
|
out[3] = !(px & 0x8000) * 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||||
{
|
{
|
||||||
// read in the TGA header stuff
|
// read in the TGA header stuff
|
||||||
@ -4949,21 +4984,11 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
|
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
|
||||||
|
|
||||||
// If I'm paletted, then I'll use the number of bits from the palette
|
// If I'm paletted, then I'll use the number of bits from the palette
|
||||||
if ( tga_indexed )
|
if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, tga_alpha_bits, 0, &tga_rgb16);
|
||||||
{
|
else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, tga_alpha_bits, (tga_image_type == 3), &tga_rgb16);
|
||||||
tga_comp = tga_palette_bits / 8;
|
|
||||||
}
|
if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
|
||||||
else {
|
return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
|
||||||
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
|
// tga info
|
||||||
*x = tga_width;
|
*x = tga_width;
|
||||||
@ -4989,15 +5014,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// any data to skip? (offset usually = 0)
|
// any data to skip? (offset usually = 0)
|
||||||
stbi__skip(s, tga_palette_start );
|
stbi__skip(s, tga_palette_start );
|
||||||
// load the palette
|
// load the palette
|
||||||
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 );
|
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp );
|
||||||
if (!tga_palette) {
|
if (!tga_palette) {
|
||||||
STBI_FREE(tga_data);
|
STBI_FREE(tga_data);
|
||||||
return stbi__errpuc("outofmem", "Out of memory");
|
return stbi__errpuc("outofmem", "Out of memory");
|
||||||
}
|
}
|
||||||
if (!stbi__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) {
|
if (tga_rgb16) {
|
||||||
STBI_FREE(tga_data);
|
stbi_uc *pal_entry = tga_palette;
|
||||||
STBI_FREE(tga_palette);
|
STBI_ASSERT(tga_comp == STBI_rgb || tga_comp == STBI_rgb_alpha);
|
||||||
return stbi__errpuc("bad palette", "Corrupt TGA");
|
for (i=0; i < tga_palette_len; ++i) {
|
||||||
|
stbi__tga_read_rgb16(s, tga_comp == STBI_rgb_alpha, pal_entry);
|
||||||
|
pal_entry += tga_comp;
|
||||||
|
}
|
||||||
|
} else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
|
||||||
|
STBI_FREE(tga_data);
|
||||||
|
STBI_FREE(tga_palette);
|
||||||
|
return stbi__errpuc("bad palette", "Corrupt TGA");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// load the data
|
// load the data
|
||||||
@ -5027,39 +5059,21 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
// load however much data we did have
|
// load however much data we did have
|
||||||
if ( tga_indexed )
|
if ( tga_indexed )
|
||||||
{
|
{
|
||||||
// read in 1 byte, then perform the lookup
|
// read in index, then perform the lookup
|
||||||
int pal_idx = stbi__get8(s);
|
int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
|
||||||
if ( pal_idx >= tga_palette_len )
|
if ( pal_idx >= tga_palette_len ) {
|
||||||
{
|
// invalid index
|
||||||
// invalid index
|
|
||||||
pal_idx = 0;
|
pal_idx = 0;
|
||||||
}
|
}
|
||||||
pal_idx *= tga_bits_per_pixel / 8;
|
pal_idx *= tga_comp;
|
||||||
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
for (j = 0; j < tga_comp; ++j) {
|
||||||
{
|
|
||||||
raw_data[j] = tga_palette[pal_idx+j];
|
raw_data[j] = tga_palette[pal_idx+j];
|
||||||
}
|
}
|
||||||
} else if(tga_rgb16) {
|
} else if(tga_rgb16) {
|
||||||
// convert from 16bit RGB(A) to 24/32bit RGB(A)
|
stbi__tga_read_rgb16(s, tga_comp == STBI_rgb_alpha, raw_data);
|
||||||
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 {
|
} else {
|
||||||
// read in the data raw
|
// read in the data raw
|
||||||
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
for (j = 0; j < tga_comp; ++j) {
|
||||||
{
|
|
||||||
raw_data[j] = stbi__get8(s);
|
raw_data[j] = stbi__get8(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5098,7 +5112,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// swap RGB
|
// swap RGB - if the source data was RGB16, it already is in the right order
|
||||||
if (tga_comp >= 3 && !tga_rgb16)
|
if (tga_comp >= 3 && !tga_rgb16)
|
||||||
{
|
{
|
||||||
unsigned char* tga_pixel = tga_data;
|
unsigned char* tga_pixel = tga_data;
|
||||||
|
Loading…
Reference in New Issue
Block a user