tga optimizations
This commit is contained in:
parent
fc0bfd1b71
commit
f0976fd312
256
stb_image.c
256
stb_image.c
@ -22,7 +22,7 @@
|
|||||||
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
||||||
|
|
||||||
Latest revisions:
|
Latest revisions:
|
||||||
1.35 (2014-05-27) warnings, bugfixes, etc
|
1.35 (2014-05-27) warnings, bugfixes, TGA optimization, etc
|
||||||
1.34 (unknown ) warning fix
|
1.34 (unknown ) warning fix
|
||||||
1.33 (2011-07-14) minor fixes suggested by Dave Moore
|
1.33 (2011-07-14) minor fixes suggested by Dave Moore
|
||||||
1.32 (2011-07-13) info support for all filetypes (SpartanJ)
|
1.32 (2011-07-13) info support for all filetypes (SpartanJ)
|
||||||
@ -57,7 +57,7 @@
|
|||||||
John Bartholomew
|
John Bartholomew
|
||||||
Optimizations & bugfixes Ken Hamada
|
Optimizations & bugfixes Ken Hamada
|
||||||
Fabian "ryg" Giesen Cort Stratton
|
Fabian "ryg" Giesen Cort Stratton
|
||||||
Blazej Dariusz Roszkowski
|
Arseny Kapoulkine Blazej Dariusz Roszkowski
|
||||||
Thibault Reuille
|
Thibault Reuille
|
||||||
If your name should be here but Paul Du Bois
|
If your name should be here but Paul Du Bois
|
||||||
isn't let Sean know. Guillaume George
|
isn't let Sean know. Guillaume George
|
||||||
@ -3260,13 +3260,13 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
|||||||
int tga_width = get16le(s);
|
int tga_width = get16le(s);
|
||||||
int tga_height = get16le(s);
|
int tga_height = get16le(s);
|
||||||
int tga_bits_per_pixel = get8u(s);
|
int tga_bits_per_pixel = get8u(s);
|
||||||
|
int tga_comp = tga_bits_per_pixel / 8;
|
||||||
int tga_inverted = get8u(s);
|
int tga_inverted = get8u(s);
|
||||||
// image data
|
// image data
|
||||||
unsigned char *tga_data;
|
unsigned char *tga_data;
|
||||||
unsigned char *tga_palette = NULL;
|
unsigned char *tga_palette = NULL;
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned char raw_data[4];
|
unsigned char raw_data[4];
|
||||||
unsigned char trans_data[4];
|
|
||||||
int RLE_count = 0;
|
int RLE_count = 0;
|
||||||
int RLE_repeating = 0;
|
int RLE_repeating = 0;
|
||||||
int read_next_pixel = 1;
|
int read_next_pixel = 1;
|
||||||
@ -3294,178 +3294,143 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
|||||||
// 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_bits_per_pixel = tga_palette_bits;
|
tga_comp = tga_palette_bits / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tga info
|
// tga info
|
||||||
*x = tga_width;
|
*x = tga_width;
|
||||||
*y = tga_height;
|
*y = tga_height;
|
||||||
if ( (req_comp < 1) || (req_comp > 4) )
|
if (comp) *comp = tga_comp;
|
||||||
{
|
|
||||||
// just use whatever the file was
|
|
||||||
req_comp = tga_bits_per_pixel / 8;
|
|
||||||
*comp = req_comp;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// force a new number of components
|
|
||||||
*comp = tga_bits_per_pixel/8;
|
|
||||||
}
|
|
||||||
tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp );
|
tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp );
|
||||||
if (!tga_data) return epuc("outofmem", "Out of memory");
|
if (!tga_data) return epuc("outofmem", "Out of memory");
|
||||||
|
|
||||||
// skip to the data's starting position (offset usually = 0)
|
// skip to the data's starting position (offset usually = 0)
|
||||||
skip(s, tga_offset );
|
skip(s, tga_offset );
|
||||||
// do I need to load a palette?
|
|
||||||
if ( tga_indexed )
|
if ( !tga_indexed && !tga_is_RLE) {
|
||||||
{
|
for (i=0; i < tga_height; ++i) {
|
||||||
// any data to skip? (offset usually = 0)
|
int y = tga_inverted ? tga_height -i - 1 : i;
|
||||||
skip(s, tga_palette_start );
|
stbi__uint8 *tga_row = tga_data + y*tga_width*tga_comp;
|
||||||
// load the palette
|
getn(s, tga_row, tga_width * tga_comp);
|
||||||
tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 );
|
|
||||||
if (!tga_palette) {
|
|
||||||
free(tga_data);
|
|
||||||
return epuc("outofmem", "Out of memory");
|
|
||||||
}
|
}
|
||||||
if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) {
|
} else {
|
||||||
free(tga_data);
|
// do I need to load a palette?
|
||||||
free(tga_palette);
|
if ( tga_indexed)
|
||||||
return epuc("bad palette", "Corrupt TGA");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// load the data
|
|
||||||
trans_data[0] = trans_data[1] = trans_data[2] = trans_data[3] = 0;
|
|
||||||
for (i=0; i < tga_width * tga_height; ++i)
|
|
||||||
{
|
|
||||||
// if I'm in RLE mode, do I need to get a RLE chunk?
|
|
||||||
if ( tga_is_RLE )
|
|
||||||
{
|
{
|
||||||
if ( RLE_count == 0 )
|
// any data to skip? (offset usually = 0)
|
||||||
{
|
skip(s, tga_palette_start );
|
||||||
// yep, get the next byte as a RLE command
|
// load the palette
|
||||||
int RLE_cmd = get8u(s);
|
tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 );
|
||||||
RLE_count = 1 + (RLE_cmd & 127);
|
if (!tga_palette) {
|
||||||
RLE_repeating = RLE_cmd >> 7;
|
free(tga_data);
|
||||||
read_next_pixel = 1;
|
return epuc("outofmem", "Out of memory");
|
||||||
} else if ( !RLE_repeating )
|
}
|
||||||
{
|
if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) {
|
||||||
read_next_pixel = 1;
|
free(tga_data);
|
||||||
|
free(tga_palette);
|
||||||
|
return epuc("bad palette", "Corrupt TGA");
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
{
|
|
||||||
read_next_pixel = 1;
|
|
||||||
}
|
}
|
||||||
// OK, if I need to read a pixel, do it now
|
// load the data
|
||||||
if ( read_next_pixel )
|
for (i=0; i < tga_width * tga_height; ++i)
|
||||||
{
|
{
|
||||||
// load however much data we did have
|
// if I'm in RLE mode, do I need to get a RLE chunk?
|
||||||
if ( tga_indexed )
|
if ( tga_is_RLE )
|
||||||
{
|
{
|
||||||
// read in 1 byte, then perform the lookup
|
if ( RLE_count == 0 )
|
||||||
int pal_idx = get8u(s);
|
|
||||||
if ( pal_idx >= tga_palette_len )
|
|
||||||
{
|
{
|
||||||
// invalid index
|
// yep, get the next byte as a RLE command
|
||||||
pal_idx = 0;
|
int RLE_cmd = get8u(s);
|
||||||
}
|
RLE_count = 1 + (RLE_cmd & 127);
|
||||||
pal_idx *= tga_bits_per_pixel / 8;
|
RLE_repeating = RLE_cmd >> 7;
|
||||||
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
read_next_pixel = 1;
|
||||||
|
} else if ( !RLE_repeating )
|
||||||
{
|
{
|
||||||
raw_data[j] = tga_palette[pal_idx+j];
|
read_next_pixel = 1;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// read in the data raw
|
read_next_pixel = 1;
|
||||||
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
}
|
||||||
|
// OK, if I need to read a pixel, do it now
|
||||||
|
if ( read_next_pixel )
|
||||||
|
{
|
||||||
|
// load however much data we did have
|
||||||
|
if ( tga_indexed )
|
||||||
{
|
{
|
||||||
raw_data[j] = get8u(s);
|
// read in 1 byte, then perform the lookup
|
||||||
|
int pal_idx = get8u(s);
|
||||||
|
if ( pal_idx >= tga_palette_len )
|
||||||
|
{
|
||||||
|
// invalid index
|
||||||
|
pal_idx = 0;
|
||||||
|
}
|
||||||
|
pal_idx *= tga_bits_per_pixel / 8;
|
||||||
|
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
||||||
|
{
|
||||||
|
raw_data[j] = tga_palette[pal_idx+j];
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// read in the data raw
|
||||||
|
for (j = 0; j*8 < tga_bits_per_pixel; ++j)
|
||||||
|
{
|
||||||
|
raw_data[j] = get8u(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear the reading flag for the next pixel
|
||||||
|
read_next_pixel = 0;
|
||||||
|
} // end of reading a pixel
|
||||||
|
|
||||||
|
// copy data
|
||||||
|
for (j = 0; j < tga_comp; ++j)
|
||||||
|
tga_data[i*tga_comp+j] = raw_data[j];
|
||||||
|
|
||||||
|
// in case we're in RLE mode, keep counting down
|
||||||
|
--RLE_count;
|
||||||
|
}
|
||||||
|
// do I need to invert the image?
|
||||||
|
if ( tga_inverted )
|
||||||
|
{
|
||||||
|
for (j = 0; j*2 < tga_height; ++j)
|
||||||
|
{
|
||||||
|
int index1 = j * tga_width * req_comp;
|
||||||
|
int index2 = (tga_height - 1 - j) * tga_width * req_comp;
|
||||||
|
for (i = tga_width * req_comp; i > 0; --i)
|
||||||
|
{
|
||||||
|
unsigned char temp = tga_data[index1];
|
||||||
|
tga_data[index1] = tga_data[index2];
|
||||||
|
tga_data[index2] = temp;
|
||||||
|
++index1;
|
||||||
|
++index2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// convert raw to the intermediate format
|
|
||||||
switch (tga_bits_per_pixel)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
// Luminous => RGBA
|
|
||||||
trans_data[0] = raw_data[0];
|
|
||||||
trans_data[1] = raw_data[0];
|
|
||||||
trans_data[2] = raw_data[0];
|
|
||||||
trans_data[3] = 255;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
// Luminous,Alpha => RGBA
|
|
||||||
trans_data[0] = raw_data[0];
|
|
||||||
trans_data[1] = raw_data[0];
|
|
||||||
trans_data[2] = raw_data[0];
|
|
||||||
trans_data[3] = raw_data[1];
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
// BGR => RGBA
|
|
||||||
trans_data[0] = raw_data[2];
|
|
||||||
trans_data[1] = raw_data[1];
|
|
||||||
trans_data[2] = raw_data[0];
|
|
||||||
trans_data[3] = 255;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
// BGRA => RGBA
|
|
||||||
trans_data[0] = raw_data[2];
|
|
||||||
trans_data[1] = raw_data[1];
|
|
||||||
trans_data[2] = raw_data[0];
|
|
||||||
trans_data[3] = raw_data[3];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// clear the reading flag for the next pixel
|
|
||||||
read_next_pixel = 0;
|
|
||||||
} // end of reading a pixel
|
|
||||||
// convert to final format
|
|
||||||
switch (req_comp)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
// RGBA => Luminance
|
|
||||||
tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// RGBA => Luminance,Alpha
|
|
||||||
tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]);
|
|
||||||
tga_data[i*req_comp+1] = trans_data[3];
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
// RGBA => RGB
|
|
||||||
tga_data[i*req_comp+0] = trans_data[0];
|
|
||||||
tga_data[i*req_comp+1] = trans_data[1];
|
|
||||||
tga_data[i*req_comp+2] = trans_data[2];
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
// RGBA => RGBA
|
|
||||||
tga_data[i*req_comp+0] = trans_data[0];
|
|
||||||
tga_data[i*req_comp+1] = trans_data[1];
|
|
||||||
tga_data[i*req_comp+2] = trans_data[2];
|
|
||||||
tga_data[i*req_comp+3] = trans_data[3];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// in case we're in RLE mode, keep counting down
|
// clear my palette, if I had one
|
||||||
--RLE_count;
|
if ( tga_palette != NULL )
|
||||||
}
|
|
||||||
// do I need to invert the image?
|
|
||||||
if ( tga_inverted )
|
|
||||||
{
|
|
||||||
for (j = 0; j*2 < tga_height; ++j)
|
|
||||||
{
|
{
|
||||||
int index1 = j * tga_width * req_comp;
|
free( tga_palette );
|
||||||
int index2 = (tga_height - 1 - j) * tga_width * req_comp;
|
|
||||||
for (i = tga_width * req_comp; i > 0; --i)
|
|
||||||
{
|
|
||||||
unsigned char temp = tga_data[index1];
|
|
||||||
tga_data[index1] = tga_data[index2];
|
|
||||||
tga_data[index2] = temp;
|
|
||||||
++index1;
|
|
||||||
++index2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// clear my palette, if I had one
|
|
||||||
if ( tga_palette != NULL )
|
// swap RGB
|
||||||
|
if (tga_comp >= 3)
|
||||||
{
|
{
|
||||||
free( tga_palette );
|
unsigned char* tga_pixel = tga_data;
|
||||||
|
for (i=0; i < tga_width * tga_height; ++i)
|
||||||
|
{
|
||||||
|
unsigned char temp = tga_pixel[0];
|
||||||
|
tga_pixel[0] = tga_pixel[2];
|
||||||
|
tga_pixel[2] = temp;
|
||||||
|
tga_pixel += tga_comp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert to target component count
|
||||||
|
if (req_comp && req_comp != tga_comp)
|
||||||
|
tga_data = convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
|
||||||
|
|
||||||
// the things I do to get rid of an error message, and yet keep
|
// the things I do to get rid of an error message, and yet keep
|
||||||
// Microsoft's C compilers happy... [8^(
|
// Microsoft's C compilers happy... [8^(
|
||||||
tga_palette_start = tga_palette_len = tga_palette_bits =
|
tga_palette_start = tga_palette_len = tga_palette_bits =
|
||||||
@ -4624,6 +4589,7 @@ int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int
|
|||||||
fix broken STBI_SIMD path
|
fix broken STBI_SIMD path
|
||||||
fix bug where stbi_load_from_file no longer left file pointer in correct place
|
fix bug where stbi_load_from_file no longer left file pointer in correct place
|
||||||
fix broken non-easy path for 32-bit BMP (possibly never used)
|
fix broken non-easy path for 32-bit BMP (possibly never used)
|
||||||
|
TGA optimization by Arseny Kapoulkine
|
||||||
1.34 (unknown)
|
1.34 (unknown)
|
||||||
use STBI_NOTUSED in resample_row_generic(), fix one more leak in tga failure case
|
use STBI_NOTUSED in resample_row_generic(), fix one more leak in tga failure case
|
||||||
1.33 (2011-07-14)
|
1.33 (2011-07-14)
|
||||||
|
Loading…
Reference in New Issue
Block a user