1use crate::error::DocxError;
2use image::{GenericImageView, load_from_memory};
3use std::fs::File;
4use std::io::Read;
5use uuid::Uuid;
6
7pub static DOCX_EMU: f32 = 360000.0;
9pub static DOCX_MAX_EMU: u64 = (21.0 * 360000.0 / 2.0) as u64;
10static DPI: f64 = 96f64;
12static EMU: f64 = 914400f64;
14
15pub struct DocxImage {
17 pub image_path: String,
19 pub image_data: Vec<u8>,
21 pub relation_id: String,
23 pub width: u64,
25 pub height: u64,
27}
28
29impl DocxImage {
30 pub fn new(image_path: &str) -> Result<Self, DocxError> {
33 let mut file = File::open(image_path)?;
35 let mut image_data = Vec::new();
36 file.read_to_end(&mut image_data)?;
37 let (width_emu, height_emu) = get_image_size(&image_data)?;
38 Self::new_size_emu(image_path, image_data, width_emu, height_emu)
39 }
40 pub fn new_size_emu(
45 image_path: &str,
46 image_data: Vec<u8>,
47 width: u64,
48 height: u64,
49 ) -> Result<Self, DocxError> {
50 DocxImage::new_image_data_size(image_path, image_data, width, height)
51 }
52
53 pub fn new_size(image_path: &str, width: u64, height: u64) -> Result<Self, DocxError> {
58 let mut file = File::open(image_path)?;
60 let mut image_data = Vec::new();
61 file.read_to_end(&mut image_data)?;
62 DocxImage::new_image_data_size(image_path, image_data, width, height)
63 }
64
65 pub fn new_image_data(image_url: &str, image_data: Vec<u8>) -> Result<Self, DocxError> {
69 let (width_emu, height_emu) = get_image_size(&image_data)?;
70 DocxImage::new_image_data_size(image_url, image_data, width_emu, height_emu)
71 }
72
73 pub fn new_image_data_size(
79 image_url: &str,
80 image_data: Vec<u8>,
81 width: u64,
82 height: u64,
83 ) -> Result<Self, DocxError> {
84 Ok(DocxImage {
85 image_path: image_url.to_string(),
86 relation_id: format!("rId{}", Uuid::new_v4().simple()),
87 width,
88 height,
89 image_data,
90 })
91 }
92}
93
94fn get_image_size(image_data: &[u8]) -> Result<(u64, u64), DocxError> {
95 let img = load_from_memory(image_data)?;
96 let (width_px, height_px) = img.dimensions();
97 let mut width_emu = (width_px as f64 * EMU / DPI) as u64;
98 let mut height_emu = (height_px as f64 * EMU / DPI) as u64;
99 if width_emu > DOCX_MAX_EMU {
101 height_emu = DOCX_MAX_EMU * height_emu / width_emu;
102 width_emu = DOCX_MAX_EMU;
103 Ok((width_emu, height_emu))
104 } else {
105 Ok((width_emu, height_emu))
106 }
107}