diff --git a/Cargo.toml b/Cargo.toml index 1648453..81b6ecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] image = "0.23.14" +texpresso = "2.0.1" err-derive = "0.2.2" parse-display = "0.1.1" num_enum = "0.4" diff --git a/examples/png.rs b/examples/png.rs index f38a71c..a76a3b4 100644 --- a/examples/png.rs +++ b/examples/png.rs @@ -25,8 +25,8 @@ fn main() -> Result<(), Error> { match image { DynamicImage::ImageRgb8(_) => image.save(&args[2])?, DynamicImage::ImageRgba8(_) => image.save(&args[2])?, - DynamicImage::ImageBgra8(_) => image.to_rgba().save(&args[2])?, - _ => image.to_rgb().save(&args[2])?, + DynamicImage::ImageBgra8(_) => image.to_rgba8().save(&args[2])?, + _ => image.to_rgb8().save(&args[2])?, }; Ok(()) } diff --git a/src/image.rs b/src/image.rs index 9f953e1..11fba54 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,12 +1,12 @@ use crate::header::VTFHeader; use crate::utils::get_offset; use crate::Error; -use image::dxt::{DxtDecoder, DXTVariant}; -use image::{DynamicImage, ImageBuffer, ImageDecoder, Pixel}; +use image::{DynamicImage, ImageBuffer, Pixel}; use num_enum::TryFromPrimitive; use parse_display::Display; use std::ops::Deref; use std::vec::Vec; +use texpresso::Format; #[derive(Debug)] pub struct VTFImage<'a> { @@ -46,10 +46,10 @@ impl<'a> VTFImage<'a> { Ok(&self.bytes[base..base + frame_size]) } - fn decode_dxt(&self, bytes: &[u8], variant: DXTVariant) -> Result, Error> { - let mut output: Vec = Vec::new(); - DxtDecoder::new(bytes, self.width as u32, self.height as u32, variant)?.read_image(&mut output)?; - Ok(output.to_vec()) + fn decode_dxt(&self, bytes: &[u8], variant: Format) -> Result, Error> { + let mut output: Vec = vec![0; self.width as usize * self.height as usize * 4]; + variant.decompress(bytes, self.width as usize, self.height as usize, &mut output); + Ok(output) } fn image_from_buffer( @@ -72,19 +72,19 @@ impl<'a> VTFImage<'a> { let bytes = self.get_frame(frame)?; match self.format { ImageFormat::Dxt1 => { - let buf = self.decode_dxt(bytes, DXTVariant::DXT1)?; - self.image_from_buffer(buf, DynamicImage::ImageRgb8) + let buf = self.decode_dxt(bytes, Format::Bc1)?; + self.image_from_buffer(buf, DynamicImage::ImageRgba8) } ImageFormat::Dxt1Onebitalpha => { - let buf = self.decode_dxt(bytes, DXTVariant::DXT1)?; + let buf = self.decode_dxt(bytes, Format::Bc1)?; self.image_from_buffer(buf, DynamicImage::ImageRgba8) } ImageFormat::Dxt3 => { - let buf = self.decode_dxt(bytes, DXTVariant::DXT3)?; + let buf = self.decode_dxt(bytes, Format::Bc2)?; self.image_from_buffer(buf, DynamicImage::ImageRgba8) } ImageFormat::Dxt5 => { - let buf = self.decode_dxt(bytes, DXTVariant::DXT5)?; + let buf = self.decode_dxt(bytes, Format::Bc3)?; self.image_from_buffer(buf, DynamicImage::ImageRgba8) } ImageFormat::Rgba8888 => { diff --git a/src/vtf.rs b/src/vtf.rs index 12b06a6..9a2ea21 100644 --- a/src/vtf.rs +++ b/src/vtf.rs @@ -2,10 +2,10 @@ use crate::header::VTFHeader; use crate::image::{ImageFormat, VTFImage}; use crate::resources::{ResourceList, ResourceType}; use crate::Error; -use image::dxt::{DxtEncoder, DXTVariant}; use image::{DynamicImage, GenericImageView}; use std::io::Cursor; use std::vec::Vec; +use texpresso::{Format, Params}; #[derive(Debug)] pub struct VTF<'a> { @@ -30,7 +30,7 @@ impl<'a> VTF<'a> { let highres_offset = match header .resources - .get_by_type(ResourceType::VTF_LEGACY_RSRC_LOW_RES_IMAGE) + .get_by_type(ResourceType::VTF_LEGACY_RSRC_IMAGE) { Some(resource) => resource.data, None => { @@ -115,26 +115,19 @@ impl<'a> VTF<'a> { data.resize(header_size, 0); + let width = header.width as usize; + let height = header.height as usize; + match image_format { ImageFormat::Dxt5 => { let image_data = image.to_rgba8(); - let encoder = DxtEncoder::new(&mut data); - encoder.encode( - &image_data, - header.width as u32, - header.height as u32, - DXTVariant::DXT5, - )?; + data.resize(header_size + Format::Bc3.compressed_size(width, height), 0); + Format::Bc3.compress(image_data.as_raw(), width, height, Params::default(), &mut data[header_size..]); } ImageFormat::Dxt1Onebitalpha => { let image_data = image.to_rgba8(); - let encoder = DxtEncoder::new(&mut data); - encoder.encode( - &image_data, - header.width as u32, - header.height as u32, - DXTVariant::DXT1, - )?; + data.resize(header_size + Format::Bc1.compressed_size(width, height), 0); + Format::Bc1.compress(image_data.as_raw(), width, height, Params::default(), &mut data[header_size..]); } ImageFormat::Rgba8888 => { let image_data = image.to_rgba8();