Skip to main content

umya_spreadsheet/structs/
image.rs

1use std::{
2    fs,
3    fs::File,
4    io::{
5        BufReader,
6        Cursor,
7        Read,
8    },
9};
10
11use base64::{
12    Engine as _,
13    engine::general_purpose::STANDARD,
14};
15use quick_xml::Writer;
16
17use crate::{
18    structs::{
19        MediaObject,
20        drawing::{
21            FillRectangle,
22            PresetGeometry,
23            Stretch,
24            spreadsheet::{
25                MarkerType,
26                OneCellAnchor,
27                Picture,
28                TwoCellAnchor,
29            },
30        },
31    },
32    traits::AdjustmentCoordinate,
33};
34
35#[derive(Clone, Default, Debug)]
36pub struct Image {
37    two_cell_anchor: Option<Box<TwoCellAnchor>>,
38    one_cell_anchor: Option<Box<OneCellAnchor>>,
39}
40/// ## Example
41/// ```rust
42/// extern crate umya_spreadsheet;
43/// let mut book = umya_spreadsheet::new_file();
44///
45/// // Add Image
46/// let mut marker = umya_spreadsheet::structs::drawing::spreadsheet::MarkerType::default();
47/// marker.set_coordinate("B3");
48/// let mut image = umya_spreadsheet::structs::Image::default();
49/// image.new_image("./images/sample1.png", marker);
50/// book.sheet_by_name_mut("Sheet1").unwrap().add_image(image);
51///
52/// // Get Image by Worksheet.
53/// let worksheet = book.sheet_by_name_mut("Sheet1").unwrap();
54/// let image = worksheet.image_mut("B3");
55/// let image = worksheet.image_by_column_and_row_mut(2, 1);
56///
57/// // Use this if there are multiple Images in a given cell.
58/// let images = worksheet.images("B3");
59/// let images = worksheet.images_mut("B3");
60///
61/// // Download Image
62/// book.sheet_by_name("Sheet1")
63///     .unwrap()
64///     .image_collection()
65///     .get(0)
66///     .unwrap()
67///     .download_image("./tests/result_files/bbb.png");
68///
69/// // Change Image
70/// book.sheet_by_name_mut("Sheet1")
71///     .unwrap()
72///     .image_collection_mut()
73///     .get_mut(0)
74///     .unwrap()
75///     .change_image("./images/sample1.png");
76/// ```
77impl Image {
78    #[inline]
79    #[must_use]
80    pub fn two_cell_anchor(&self) -> Option<&TwoCellAnchor> {
81        self.two_cell_anchor.as_deref()
82    }
83
84    #[inline]
85    #[must_use]
86    #[deprecated(since = "3.0.0", note = "Use two_cell_anchor()")]
87    pub fn get_two_cell_anchor(&self) -> Option<&TwoCellAnchor> {
88        self.two_cell_anchor()
89    }
90
91    #[inline]
92    pub fn two_cell_anchor_mut(&mut self) -> Option<&mut TwoCellAnchor> {
93        self.two_cell_anchor.as_deref_mut()
94    }
95
96    #[inline]
97    #[deprecated(since = "3.0.0", note = "Use two_cell_anchor_mut()")]
98    pub fn get_two_cell_anchor_mut(&mut self) -> Option<&mut TwoCellAnchor> {
99        self.two_cell_anchor_mut()
100    }
101
102    #[inline]
103    pub fn set_two_cell_anchor(&mut self, value: TwoCellAnchor) -> &mut Self {
104        self.two_cell_anchor = Some(Box::new(value));
105        self
106    }
107
108    #[inline]
109    pub fn remove_two_cell_anchor(&mut self) -> &mut Self {
110        self.two_cell_anchor = None;
111        self
112    }
113
114    #[inline]
115    #[must_use]
116    pub fn one_cell_anchor(&self) -> Option<&OneCellAnchor> {
117        self.one_cell_anchor.as_deref()
118    }
119
120    #[inline]
121    #[must_use]
122    #[deprecated(since = "3.0.0", note = "Use one_cell_anchor()")]
123    pub fn get_one_cell_anchor(&self) -> Option<&OneCellAnchor> {
124        self.one_cell_anchor()
125    }
126
127    #[inline]
128    pub fn one_cell_anchor_mut(&mut self) -> Option<&mut OneCellAnchor> {
129        self.one_cell_anchor.as_deref_mut()
130    }
131
132    #[inline]
133    #[deprecated(since = "3.0.0", note = "Use one_cell_anchor_mut()")]
134    pub fn get_one_cell_anchor_mut(&mut self) -> Option<&mut OneCellAnchor> {
135        self.one_cell_anchor_mut()
136    }
137
138    #[inline]
139    pub fn set_one_cell_anchor(&mut self, value: OneCellAnchor) -> &mut Self {
140        self.one_cell_anchor = Some(Box::new(value));
141        self
142    }
143
144    #[inline]
145    pub fn remove_one_cell_anchor(&mut self) -> &mut Self {
146        self.one_cell_anchor = None;
147        self
148    }
149
150    #[allow(clippy::cast_possible_truncation)]
151    pub fn new_image(&mut self, path: &str, marker: MarkerType) {
152        let path = std::path::Path::new(path);
153
154        let size = imagesize::size(path).unwrap();
155        let image_name = path.file_name().unwrap().to_str().unwrap();
156        let mut buf = Vec::new();
157
158        let file = File::open(path).unwrap();
159        BufReader::new(file).read_to_end(&mut buf).unwrap();
160
161        self.new_image_with_dimensions(size.height as u32, size.width as u32, image_name, buf, marker);
162    }
163
164    pub fn new_image_with_dimensions<B: Into<Vec<u8>>>(
165        &mut self,
166        height: u32,
167        width: u32,
168        image_name: &str,
169        bytes: B,
170        marker: MarkerType,
171    ) {
172        let mut picture = Picture::default();
173        // filename and filedata.
174        picture
175            .blip_fill_mut()
176            .blip_mut()
177            .set_cstate("print")
178            .image_mut()
179            .set_image_name(image_name)
180            .set_image_data(bytes.into());
181
182        // name
183        picture
184            .non_visual_picture_properties_mut()
185            .non_visual_drawing_properties_mut()
186            .set_name(image_name);
187
188        // prefer_relative_resize
189        picture
190            .non_visual_picture_properties_mut()
191            .non_visual_picture_drawing_properties_mut()
192            .set_prefer_relative_resize(false);
193
194        // stretch
195        let fill_rectangle = FillRectangle::default();
196        let mut stretch = Stretch::default();
197        stretch.set_fill_rectangle(fill_rectangle);
198        picture.blip_fill_mut().set_stretch(stretch);
199
200        // geometry
201        picture
202            .shape_properties_mut()
203            .geometry_mut()
204            .set_geometry(PresetGeometry::GEOMETRY_RECT);
205
206        let mut one_cell_anchor = OneCellAnchor::default();
207        one_cell_anchor.set_from_marker(marker);
208        one_cell_anchor
209            .extent_mut()
210            .set_cy(i64::from(height) * 9525);
211        one_cell_anchor
212            .extent_mut()
213            .set_cx(i64::from(width) * 9525);
214        one_cell_anchor.set_picture(picture);
215        self.set_one_cell_anchor(one_cell_anchor);
216    }
217
218    #[inline]
219    pub fn change_image(&mut self, path: &str) {
220        let marker = self.from_marker_type().clone();
221        self.remove_two_cell_anchor();
222        self.remove_one_cell_anchor();
223        self.new_image(path, marker);
224    }
225
226    #[inline]
227    pub fn download_image(&self, path: &str) {
228        fs::write(path, self.image_data()).unwrap();
229    }
230
231    #[inline]
232    #[must_use]
233    pub fn has_image(&self) -> bool {
234        !self.media_object().is_empty()
235    }
236
237    #[inline]
238    #[must_use]
239    pub fn image_name(&self) -> &str {
240        match self.media_object().first() {
241            Some(v) => v.image_name(),
242            None => "",
243        }
244    }
245
246    #[inline]
247    #[must_use]
248    #[deprecated(since = "3.0.0", note = "Use image_name()")]
249    pub fn get_image_name(&self) -> &str {
250        self.image_name()
251    }
252
253    #[inline]
254    #[must_use]
255    pub fn image_data(&self) -> &[u8] {
256        match self.media_object().first() {
257            Some(v) => v.image_data(),
258            None => &[0u8; 0],
259        }
260    }
261
262    #[inline]
263    #[must_use]
264    #[deprecated(since = "3.0.0", note = "Use image_data()")]
265    pub fn get_image_data(&self) -> &[u8] {
266        self.image_data()
267    }
268
269    #[inline]
270    #[must_use]
271    pub fn image_data_base64(&self) -> String {
272        STANDARD.encode(self.image_data())
273    }
274
275    #[inline]
276    #[must_use]
277    #[deprecated(since = "3.0.0", note = "Use image_data_base64()")]
278    pub fn get_image_data_base64(&self) -> String {
279        self.image_data_base64()
280    }
281
282    #[inline]
283    #[must_use]
284    pub fn coordinate(&self) -> String {
285        self.from_marker_type().coordinate()
286    }
287
288    #[inline]
289    #[must_use]
290    #[deprecated(since = "3.0.0", note = "Use coordinate()")]
291    pub fn get_coordinate(&self) -> String {
292        self.coordinate()
293    }
294
295    #[inline]
296    #[must_use]
297    pub fn col(&self) -> u32 {
298        self.from_marker_type().col()
299    }
300
301    #[inline]
302    #[must_use]
303    #[deprecated(since = "3.0.0", note = "Use col()")]
304    pub fn get_col(&self) -> u32 {
305        self.col()
306    }
307
308    #[inline]
309    #[must_use]
310    pub fn row(&self) -> u32 {
311        self.from_marker_type().row()
312    }
313
314    #[inline]
315    #[must_use]
316    #[deprecated(since = "3.0.0", note = "Use row()")]
317    pub fn get_row(&self) -> u32 {
318        self.row()
319    }
320
321    #[inline]
322    #[must_use]
323    pub fn from_marker_type(&self) -> &MarkerType {
324        if let Some(anchor) = self.two_cell_anchor() {
325            return anchor.from_marker();
326        }
327        if let Some(anchor) = self.one_cell_anchor() {
328            return anchor.from_marker();
329        }
330        panic!("Not Found MediaObject");
331    }
332
333    #[inline]
334    #[must_use]
335    #[deprecated(since = "3.0.0", note = "Use from_marker_type()")]
336    pub fn get_from_marker_type(&self) -> &MarkerType {
337        self.from_marker_type()
338    }
339
340    #[inline]
341    #[must_use]
342    pub fn to_marker_type(&self) -> Option<&MarkerType> {
343        self.two_cell_anchor()
344            .as_ref()
345            .map(|anchor| anchor.to_marker())
346    }
347
348    #[inline]
349    #[must_use]
350    #[deprecated(since = "3.0.0", note = "Use to_marker_type()")]
351    pub fn get_to_marker_type(&self) -> Option<&MarkerType> {
352        self.to_marker_type()
353    }
354
355    pub(crate) fn media_object(&self) -> Vec<&MediaObject> {
356        let mut result: Vec<&MediaObject> = Vec::new();
357        if let Some(anchor) = self.two_cell_anchor() {
358            if let Some(v) = anchor.picture() {
359                result.push(v.blip_fill().blip().image());
360            }
361            if let Some(v) = anchor.shape() {
362                if let Some(bf) = v.shape_properties().blip_fill() {
363                    result.push(bf.blip().image());
364                }
365            }
366            if let Some(v) = anchor.connection_shape() {
367                if let Some(bf) = v.shape_properties().blip_fill() {
368                    result.push(bf.blip().image());
369                }
370            }
371            if let Some(v) = anchor.group_shape() {
372                for pic in v.picture_collection() {
373                    result.push(pic.blip_fill().blip().image());
374                }
375                for shp in v.shape_collection() {
376                    if let Some(bf) = shp.shape_properties().blip_fill() {
377                        result.push(bf.blip().image());
378                    }
379                }
380            }
381        }
382        if let Some(anchor) = self.one_cell_anchor() {
383            if let Some(v) = anchor.picture() {
384                result.push(v.blip_fill().blip().image());
385            }
386            if let Some(v) = anchor.shape() {
387                if let Some(bf) = v.shape_properties().blip_fill() {
388                    result.push(bf.blip().image());
389                }
390            }
391            if let Some(v) = anchor.group_shape() {
392                for pic in v.picture_collection() {
393                    result.push(pic.blip_fill().blip().image());
394                }
395                for shp in v.shape_collection() {
396                    if let Some(bf) = shp.shape_properties().blip_fill() {
397                        result.push(bf.blip().image());
398                    }
399                }
400            }
401        }
402        result
403    }
404
405    #[deprecated(since = "3.0.0", note = "Use media_object()")]
406    pub(crate) fn get_media_object(&self) -> Vec<&MediaObject> {
407        self.media_object()
408    }
409
410    #[inline]
411    pub(crate) fn write_to(
412        &self,
413        writer: &mut Writer<Cursor<Vec<u8>>>,
414        rel_list: &mut Vec<(String, String)>,
415    ) {
416        if let Some(anchor) = self.two_cell_anchor() {
417            anchor.write_to(writer, rel_list, 0);
418        }
419        if let Some(anchor) = self.one_cell_anchor() {
420            anchor.write_to(writer, rel_list);
421        }
422    }
423}
424impl AdjustmentCoordinate for Image {
425    #[inline]
426    fn adjustment_insert_coordinate(
427        &mut self,
428        root_col_num: u32,
429        offset_col_num: u32,
430        root_row_num: u32,
431        offset_row_num: u32,
432    ) {
433        // one_cell_anchor
434        if let Some(anchor) = self.one_cell_anchor.as_mut() {
435            anchor.adjustment_insert_coordinate(
436                root_col_num,
437                offset_col_num,
438                root_row_num,
439                offset_row_num,
440            );
441        }
442
443        // two_cell_anchor
444        if let Some(anchor) = self.two_cell_anchor.as_mut() {
445            anchor.adjustment_insert_coordinate(
446                root_col_num,
447                offset_col_num,
448                root_row_num,
449                offset_row_num,
450            );
451        }
452    }
453
454    #[inline]
455    fn adjustment_remove_coordinate(
456        &mut self,
457        root_col_num: u32,
458        offset_col_num: u32,
459        root_row_num: u32,
460        offset_row_num: u32,
461    ) {
462        // one_cell_anchor
463        if let Some(anchor) = self.one_cell_anchor.as_mut() {
464            anchor.adjustment_remove_coordinate(
465                root_col_num,
466                offset_col_num,
467                root_row_num,
468                offset_row_num,
469            );
470        }
471
472        // two_cell_anchor
473        if let Some(anchor) = self.two_cell_anchor.as_mut() {
474            anchor.adjustment_remove_coordinate(
475                root_col_num,
476                offset_col_num,
477                root_row_num,
478                offset_row_num,
479            );
480        }
481    }
482
483    #[inline]
484    fn is_remove_coordinate(
485        &self,
486        root_col_num: u32,
487        offset_col_num: u32,
488        root_row_num: u32,
489        offset_row_num: u32,
490    ) -> bool {
491        if let Some(anchor) = self.one_cell_anchor.as_ref() {
492            return anchor.is_remove_coordinate(
493                root_col_num,
494                offset_col_num,
495                root_row_num,
496                offset_row_num,
497            );
498        }
499        if let Some(anchor) = self.two_cell_anchor.as_ref() {
500            return anchor.is_remove_coordinate(
501                root_col_num,
502                offset_col_num,
503                root_row_num,
504                offset_row_num,
505            );
506        }
507        false
508    }
509}