image.py 1.5 KB

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