72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
|
|
# Copyright (c) 2010-2024 openpyxl
|
|
|
|
|
|
from io import BytesIO
|
|
from warnings import warn
|
|
|
|
from openpyxl.xml.functions import fromstring
|
|
from openpyxl.xml.constants import IMAGE_NS
|
|
from openpyxl.packaging.relationship import (
|
|
get_rel,
|
|
get_rels_path,
|
|
get_dependents,
|
|
)
|
|
from openpyxl.drawing.spreadsheet_drawing import SpreadsheetDrawing
|
|
from openpyxl.drawing.image import Image, PILImage
|
|
from openpyxl.chart.chartspace import ChartSpace
|
|
from openpyxl.chart.reader import read_chart
|
|
|
|
|
|
def find_images(archive, path):
|
|
"""
|
|
Given the path to a drawing file extract charts and images
|
|
|
|
Ignore errors due to unsupported parts of DrawingML
|
|
"""
|
|
|
|
src = archive.read(path)
|
|
tree = fromstring(src)
|
|
try:
|
|
drawing = SpreadsheetDrawing.from_tree(tree)
|
|
except TypeError:
|
|
warn("DrawingML support is incomplete and limited to charts and images only. Shapes and drawings will be lost.")
|
|
return [], []
|
|
|
|
rels_path = get_rels_path(path)
|
|
deps = []
|
|
if rels_path in archive.namelist():
|
|
deps = get_dependents(archive, rels_path)
|
|
|
|
charts = []
|
|
for rel in drawing._chart_rels:
|
|
try:
|
|
cs = get_rel(archive, deps, rel.id, ChartSpace)
|
|
except TypeError as e:
|
|
warn(f"Unable to read chart {rel.id} from {path} {e}")
|
|
continue
|
|
chart = read_chart(cs)
|
|
chart.anchor = rel.anchor
|
|
charts.append(chart)
|
|
|
|
images = []
|
|
if not PILImage: # Pillow not installed, drop images
|
|
return charts, images
|
|
|
|
for rel in drawing._blip_rels:
|
|
dep = deps.get(rel.embed)
|
|
if dep.Type == IMAGE_NS:
|
|
try:
|
|
image = Image(BytesIO(archive.read(dep.target)))
|
|
except OSError:
|
|
msg = "The image {0} will be removed because it cannot be read".format(dep.target)
|
|
warn(msg)
|
|
continue
|
|
if image.format.upper() == "WMF": # cannot save
|
|
msg = "{0} image format is not supported so the image is being dropped".format(image.format)
|
|
warn(msg)
|
|
continue
|
|
image.anchor = rel.anchor
|
|
images.append(image)
|
|
return charts, images
|