Skip to main content

blp/core/export/
jpg.rs

1use crate::core::image::ImageBlp;
2use crate::core::mipmap::Mipmap;
3use crate::core::types::TextureType;
4use crate::error::error::BlpError;
5use std::fs;
6use std::path::Path;
7
8impl ImageBlp {
9    /// Экспортирует данный мип как "сырой" JPEG:
10    /// склеивает общий JPEG header из файла с хвостом этого мипа и записывает в out_path.
11    /// Требуется исходный буфер `buf` с .blp данными (тот же, что парсили).
12    pub fn export_jpg(&self, mip: &Mipmap, buf: &[u8], out_path: &Path) -> Result<(), BlpError> {
13        // Подготовим директорию
14        if let Some(parent) = out_path.parent() {
15            if !parent.as_os_str().is_empty() {
16                fs::create_dir_all(parent)?;
17            }
18        }
19
20        // Этот метод имеет смысл только для JPEG-BLP
21        if self.texture_type != TextureType::JPEG {
22            return Err(BlpError::new("export-jpg.not-jpeg"));
23        }
24
25        // Общий header
26        let h_off = self.header_offset;
27        let h_len = self.header_length;
28        if h_len == 0 || h_off.checked_add(h_len).is_none() || h_off + h_len > buf.len() {
29            return Err(BlpError::new("export-jpg.header.oob")
30                .with_arg("offset", h_off as u32)
31                .with_arg("length", h_len as u32)
32                .with_arg("buf_len", buf.len() as u32));
33        }
34        let header_bytes = &buf[h_off..h_off + h_len];
35
36        // Хвост выбранного мипа
37        let off = mip.offset;
38        let len = mip.length;
39        if len == 0 || off.checked_add(len).is_none() || off + len > buf.len() {
40            return Err(BlpError::new("export-jpg.mip.oob")
41                .with_arg("offset", off as u32)
42                .with_arg("length", len as u32)
43                .with_arg("buf_len", buf.len() as u32));
44        }
45        let tail = &buf[off..off + len];
46
47        // Склейка [header][tail] и запись
48        let mut full = Vec::with_capacity(header_bytes.len() + tail.len());
49        full.extend_from_slice(header_bytes);
50        full.extend_from_slice(tail);
51
52        fs::write(out_path, &full)?;
53        Ok(())
54    }
55}