use STB for TGA as well

This commit is contained in:
Jonathan 2023-05-21 23:20:49 -04:00
parent 45fd6ac588
commit 3f3b765780
2 changed files with 1 additions and 159 deletions

View File

@ -253,160 +253,6 @@ std::optional<texture> load_mip(
return tex;
}
/*
============================================================================
TARGA IMAGE
============================================================================
*/
struct targa_t
{
uint8_t id_length, colormap_type, image_type;
uint16_t colormap_index, colormap_length;
uint8_t colormap_size;
uint16_t x_origin, y_origin, width, height;
uint8_t pixel_size, attributes;
auto stream_data()
{
return std::tie(id_length, colormap_type, image_type, colormap_index, colormap_length, colormap_size, x_origin,
y_origin, width, height, pixel_size, attributes);
}
};
/*
=============
LoadTGA
=============
*/
std::optional<texture> load_tga(
const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game)
{
imemstream stream(file->data(), file->size(), std::ios_base::in | std::ios_base::binary);
stream >> endianness<std::endian::little>;
// Parse TGA
targa_t targa_header;
stream >= targa_header;
if (targa_header.image_type != 2 && targa_header.image_type != 10) {
logging::funcprint("Failed to load {}. Only type 2 and 10 targa RGB images supported.\n", name);
return std::nullopt;
}
if (targa_header.colormap_type != 0 || (targa_header.pixel_size != 32 && targa_header.pixel_size != 24)) {
logging::funcprint("Failed to load {}. Only 32 or 24 bit images supported (no colormaps).\n", name);
return std::nullopt;
}
int32_t columns = targa_header.width;
int32_t rows = targa_header.height;
uint32_t numPixels = columns * rows;
texture tex;
tex.meta.extension = ext::TGA;
tex.meta.name = name;
tex.meta.width = tex.width = columns;
tex.meta.height = tex.height = rows;
if (!meta_only) {
tex.pixels.resize(numPixels);
if (targa_header.id_length != 0)
stream.seekg(targa_header.id_length, std::ios_base::cur); // skip TARGA image comment
if (targa_header.image_type == 2) { // Uncompressed, RGB images
for (int32_t row = rows - 1; row >= 0; row--) {
qvec4b *pixbuf = tex.pixels.data() + row * columns;
for (int32_t column = 0; column < columns; column++) {
uint8_t red, green, blue, alphabyte;
switch (targa_header.pixel_size) {
case 24:
stream >= blue >= green >= red;
*pixbuf++ = {red, green, blue, 255};
break;
case 32:
stream >= blue >= green >= red >= alphabyte;
*pixbuf++ = {red, green, blue, alphabyte};
break;
default:
logging::funcprint(
"TGA {}, unsupported pixel size: {}\n", name, targa_header.pixel_size); // mxd
return std::nullopt;
}
}
}
} else if (targa_header.image_type == 10) { // Runlength encoded RGB images
unsigned char red, green, blue, alphabyte, j;
for (int32_t row = rows - 1; row >= 0; row--) {
qvec4b *pixbuf = tex.pixels.data() + row * columns;
for (int32_t column = 0; column < columns;) {
uint8_t packetHeader;
stream >= packetHeader;
uint8_t packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
stream >= blue >= green >= red;
alphabyte = 255;
break;
case 32: stream >= blue >= green >= red >= alphabyte; break;
default:
logging::funcprint(
"TGA {}, unsupported pixel size: {}\n", name, targa_header.pixel_size); // mxd
return std::nullopt;
}
for (j = 0; j < packetSize; j++) {
*pixbuf++ = {red, green, blue, alphabyte};
column++;
if (column == columns) { // run spans across rows
column = 0;
if (row > 0)
row--;
else
goto breakOut;
pixbuf = tex.pixels.data() + row * columns;
}
}
} else { // non run-length packet
for (j = 0; j < packetSize; j++) {
switch (targa_header.pixel_size) {
case 24:
stream >= blue >= green >= red;
*pixbuf++ = {red, green, blue, 255};
break;
case 32:
stream >= blue >= green >= red >= alphabyte;
*pixbuf++ = {red, green, blue, alphabyte};
break;
default:
logging::funcprint(
"TGA {}, unsupported pixel size: {}\n", name, targa_header.pixel_size); // mxd
return std::nullopt;
}
column++;
if (column == columns) { // pixel packet run spans across rows
column = 0;
if (row > 0)
row--;
else
goto breakOut;
pixbuf = tex.pixels.data() + row * columns;
}
}
}
}
breakOut:;
}
}
}
return tex; // mxd
}
std::optional<texture> load_stb(
const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game)
{

View File

@ -95,10 +95,6 @@ const texture *find(const std::string_view &str);
std::optional<texture> load_wal(
const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game);
// Load TGA
std::optional<texture> load_tga(
const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game);
// Load Quake/Half Life mip (raw data)
std::optional<texture> load_mip(
const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game);
@ -113,7 +109,7 @@ constexpr struct
const char *suffix;
ext id;
decltype(load_wal) *loader;
} extension_list[] = {{".png", ext::STB, load_stb}, {".jpg", ext::STB, load_stb}, {".tga", ext::TGA, load_tga},
} extension_list[] = {{".png", ext::STB, load_stb}, {".jpg", ext::STB, load_stb}, {".tga", ext::TGA, load_stb},
{".wal", ext::WAL, load_wal}, {".mip", ext::MIP, load_mip}, {"", ext::MIP, load_mip}};
// Attempt to load a texture from the specified name.