1# Copyright (c) 2010-2024 openpyxl
2
3from io import BytesIO
4
5try:
6 from PIL import Image as PILImage
7except ImportError:
8 PILImage = False
9
10
11def _import_image(img):
12 if not PILImage:
13 raise ImportError('You must install Pillow to fetch image objects')
14
15 if not isinstance(img, PILImage.Image):
16 img = PILImage.open(img)
17
18 return img
19
20
21class Image:
22 """Image in a spreadsheet"""
23
24 _id = 1
25 _path = "/xl/media/image{0}.{1}"
26 anchor = "A1"
27
28 def __init__(self, img):
29
30 self.ref = img
31 mark_to_close = isinstance(img, str)
32 image = _import_image(img)
33 self.width, self.height = image.size
34
35 try:
36 self.format = image.format.lower()
37 except AttributeError:
38 self.format = "png"
39 if mark_to_close:
40 # PIL instances created for metadata should be closed.
41 image.close()
42
43
44 def _data(self):
45 """
46 Return image data, convert to supported types if necessary
47 """
48 img = _import_image(self.ref)
49 # don't convert these file formats
50 if self.format in ['gif', 'jpeg', 'png']:
51 img.fp.seek(0)
52 fp = img.fp
53 else:
54 fp = BytesIO()
55 img.save(fp, format="png")
56 fp.seek(0)
57
58 data = fp.read()
59 fp.close()
60 return data
61
62
63 @property
64 def path(self):
65 return self._path.format(self._id, self.format)