umya_spreadsheet/structs/
image.rs1use 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}
40impl 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 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 picture
184 .non_visual_picture_properties_mut()
185 .non_visual_drawing_properties_mut()
186 .set_name(image_name);
187
188 picture
190 .non_visual_picture_properties_mut()
191 .non_visual_picture_drawing_properties_mut()
192 .set_prefer_relative_resize(false);
193
194 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 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 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 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 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 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}