Created
February 24, 2023 19:52
-
-
Save acorn1010/6a0e47a2a6ee4c348e8eaa4d41ba8cfc to your computer and use it in GitHub Desktop.
Rust TypeScript type generator for images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::env; | |
use std::fs::File; | |
use std::io::Write; | |
use std::time::Instant; | |
use walkdir::WalkDir; | |
use image::GenericImageView; | |
use rayon::prelude::*; | |
fn main() { | |
// Read input and output file paths | |
let args: Vec<String> = env::args().collect(); | |
if args.len() != 3 { | |
eprintln!("Usage: program_name input_file_path output_file_path"); | |
return; | |
} | |
let input_file_path = &args[1]; | |
let output_file_path = &args[2]; | |
println!("Generating image TypeScript file..."); | |
let start = Instant::now(); | |
let entries = | |
WalkDir::new(input_file_path) | |
.into_iter() | |
.filter_map(|e| e.ok()) | |
.collect::<Vec<_>>(); | |
let extensions = ["webp"]; // TODO(acorn1010): Maybe add png here, since it's a different size? | |
let results: Vec<_> = entries | |
.par_iter() | |
.filter_map(|entry| { | |
match entry.path().extension().and_then(|ext| ext.to_str()) { | |
Some(extension) if extensions.contains(&extension) => { | |
if let Ok(image) = image::open(&entry.path()) { | |
let (width, height) = image.dimensions(); | |
let filename = entry.path() | |
.with_extension("") | |
.strip_prefix(input_file_path) | |
.unwrap() | |
.display() | |
.to_string(); | |
Some((filename, width, height)) | |
} else { | |
None | |
} | |
} | |
_ => None, | |
} | |
}) | |
.collect(); | |
let mut sorted_results = results; | |
sorted_results.par_sort_unstable_by(|a, b| a.0.cmp(&b.0)); | |
let mut file = File::create(output_file_path).unwrap(); | |
file.write_all(b"/** This file is auto-generated by scripts/rust/image_utils. */\n").unwrap(); | |
file.write_all(b"\n").unwrap(); | |
file.write_all(b"/**\n").unwrap(); | |
file.write_all(b" * Maps the base filepath (from Foony's domain) to an image path without the extension.\n").unwrap(); | |
file.write_all(b" * .webp and .avif extensions are supported for all files here.\n").unwrap(); | |
file.write_all(b" */\n").unwrap(); | |
file.write_all(b"export type SiteImages = {\n").unwrap(); | |
for (filename, width, height) in sorted_results { | |
let line = format!(" '{}': {{width: {}, height: {}}},\n", filename, width, height); | |
file.write_all(line.as_bytes()).unwrap(); | |
} | |
file.write_all(b"};\n").unwrap(); | |
file.write_all(b"export type SiteImage = keyof SiteImages;\n").unwrap(); | |
println!("Elapsed time: {:?}", start.elapsed()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment