naive multithreaded convert downloaded textures to dds

This commit is contained in:
Quaternions 2023-09-28 22:06:27 -07:00
parent 8553625738
commit 4417bafc5c

View File

@ -1,3 +1,5 @@
use std::io::{Read, Seek};
use clap::{Args, Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
mod error; mod error;
@ -20,6 +22,7 @@ struct Cli {
enum Commands { enum Commands {
Download(MapList), Download(MapList),
DownloadTextures(PathBufList), DownloadTextures(PathBufList),
ConvertTextures,
Upload, Upload,
Scan, Scan,
Extract(PathBufList), Extract(PathBufList),
@ -291,6 +294,81 @@ fn download_textures(paths: Vec<std::path::PathBuf>) -> BoxResult<()>{
Ok(()) Ok(())
} }
fn convert(file_thing:std::fs::DirEntry) -> BoxResult<()>{
let mut input = std::io::BufReader::new(std::fs::File::open(file_thing.path())?);
let mut fourcc=[0u8;4];
input.read_exact(&mut fourcc)?;
input.rewind()?;
let mut extracted_input=None;
let image=if&fourcc==b"\x89PNG"{
image::load(input,image::ImageFormat::Png)?.to_rgba8()
}else if &fourcc[0..2]==b"\x1f\x8b"{
//gzip
let mut extracted:Vec<u8>=Vec::new();
flate2::read::GzDecoder::new(input).read_to_end(&mut extracted)?;
extracted_input=Some(extracted.clone());
image::load(std::io::Cursor::new(extracted),image::ImageFormat::Png)?.to_rgba8()
}else{
Err(error::Error::new("Unknown texture format"))?
};
let dds = image_dds::dds_from_image(
&image,
image_dds::ImageFormat::BC7Unorm,
image_dds::Quality::Slow,
image_dds::Mipmaps::GeneratedAutomatic,
)?;
//write dds
let mut dest=std::path::PathBuf::from("textures/dds");
dest.push(file_thing.file_name());
dest.set_extension("dds");
let mut writer = std::io::BufWriter::new(std::fs::File::create(dest)?);
dds.write(&mut writer)?;
if let Some(mut extracted)=extracted_input{
//write extracted to processed
let mut dest=std::path::PathBuf::from("textures/processed");
dest.push(file_thing.file_name());
std::fs::write(dest, &mut extracted)?;
//delete ugly gzip file
std::fs::remove_file(file_thing.path())?;
}else{
//move file to processed
let mut dest=std::path::PathBuf::from("textures/processed");
dest.push(file_thing.file_name());
std::fs::rename(file_thing.path(), dest)?;
}
Ok(())
}
fn convert_textures() -> BoxResult<()>{
let start = std::time::Instant::now();
let mut threads=Vec::new();
for entry in std::fs::read_dir("textures/unprocessed")? {
let file_thing=entry?;
threads.push(std::thread::spawn(move ||{
let file_name=file_thing.file_name();
let result=convert(file_thing);
if let Err(e)=result{
println!("error processing file:{:?} error message:{:?}",file_name,e);
}
}));
}
let mut i=0;
let n_threads=threads.len();
for thread in threads{
i+=1;
if let Err(e)=thread.join(){
println!("thread error: {:?}",e);
}else{
println!("{}/{}",i,n_threads);
}
}
println!("{:?}", start.elapsed());
Ok(())
}
enum Scan{ enum Scan{
Passed, Passed,
Blocked, Blocked,
@ -748,6 +826,7 @@ fn main() -> BoxResult<()> {
match cli.command { match cli.command {
Commands::Download(map_list)=>download(map_list.maps), Commands::Download(map_list)=>download(map_list.maps),
Commands::DownloadTextures(pathlist)=>download_textures(pathlist.paths), Commands::DownloadTextures(pathlist)=>download_textures(pathlist.paths),
Commands::ConvertTextures=>convert_textures(),
Commands::Upload=>upload(), Commands::Upload=>upload(),
Commands::Scan=>scan(), Commands::Scan=>scan(),
Commands::Replace=>replace(), Commands::Replace=>replace(),