image.py 1.4 KB

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