1
Fork 0
mirror of https://github.com/redstrate/Physis.git synced 2025-04-21 20:27:46 +00:00

Switch to texture2ddecoder

This crate supports more BCn decoders which texpresso doesn't (like
BC7.)
This commit is contained in:
Joshua Goins 2024-04-20 10:46:59 -04:00
parent 1b055b3f7a
commit 3e00c35bd8
2 changed files with 29 additions and 32 deletions

View file

@ -44,7 +44,7 @@ game_install = []
# enables support for extracting visual data, such as models, textures, materials, etc. # enables support for extracting visual data, such as models, textures, materials, etc.
# this enables a bunch of dependencies! # this enables a bunch of dependencies!
# tip: can be safely turned off for launchers and other tools that simply need to extract the bare minimum of data # tip: can be safely turned off for launchers and other tools that simply need to extract the bare minimum of data
visual_data = ["dep:half", "dep:bitflags", "dep:texpresso"] visual_data = ["dep:half", "dep:bitflags", "dep:texture2ddecoder"]
# testing only features # testing only features
retail_game_testing = [] retail_game_testing = []
@ -70,4 +70,4 @@ half = { version = "2", optional = true }
bitflags = { version = "1.3", optional = true } bitflags = { version = "1.3", optional = true }
# needed for dxt/bc decompression # needed for dxt/bc decompression
texpresso = { version = "2", optional = true } texture2ddecoder = { version = "0.0.5", optional = true }

View file

@ -8,7 +8,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom};
use binrw::BinRead; use binrw::BinRead;
use binrw::binrw; use binrw::binrw;
use bitflags::bitflags; use bitflags::bitflags;
use texpresso::Format; use texture2ddecoder::{decode_bc1, decode_bc3, decode_bc5};
use crate::ByteSpan; use crate::ByteSpan;
// Attributes and Format are adapted from Lumina (https://github.com/NotAdam/Lumina/blob/master/src/Lumina/Data/Files/TexFile.cs) // Attributes and Format are adapted from Lumina (https://github.com/NotAdam/Lumina/blob/master/src/Lumina/Data/Files/TexFile.cs)
@ -79,6 +79,8 @@ pub struct Texture {
pub rgba: Vec<u8>, pub rgba: Vec<u8>,
} }
type DecodeFunction = fn(&[u8], usize, usize, &mut [u32]) -> Result<(), &'static str>;
impl Texture { impl Texture {
/// Reads an existing TEX file /// Reads an existing TEX file
pub fn from_existing(buffer: ByteSpan) -> Option<Texture> { pub fn from_existing(buffer: ByteSpan) -> Option<Texture> {
@ -92,7 +94,7 @@ impl Texture {
let mut src = vec![0u8; buffer.len() - std::mem::size_of::<TexHeader>()]; let mut src = vec![0u8; buffer.len() - std::mem::size_of::<TexHeader>()];
cursor.read_exact(src.as_mut_slice()).ok()?; cursor.read_exact(src.as_mut_slice()).ok()?;
let mut dst; let mut dst : Vec<u8>;
match header.format { match header.format {
TextureFormat::B4G4R4A4 => { TextureFormat::B4G4R4A4 => {
@ -119,40 +121,16 @@ impl Texture {
} }
} }
TextureFormat::B8G8R8A8 => { TextureFormat::B8G8R8A8 => {
dst = src; dst = src; // TODO: not correct, of course
} }
TextureFormat::BC1 => { TextureFormat::BC1 => {
dst = vec![0u8; header.width as usize * header.height as usize * 4]; dst = Texture::decode(&src, header.width as usize, header.height as usize, decode_bc1);
let format = Format::Bc1;
format.decompress(
&src,
header.width as usize,
header.height as usize,
dst.as_mut_slice(),
);
} }
TextureFormat::BC3 => { TextureFormat::BC3 => {
dst = vec![0u8; header.width as usize * header.height as usize * 4]; dst = Texture::decode(&src, header.width as usize, header.height as usize, decode_bc3);
let format = Format::Bc3;
format.decompress(
&src,
header.width as usize,
header.height as usize,
dst.as_mut_slice(),
);
} }
TextureFormat::BC5 => { TextureFormat::BC5 => {
dst = vec![0u8; header.width as usize * header.height as usize * 4]; dst = Texture::decode(&src, header.width as usize, header.height as usize, decode_bc5);
let format = Format::Bc5;
format.decompress(
&src,
header.width as usize,
header.height as usize,
dst.as_mut_slice(),
);
} }
} }
@ -162,6 +140,25 @@ impl Texture {
rgba: dst, rgba: dst,
}) })
} }
fn decode(src: &[u8], width: usize, height: usize, decode_func: DecodeFunction) -> Vec<u8> {
let mut image: Vec<u32> = vec![0; (width * height) as usize];
decode_func(
&src,
width as usize,
height as usize,
&mut image,
)
.unwrap();
image
.iter()
.flat_map(|x| {
let v = x.to_le_bytes();
[v[2], v[1], v[0], v[3]]
})
.collect::<Vec<u8>>()
}
} }
#[cfg(test)] #[cfg(test)]