Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5e91c5a

Browse files
committed
Add support for metadata= and pil_kwargs= in imsave().
For consistency with savefig().
1 parent b9fa7b7 commit 5e91c5a

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
`~pyplot.imsave` gained support for the ``metadata`` and ``pil_kwargs`` parameters
2+
``````````````````````````````````````````````````````````````````````````````````
3+
4+
These parameters behave similarly as for the `Figure.savefig()` method.

lib/matplotlib/image.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ def read_png(*args, **kwargs):
14311431

14321432

14331433
def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
1434-
origin=None, dpi=100):
1434+
origin=None, dpi=100, *, metadata=None, pil_kwargs=None):
14351435
"""
14361436
Save an array as an image file.
14371437
@@ -1464,6 +1464,17 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
14641464
dpi : int
14651465
The DPI to store in the metadata of the file. This does not affect the
14661466
resolution of the output image.
1467+
metadata : dict, optional
1468+
Metadata in the image file. The supported keys depend on the output
1469+
format, see the documentation of the respective backends for more
1470+
information.
1471+
pil_kwargs : dict, optional
1472+
If set to a non-None value, always use Pillow to save the figure
1473+
(regardless of the output format), and pass these keyword arguments to
1474+
`PIL.Image.save`.
1475+
1476+
If the 'pnginfo' key is present, it completely overrides
1477+
*metadata*, including the default 'Software' key.
14671478
"""
14681479
from matplotlib.figure import Figure
14691480
from matplotlib import _png
@@ -1474,10 +1485,14 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
14741485
else rcParams["savefig.format"]).lower()
14751486
if format in ["pdf", "ps", "eps", "svg"]:
14761487
# Vector formats that are not handled by PIL.
1488+
if pil_kwargs is not None:
1489+
raise ValueError(
1490+
f"Cannot use 'pil_kwargs' when saving to {format}")
14771491
fig = Figure(dpi=dpi, frameon=False)
14781492
fig.figimage(arr, cmap=cmap, vmin=vmin, vmax=vmax, origin=origin,
14791493
resize=True)
1480-
fig.savefig(fname, dpi=dpi, format=format, transparent=True)
1494+
fig.savefig(fname, dpi=dpi, format=format, transparent=True,
1495+
metadata=metadata)
14811496
else:
14821497
# Don't bother creating an image; this avoids rounding errors on the
14831498
# size when dividing and then multiplying by dpi.
@@ -1488,17 +1503,28 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
14881503
if origin == "lower":
14891504
arr = arr[::-1]
14901505
rgba = sm.to_rgba(arr, bytes=True)
1491-
if format == "png":
1492-
_png.write_png(rgba, fname, dpi=dpi)
1506+
if format == "png" and pil_kwargs is None:
1507+
_png.write_png(rgba, fname, dpi=dpi, metadata=metadata)
14931508
else:
14941509
try:
14951510
from PIL import Image
1511+
from PIL.PngImagePlugin import PngInfo
14961512
except ImportError as exc:
1497-
raise ImportError(
1498-
f"Saving to {format} requires Pillow") from exc
1513+
if pil_kwargs is not None:
1514+
raise ImportError("Setting 'pil_kwargs' requires Pillow")
1515+
else:
1516+
raise ImportError(f"Saving to {format} requires Pillow")
1517+
if pil_kwargs is None:
1518+
pil_kwargs = {}
14991519
pil_shape = (rgba.shape[1], rgba.shape[0])
15001520
image = Image.frombuffer(
15011521
"RGBA", pil_shape, rgba, "raw", "RGBA", 0, 1)
1522+
if format == "png" and metadata is not None:
1523+
# cf. backend_agg's print_png.
1524+
pnginfo = PngInfo()
1525+
for k, v in metadata.items():
1526+
pnginfo.add_text(k, v)
1527+
pil_kwargs["pnginfo"] = pnginfo
15021528
if format in ["jpg", "jpeg"]:
15031529
format = "jpeg" # Pillow doesn't recognize "jpg".
15041530
color = tuple(
@@ -1507,7 +1533,9 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
15071533
background = Image.new("RGB", pil_shape, color)
15081534
background.paste(image, image)
15091535
image = background
1510-
image.save(fname, format=format, dpi=(dpi, dpi))
1536+
pil_kwargs.setdefault("format", format)
1537+
pil_kwargs.setdefault("dpi", (dpi, dpi))
1538+
image.save(fname, **pil_kwargs)
15111539

15121540

15131541
def pil_to_array(pilImage):

lib/matplotlib/tests/test_image.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,29 @@ def test_imsave_color_alpha():
213213
assert_array_equal(data, arr_buf)
214214

215215

216+
def test_imsave_pil_kwargs_png():
217+
Image = pytest.importorskip("PIL.Image")
218+
from PIL.PngImagePlugin import PngInfo
219+
buf = io.BytesIO()
220+
pnginfo = PngInfo()
221+
pnginfo.add_text("Software", "test")
222+
plt.imsave(buf, [[0, 1], [2, 3]],
223+
format="png", pil_kwargs={"pnginfo": pnginfo})
224+
im = Image.open(buf)
225+
assert im.info["Software"] == "test"
226+
227+
228+
def test_imsave_pil_kwargs_tiff():
229+
Image = pytest.importorskip("PIL.Image")
230+
from PIL.TiffTags import TAGS_V2 as TAGS
231+
buf = io.BytesIO()
232+
pil_kwargs = {"description": "test image"}
233+
plt.imsave(buf, [[0, 1], [2, 3]], format="tiff", pil_kwargs=pil_kwargs)
234+
im = Image.open(buf)
235+
tags = {TAGS[k].name: v for k, v in im.tag_v2.items()}
236+
assert tags["ImageDescription"] == "test image"
237+
238+
216239
@image_comparison(baseline_images=['image_alpha'], remove_text=True)
217240
def test_image_alpha():
218241
plt.figure()

0 commit comments

Comments
 (0)