stb_image.h: Improve stbi__tga_info() and stbi__tga_test()

* for paletted images, .._info()'s comp should be based on the palette's
  bits per pixel, not the images bits per pixel (which describes the
  size of an index into the palette and is also checked now)
* make sure the color (map) type and the image type fields of the header
  are consistent (=> if TGA color type is 1 for paletted, the TGA image
  type must be 1 or 9)
* .._test() does some more checks and uses stbi__get16le() instead of
  stbi__get16be() - TGA is little endian.
* .._test() now always rewinds (sometimes it used to do only return 0;
  without rewinding)
* remove "error check" at the beginning of stbi__tga_load(), because
  all that is already tested in stbi__tga_test()
pull/208/head
Daniel Gibson 2015-12-06 00:30:16 +01:00
parent 7453e1bfa4
commit 57409c3d15
1 changed files with 57 additions and 37 deletions

View File

@ -4813,19 +4813,36 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
#ifndef STBI_NO_TGA #ifndef STBI_NO_TGA
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; int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
int sz; int sz, tga_colormap_type;
stbi__get8(s); // discard Offset stbi__get8(s); // discard Offset
sz = stbi__get8(s); // color type tga_colormap_type = stbi__get8(s); // colormap type
if( sz > 1 ) { if( tga_colormap_type > 1 ) {
stbi__rewind(s); stbi__rewind(s);
return 0; // only RGB or indexed allowed return 0; // only RGB or indexed allowed
} }
sz = stbi__get8(s); // image type tga_image_type = stbi__get8(s); // image type
// only RGB or grey allowed, +/- RLE if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; if (tga_image_type != 1 && tga_image_type != 9) {
tga_image_type = sz; stbi__rewind(s);
stbi__skip(s,9); return 0;
}
stbi__skip(s,4); // skip index of first colormap entry and number of entries
sz = stbi__get8(s); // check bits per palette color entry
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
stbi__rewind(s);
return 0;
}
stbi__skip(s,4); // skip image x and y origin
tga_colormap_bpp = sz;
} else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
stbi__rewind(s);
return 0; // only RGB or grey allowed, +/- RLE
}
stbi__skip(s,9); // skip colormap specification and image x/y origin
tga_colormap_bpp = 0;
}
tga_w = stbi__get16le(s); tga_w = stbi__get16le(s);
if( tga_w < 1 ) { if( tga_w < 1 ) {
stbi__rewind(s); stbi__rewind(s);
@ -4837,9 +4854,17 @@ 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
if (tga_colormap_bpp != 0) {
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
// I don't think anything but 8 or 16bit indexes makes sense
stbi__rewind(s);
return 0;
}
tga_bits_per_pixel = tga_colormap_bpp; // make sure colormap's bpp are tested for tga_comp
}
sz = stbi__get8(s) & 15; // alpha bits sz = stbi__get8(s) & 15; // alpha bits
// only RGB or RGBA (incl. 16bit) or grey allowed // 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) { switch(tga_bits_per_pixel) {
case 8: tga_comp = STBI_grey; break; case 8: tga_comp = STBI_grey; break;
case 15: tga_comp = STBI_rgb; break; case 15: tga_comp = STBI_rgb; break;
@ -4859,25 +4884,31 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
static int stbi__tga_test(stbi__context *s) static int stbi__tga_test(stbi__context *s)
{ {
int res; int res = 0;
int sz; int sz, tga_color_type;
stbi__get8(s); // discard Offset stbi__get8(s); // discard Offset
sz = stbi__get8(s); // color type tga_color_type = stbi__get8(s); // color type
if ( sz > 1 ) return 0; // only RGB or indexed allowed if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed
sz = stbi__get8(s); // image type sz = stbi__get8(s); // image type
if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE if ( tga_color_type == 1 ) { // colormapped (paletted) image
stbi__get16be(s); // discard palette start if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
stbi__get16be(s); // discard palette length stbi__skip(s,4); // skip index of first colormap entry and number of entries
stbi__get8(s); // discard bits per palette color entry sz = stbi__get8(s); // check bits per palette color entry
stbi__get16be(s); // discard x origin if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
stbi__get16be(s); // discard y origin stbi__skip(s,4); // skip image x and y origin
if ( stbi__get16be(s) < 1 ) return 0; // test width } else { // "normal" image w/o colormap
if ( stbi__get16be(s) < 1 ) return 0; // test height if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
stbi__skip(s,9); // skip colormap specification and image x/y origin
}
if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width
if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height
sz = stbi__get8(s); // bits per pixel sz = stbi__get8(s); // bits per pixel
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
res = 0; if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
else
res = 1; res = 1; // if we got this far, everything's good and we can return 1 instead of 0
errorEnd:
stbi__rewind(s); stbi__rewind(s);
return res; return res;
} }
@ -4917,17 +4948,6 @@ 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);
// 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 != 15) && (tga_bits_per_pixel != 16) &&
(tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32))
)
{
return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA
}
// 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 )
{ {