drawings.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. from __future__ import absolute_import
  2. # Copyright (c) 2010-2019 openpyxl
  3. from io import BytesIO
  4. from warnings import warn
  5. from openpyxl.xml.functions import fromstring
  6. from openpyxl.xml.constants import IMAGE_NS
  7. from openpyxl.packaging.relationship import get_rel, get_rels_path, get_dependents
  8. from openpyxl.drawing.spreadsheet_drawing import SpreadsheetDrawing
  9. from openpyxl.drawing.image import Image, PILImage
  10. from openpyxl.chart.chartspace import ChartSpace
  11. from openpyxl.chart.reader import read_chart
  12. def find_images(archive, path):
  13. """
  14. Given the path to a drawing file extract charts and images
  15. Ingore errors due to unsupported parts of DrawingML
  16. """
  17. src = archive.read(path)
  18. tree = fromstring(src)
  19. try:
  20. drawing = SpreadsheetDrawing.from_tree(tree)
  21. except TypeError:
  22. warn("DrawingML support is incomplete and limited to charts and images only. Shapes and drawings will be lost.")
  23. return [], []
  24. rels_path = get_rels_path(path)
  25. deps = []
  26. if rels_path in archive.namelist():
  27. deps = get_dependents(archive, rels_path)
  28. charts = []
  29. for rel in drawing._chart_rels:
  30. cs = get_rel(archive, deps, rel.id, ChartSpace)
  31. chart = read_chart(cs)
  32. chart.anchor = rel.anchor
  33. charts.append(chart)
  34. images = []
  35. if not PILImage: # Pillow not installed, drop images
  36. return charts, images
  37. for rel in drawing._blip_rels:
  38. dep = deps[rel.embed]
  39. if dep.Type == IMAGE_NS:
  40. try:
  41. image = Image(BytesIO(archive.read(dep.target)))
  42. except (OSError, IOError): # Python 2.7
  43. msg = "The image {0} will be removed because it cannot be read".format(dep.target)
  44. warn(msg)
  45. continue
  46. if image.format.upper() == "WMF": # cannot save
  47. msg = "{0} image format is not supported so the image is being dropped".format(image.format)
  48. warn(msg)
  49. continue
  50. image.anchor = rel.anchor
  51. images.append(image)
  52. return charts, images