umya_spreadsheet/structs/
image.rs

1use crate::structs::drawing::spreadsheet::MarkerType;
2use crate::structs::drawing::spreadsheet::OneCellAnchor;
3use crate::structs::drawing::spreadsheet::Picture;
4use crate::structs::drawing::spreadsheet::TwoCellAnchor;
5use crate::structs::drawing::FillRectangle;
6use crate::structs::drawing::PresetGeometry;
7use crate::structs::drawing::Stretch;
8use crate::structs::MediaObject;
9use crate::traits::AdjustmentCoordinate;
10use base64::{engine::general_purpose::STANDARD, Engine as _};
11use quick_xml::Writer;
12use std::fs;
13use std::fs::File;
14use std::io::BufReader;
15use std::io::Cursor;
16use std::io::Read;
17
18lazy_static! {
19    static ref EMPTY_VEC: Vec<u8> = Vec::new();
20}
21
22#[derive(Clone, Default, Debug)]
23pub struct Image {
24    two_cell_anchor: Option<Box<TwoCellAnchor>>,
25    one_cell_anchor: Option<Box<OneCellAnchor>>,
26}
27/// ## Example
28/// ```rust
29/// extern crate umya_spreadsheet;
30/// let mut book = umya_spreadsheet::new_file();
31///
32/// // Add Image
33/// let mut marker = umya_spreadsheet::structs::drawing::spreadsheet::MarkerType::default();
34/// marker.set_coordinate("B3");
35/// let mut image = umya_spreadsheet::structs::Image::default();
36/// image.new_image("./images/sample1.png", marker);
37/// book.get_sheet_by_name_mut("Sheet1").unwrap()
38///     .add_image(image);
39///
40/// // Get Image by Worksheet.
41/// let worksheet = book.get_sheet_by_name_mut("Sheet1").unwrap();
42/// let image = worksheet.get_image("B3");
43/// let image = worksheet.get_image_by_column_and_row(&2, &1);
44/// let image = worksheet.get_image_mut("B3");
45/// let image = worksheet.get_image_by_column_and_row_mut(&2, &1);
46///
47/// // Use this if there are multiple Images in a given cell.
48/// let images = worksheet.get_images("B3");
49/// let images = worksheet.get_images_by_column_and_row(&2, &1);
50/// let images = worksheet.get_images_mut("B3");
51/// let images = worksheet.get_images_by_column_and_row_mut(&2, &1);
52///
53/// // Download Image
54/// book.get_sheet_by_name("Sheet1").unwrap()
55/// .get_image_collection()
56/// .get(0)
57/// .unwrap()
58/// .download_image("./tests/result_files/bbb.png");
59///
60/// // Change Image
61/// book.get_sheet_by_name_mut("Sheet1").unwrap()
62/// .get_image_collection_mut()
63/// .get_mut(0)
64/// .unwrap()
65/// .change_image("./images/sample1.png");
66/// ```
67impl Image {
68    #[inline]
69    pub fn get_two_cell_anchor(&self) -> Option<&TwoCellAnchor> {
70        self.two_cell_anchor.as_deref()
71    }
72
73    #[inline]
74    pub fn get_two_cell_anchor_mut(&mut self) -> Option<&mut TwoCellAnchor> {
75        self.two_cell_anchor.as_deref_mut()
76    }
77
78    #[inline]
79    pub fn set_two_cell_anchor(&mut self, value: TwoCellAnchor) -> &mut Self {
80        self.two_cell_anchor = Some(Box::new(value));
81        self
82    }
83
84    #[inline]
85    pub fn remove_two_cell_anchor(&mut self) -> &mut Self {
86        self.two_cell_anchor = None;
87        self
88    }
89
90    #[inline]
91    pub fn get_one_cell_anchor(&self) -> Option<&OneCellAnchor> {
92        self.one_cell_anchor.as_deref()
93    }
94
95    #[inline]
96    pub fn get_one_cell_anchor_mut(&mut self) -> Option<&mut OneCellAnchor> {
97        self.one_cell_anchor.as_deref_mut()
98    }
99
100    #[inline]
101    pub fn set_one_cell_anchor(&mut self, value: OneCellAnchor) -> &mut Self {
102        self.one_cell_anchor = Some(Box::new(value));
103        self
104    }
105
106    #[inline]
107    pub fn remove_one_cell_anchor(&mut self) -> &mut Self {
108        self.one_cell_anchor = None;
109        self
110    }
111
112    pub fn new_image(&mut self, path: &str, marker: MarkerType) {
113        let path = std::path::Path::new(path);
114
115        let size = imagesize::size(path).unwrap();
116        let image_name = path.file_name().unwrap().to_str().unwrap();
117        let mut buf = Vec::new();
118
119        let file = File::open(path).unwrap();
120        BufReader::new(file).read_to_end(&mut buf).unwrap();
121
122        self.new_image_with_dimensions(
123            size.height as u32,
124            size.width as u32,
125            image_name,
126            buf,
127            marker,
128        )
129    }
130
131    pub fn new_image_with_dimensions<B: Into<Vec<u8>>>(
132        &mut self,
133        height: u32,
134        width: u32,
135        image_name: &str,
136        bytes: B,
137        marker: MarkerType,
138    ) {
139        let mut picture = Picture::default();
140        // filename and filedata.
141        picture
142            .get_blip_fill_mut()
143            .get_blip_mut()
144            .set_cstate("print")
145            .get_image_mut()
146            .set_image_name(image_name)
147            .set_image_data(bytes.into());
148
149        // name
150        picture
151            .get_non_visual_picture_properties_mut()
152            .get_non_visual_drawing_properties_mut()
153            .set_name(image_name);
154
155        // prefer_relative_resize
156        picture
157            .get_non_visual_picture_properties_mut()
158            .get_non_visual_picture_drawing_properties_mut()
159            .set_prefer_relative_resize(false);
160
161        // stretch
162        let fill_rectangle = FillRectangle::default();
163        let mut stretch = Stretch::default();
164        stretch.set_fill_rectangle(fill_rectangle);
165        picture.get_blip_fill_mut().set_stretch(stretch);
166
167        // geometry
168        picture
169            .get_shape_properties_mut()
170            .get_geometry_mut()
171            .set_geometry(PresetGeometry::GEOMETRY_RECT);
172
173        let mut one_cell_anchor = OneCellAnchor::default();
174        one_cell_anchor.set_from_marker(marker);
175        one_cell_anchor
176            .get_extent_mut()
177            .set_cy(height as i64 * 9525);
178        one_cell_anchor.get_extent_mut().set_cx(width as i64 * 9525);
179        one_cell_anchor.set_picture(picture);
180        self.set_one_cell_anchor(one_cell_anchor);
181    }
182
183    #[inline]
184    pub fn change_image(&mut self, path: &str) {
185        let marker = self.get_from_marker_type().clone();
186        self.remove_two_cell_anchor();
187        self.remove_one_cell_anchor();
188        self.new_image(path, marker);
189    }
190
191    #[inline]
192    pub fn download_image(&self, path: &str) {
193        fs::write(path, self.get_image_data()).unwrap();
194    }
195
196    #[inline]
197    pub fn has_image(&self) -> bool {
198        !self.get_media_object().is_empty()
199    }
200
201    #[inline]
202    pub fn get_image_name(&self) -> &str {
203        match self.get_media_object().first() {
204            Some(v) => v.get_image_name(),
205            None => "",
206        }
207    }
208
209    #[inline]
210    pub fn get_image_data(&self) -> &[u8] {
211        match self.get_media_object().first() {
212            Some(v) => v.get_image_data(),
213            None => &EMPTY_VEC,
214        }
215    }
216
217    #[inline]
218    pub fn get_image_data_base64(&self) -> String {
219        STANDARD.encode(self.get_image_data())
220    }
221
222    #[inline]
223    pub fn get_coordinate(&self) -> String {
224        self.get_from_marker_type().get_coordinate()
225    }
226
227    #[inline]
228    pub fn get_col(&self) -> &u32 {
229        self.get_from_marker_type().get_col()
230    }
231
232    #[inline]
233    pub fn get_row(&self) -> &u32 {
234        self.get_from_marker_type().get_row()
235    }
236
237    #[inline]
238    pub fn get_from_marker_type(&self) -> &MarkerType {
239        if let Some(anchor) = self.get_two_cell_anchor() {
240            return anchor.get_from_marker();
241        }
242        if let Some(anchor) = self.get_one_cell_anchor() {
243            return anchor.get_from_marker();
244        }
245        panic!("Not Found MediaObject");
246    }
247
248    #[inline]
249    pub fn get_to_marker_type(&self) -> Option<&MarkerType> {
250        self.get_two_cell_anchor()
251            .as_ref()
252            .map(|anchor| anchor.get_to_marker())
253    }
254
255    pub(crate) fn get_media_object(&self) -> Vec<&MediaObject> {
256        let mut result: Vec<&MediaObject> = Vec::new();
257        if let Some(anchor) = self.get_two_cell_anchor() {
258            if let Some(v) = anchor.get_picture() {
259                result.push(v.get_blip_fill().get_blip().get_image());
260            }
261            if let Some(v) = anchor.get_shape() {
262                if let Some(bf) = v.get_shape_properties().get_blip_fill() {
263                    result.push(bf.get_blip().get_image());
264                }
265            }
266            if let Some(v) = anchor.get_connection_shape() {
267                if let Some(bf) = v.get_shape_properties().get_blip_fill() {
268                    result.push(bf.get_blip().get_image());
269                }
270            }
271            if let Some(v) = anchor.get_group_shape() {
272                for pic in v.get_picture_collection() {
273                    result.push(pic.get_blip_fill().get_blip().get_image());
274                }
275                for shp in v.get_shape_collection() {
276                    if let Some(bf) = shp.get_shape_properties().get_blip_fill() {
277                        result.push(bf.get_blip().get_image());
278                    }
279                }
280            }
281        }
282        if let Some(anchor) = self.get_one_cell_anchor() {
283            if let Some(v) = anchor.get_picture() {
284                result.push(v.get_blip_fill().get_blip().get_image());
285            }
286            if let Some(v) = anchor.get_shape() {
287                if let Some(bf) = v.get_shape_properties().get_blip_fill() {
288                    result.push(bf.get_blip().get_image());
289                }
290            }
291            if let Some(v) = anchor.get_group_shape() {
292                for pic in v.get_picture_collection() {
293                    result.push(pic.get_blip_fill().get_blip().get_image());
294                }
295                for shp in v.get_shape_collection() {
296                    if let Some(bf) = shp.get_shape_properties().get_blip_fill() {
297                        result.push(bf.get_blip().get_image());
298                    }
299                }
300            }
301        }
302        result
303    }
304
305    #[inline]
306    pub(crate) fn write_to(
307        &self,
308        writer: &mut Writer<Cursor<Vec<u8>>>,
309        rel_list: &mut Vec<(String, String)>,
310    ) {
311        if let Some(anchor) = self.get_two_cell_anchor() {
312            anchor.write_to(writer, rel_list, &0);
313        }
314        if let Some(anchor) = self.get_one_cell_anchor() {
315            anchor.write_to(writer, rel_list);
316        }
317    }
318}
319impl AdjustmentCoordinate for Image {
320    #[inline]
321    fn adjustment_insert_coordinate(
322        &mut self,
323        root_col_num: &u32,
324        offset_col_num: &u32,
325        root_row_num: &u32,
326        offset_row_num: &u32,
327    ) {
328        // one_cell_anchor
329        match self.one_cell_anchor.as_mut() {
330            Some(anchor) => {
331                anchor.adjustment_insert_coordinate(
332                    root_col_num,
333                    offset_col_num,
334                    root_row_num,
335                    offset_row_num,
336                );
337            }
338            None => {}
339        }
340
341        // two_cell_anchor
342        match self.two_cell_anchor.as_mut() {
343            Some(anchor) => {
344                anchor.adjustment_insert_coordinate(
345                    root_col_num,
346                    offset_col_num,
347                    root_row_num,
348                    offset_row_num,
349                );
350            }
351            None => {}
352        }
353    }
354
355    #[inline]
356    fn adjustment_remove_coordinate(
357        &mut self,
358        root_col_num: &u32,
359        offset_col_num: &u32,
360        root_row_num: &u32,
361        offset_row_num: &u32,
362    ) {
363        // one_cell_anchor
364        match self.one_cell_anchor.as_mut() {
365            Some(anchor) => {
366                anchor.adjustment_remove_coordinate(
367                    root_col_num,
368                    offset_col_num,
369                    root_row_num,
370                    offset_row_num,
371                );
372            }
373            None => {}
374        }
375
376        // two_cell_anchor
377        match self.two_cell_anchor.as_mut() {
378            Some(anchor) => {
379                anchor.adjustment_remove_coordinate(
380                    root_col_num,
381                    offset_col_num,
382                    root_row_num,
383                    offset_row_num,
384                );
385            }
386            None => {}
387        }
388    }
389
390    #[inline]
391    fn is_remove_coordinate(
392        &self,
393        root_col_num: &u32,
394        offset_col_num: &u32,
395        root_row_num: &u32,
396        offset_row_num: &u32,
397    ) -> bool {
398        match self.one_cell_anchor.as_ref() {
399            Some(anchor) => {
400                return anchor.is_remove_coordinate(
401                    root_col_num,
402                    offset_col_num,
403                    root_row_num,
404                    offset_row_num,
405                );
406            }
407            None => {}
408        }
409        match self.two_cell_anchor.as_ref() {
410            Some(anchor) => {
411                return anchor.is_remove_coordinate(
412                    root_col_num,
413                    offset_col_num,
414                    root_row_num,
415                    offset_row_num,
416                );
417            }
418            None => {}
419        }
420        false
421    }
422}