From fdf690a99121d4deef1226fa4dcafaf588b096d2 Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Thu, 28 Sep 2023 22:06:27 -0700
Subject: [PATCH] naive multithreaded convert downloaded textures to dds

---
 src/main.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/src/main.rs b/src/main.rs
index df1cf2e..973023a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,5 @@
+use std::io::{Read, Seek};
+
 use clap::{Args, Parser, Subcommand};
 
 mod error;
@@ -20,6 +22,7 @@ struct Cli {
 enum Commands {
     Download(MapList),
     DownloadTextures(PathBufList),
+    ConvertTextures,
     Upload,
     Scan,
     Extract(PathBufList),
@@ -291,6 +294,75 @@ fn download_textures(paths: Vec<std::path::PathBuf>) -> BoxResult<()>{
     Ok(())
 }
 
+fn convert(file_thing:std::fs::DirEntry) -> BoxResult<()>{
+    let start = std::time::Instant::now();
+    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(&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)?;
+    }
+    println!("{:?}", start.elapsed());
+    Ok(())
+}
+fn convert_textures() -> BoxResult<()>{
+    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 result=convert(file_thing);
+            if let Err(e)=result{
+                println!("{:?}",e);
+            }
+        }));
+    }
+    for thread in threads{
+        if let Err(e)=thread.join(){
+            println!("thread error: {:?}",e);
+        }
+    }
+    Ok(())
+}
+
 enum Scan{
     Passed,
     Blocked,
@@ -748,6 +820,7 @@ fn main() -> BoxResult<()> {
     match cli.command {
         Commands::Download(map_list)=>download(map_list.maps),
         Commands::DownloadTextures(pathlist)=>download_textures(pathlist.paths),
+        Commands::ConvertTextures=>convert_textures(),
         Commands::Upload=>upload(),
         Commands::Scan=>scan(),
         Commands::Replace=>replace(),