pub mod blip;
pub mod emf;
pub mod wmf;
pub mod pict;
pub mod svg;
pub use blip::{Blip, BlipType, BitmapBlip, MetafileBlip};
use crate::common::error::Result;
use image::ImageFormat;
pub fn convert_blip_to_format(
blip: &Blip,
format: ImageFormat,
width: Option<u32>,
height: Option<u32>,
) -> Result<Vec<u8>> {
match blip {
Blip::Metafile(metafile) => {
let data = metafile.decompress()?;
match metafile.blip_type() {
Some(BlipType::Emf) => emf::convert_emf(&data, format, width, height),
Some(BlipType::Wmf) => wmf::convert_wmf(&data, format, width, height),
Some(BlipType::Pict) => pict::convert_pict(&data, format, width, height),
_ => Err(crate::common::error::Error::ParseError(
"Unknown metafile BLIP type".into(),
)),
}
}
Blip::Bitmap(bitmap) => {
let img = image::load_from_memory(&bitmap.picture_data)
.map_err(|e| crate::common::error::Error::ParseError(format!("Failed to load bitmap: {}", e)))?;
let img = match (width, height) {
(Some(w), Some(h)) if img.width() != w || img.height() != h => {
image::DynamicImage::ImageRgba8(image::imageops::resize(
&img,
w,
h,
image::imageops::FilterType::Lanczos3,
))
}
(Some(w), None) => {
let aspect = img.height() as f64 / img.width() as f64;
let h = (w as f64 * aspect) as u32;
image::DynamicImage::ImageRgba8(image::imageops::resize(
&img,
w,
h,
image::imageops::FilterType::Lanczos3,
))
}
(None, Some(h)) => {
let aspect = img.width() as f64 / img.height() as f64;
let w = (h as f64 * aspect) as u32;
image::DynamicImage::ImageRgba8(image::imageops::resize(
&img,
w,
h,
image::imageops::FilterType::Lanczos3,
))
}
_ => img,
};
let mut buffer = std::io::Cursor::new(Vec::new());
img.write_to(&mut buffer, format)
.map_err(|e| crate::common::error::Error::ParseError(format!("Failed to encode image: {}", e)))?;
Ok(buffer.into_inner())
}
}
}
pub fn convert_blip_to_png(
blip: &Blip,
width: Option<u32>,
height: Option<u32>,
) -> Result<Vec<u8>> {
convert_blip_to_format(blip, ImageFormat::Png, width, height)
}
pub fn convert_blip_to_jpeg(
blip: &Blip,
width: Option<u32>,
height: Option<u32>,
) -> Result<Vec<u8>> {
convert_blip_to_format(blip, ImageFormat::Jpeg, width, height)
}
pub fn convert_blip_to_webp(
blip: &Blip,
width: Option<u32>,
height: Option<u32>,
) -> Result<Vec<u8>> {
convert_blip_to_format(blip, ImageFormat::WebP, width, height)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_blip_type_extensions() {
assert_eq!(BlipType::Emf.extension(), "emf");
assert_eq!(BlipType::Png.extension(), "png");
assert_eq!(BlipType::Jpeg.extension(), "jpg");
}
#[test]
fn test_blip_type_classification() {
assert!(BlipType::Emf.is_metafile());
assert!(BlipType::Wmf.is_metafile());
assert!(BlipType::Pict.is_metafile());
assert!(!BlipType::Jpeg.is_metafile());
assert!(!BlipType::Png.is_metafile());
}
}