docx_template/
image.rs

1use crate::error::DocxError;
2use image::{GenericImageView, load_from_memory};
3use std::fs::File;
4use std::io::Read;
5use uuid::Uuid;
6
7static IMAGE_WIDTH: f32 = 6.09;
8static IMAGE_HEIGHT: f32 = 5.9;
9// 1厘米约等于360000EMU
10pub static DOCX_EMU: f32 = 360000.0;
11// 1英寸=96像素
12static DPI: f64 = 96f64;
13// 1英寸=914400 EMU
14static EMU: f64 = 914400f64;
15
16// 添加的图标对象
17pub struct DocxImage {
18    // 图片路径
19    pub image_path: String,
20    // 图片数据
21    pub image_data: Vec<u8>,
22    // 关联id
23    pub relation_id: String,
24    // 图片高度
25    pub width: u64,
26    // 图片高度
27    pub height: u64,
28}
29
30impl DocxImage {
31    /// 创建图片对象  
32    /// @param image_path 图片路径  
33    pub fn new(image_path: &str) -> Result<Self, DocxError> {
34        // 打开文件读取数据到数组中
35        let mut file = File::open(image_path)?;
36        let mut image_data = Vec::new();
37        file.read_to_end(&mut image_data)?;
38        let (width_emu, height_emu) = get_image_size(&image_data)?;
39        Self::new_size_emu(image_path, image_data, width_emu, height_emu)
40    }
41    /// 设置图片大小  
42    /// @param image_path 图片路径  
43    /// @param width 图片宽度  
44    /// @param height 图片高度  
45    pub fn new_size_emu(
46        image_path: &str,
47        image_data: Vec<u8>,
48        width: u64,
49        height: u64,
50    ) -> Result<Self, DocxError> {
51        DocxImage::new_image_data_size(image_path, image_data, width, height)
52    }
53
54    /// 设置图片大小  
55    /// @param image_path 图片路径  
56    /// @param width 图片宽度(emu)
57    /// @param height 图片高度 (emu)
58    pub fn new_size(image_path: &str, width: u64, height: u64) -> Result<Self, DocxError> {
59        // 打开文件读取数据到数组中
60        let mut file = File::open(image_path)?;
61        let mut image_data = Vec::new();
62        file.read_to_end(&mut image_data)?;
63        DocxImage::new_image_data_size(image_path, image_data, width, height)
64    }
65
66    /// 设置图片大小  
67    /// @param image_url 图片路径  
68    /// @param image_data 图片数据  
69    pub fn new_image_data(image_url: &str, image_data: Vec<u8>) -> Result<Self, DocxError> {
70        let (width_emu, height_emu) = get_image_size(&image_data)?;
71        DocxImage::new_image_data_size(image_url, image_data, width_emu, height_emu)
72    }
73
74    /// 设置图片大小  
75    /// @param image_url 图片路径  
76    /// @param image_data 图片数据  
77    /// @param width 图片宽度(emu)
78    /// @param height 图片高度(emu)
79    pub fn new_image_data_size(
80        image_url: &str,
81        image_data: Vec<u8>,
82        width: u64,
83        height: u64,
84    ) -> Result<Self, DocxError> {
85        Ok(DocxImage {
86            image_path: image_url.to_string(),
87            relation_id: format!("rId{}", Uuid::new_v4().simple()),
88            width,
89            height,
90            image_data,
91        })
92    }
93}
94
95fn get_image_size(image_data: &[u8]) -> Result<(u64, u64), DocxError> {
96    let img = load_from_memory(&image_data)?;
97    let (width_px, height_px) = img.dimensions();
98    let width_emu = (width_px as f64 * EMU / &DPI) as u64;
99    let height_emu = (height_px as f64 * EMU / &DPI) as u64;
100    Ok((width_emu, height_emu))
101}