poe_data_tools_cli/commands/
dump_art.rs1use std::{fs, path::Path};
2
3use anyhow::{Context, Result, ensure};
4use glob::{MatchOptions, Pattern};
5use poe_data_tools::fs::{FS, FileSystem};
6
7use crate::VERBOSE;
8
9pub fn extract_art(fs: &mut FS, patterns: &[Pattern], output_folder: &Path) -> Result<()> {
11 image_extras::register();
12
13 for pattern in patterns {
14 ensure!(
15 pattern.as_str().ends_with(".dds"),
16 "Only .dds art export is supported."
17 );
18 }
19
20 let filenames = fs
21 .list()
22 .filter(|filename| {
23 patterns.iter().any(|pattern| {
24 pattern.matches_with(
25 filename,
26 MatchOptions {
27 require_literal_separator: true,
28 ..Default::default()
29 },
30 )
31 })
32 })
33 .collect::<Vec<_>>();
34
35 fs.batch_read(&filenames)
36 .filter_map(|(path, res)| match res {
38 Ok(b) => Some((path, b)),
39 Err(e) => {
40 log::error!("Failed to extract file: {:?}: {:?}", path, e);
41 None
42 }
43 })
44 .map(|(filename, contents)| -> Result<_, anyhow::Error> {
46 let img = image::load_from_memory(&contents)
47 .with_context(|| format!("Failed to parse DDS image: {filename}"))?;
48
49 let out_filename = output_folder.join(filename.as_ref()).with_extension("png");
50 fs::create_dir_all(out_filename.parent().unwrap())
51 .with_context(|| format!("Failed to create output folder: {out_filename:?}"))?;
52
53 img.save(out_filename)
54 .with_context(|| format!("Failed to write file: {filename}"))?;
55
56 Ok(filename)
57 })
58 .for_each(|result| match result {
60 Ok(filename) => log::info!("Extracted file: {}", filename),
61 Err(e) => {
62 let error_message = if *VERBOSE.get().unwrap() {
63 format!("{e:?}")
64 } else {
65 format!("{e}")
66 };
67 log::error!("Failed to extract file: {error_message}");
68 }
69 });
70
71 Ok(())
72}