diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 9920f6d908b3..7d2c9a15e1b8 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2412,7 +2412,7 @@ def set_dpi(self, val): ---------- val : float """ - self._parent.dpi = val + self._parent.set_dpi(val) self.stale = True def _get_renderer(self): @@ -3293,7 +3293,8 @@ def set_dpi(self, val): ---------- val : float """ - self.dpi = val + self._original_dpi = val + self._set_dpi(val * self.canvas.device_pixel_ratio) self.stale = True def set_figwidth(self, val, forward=True): diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index d8bf1954df94..75baf76fdf8c 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -655,6 +655,20 @@ def test_savefig_pixel_ratio(backend): assert ratio1 == ratio2 +@pytest.mark.parametrize("target", ["figure", "subfigure"]) +def test_set_dpi_savefig(target): + fig = Figure(figsize=(2, 1), dpi=40) + fig.canvas._set_device_pixel_ratio(2) + (fig if target == "figure" else fig.subfigures()).set_dpi(60) + + with io.BytesIO() as buf: + fig.savefig(buf, format="png", dpi="figure") + assert Image.open(buf).size == (120, 60) + + assert fig.dpi == 120 + assert fig.canvas.device_pixel_ratio == 2 + + def test_savefig_preserve_layout_engine(): fig = plt.figure(layout='compressed') fig.savefig(io.BytesIO(), bbox_inches='tight') @@ -1726,6 +1740,27 @@ def test_unpickle_with_device_pixel_ratio(): ) +@pytest.mark.parametrize("target", ["figure", "subfigure"]) +@pytest.mark.parametrize("set_dpi_first", [False, True]) +@pytest.mark.parametrize("device_pixel_ratio", [1, 7]) +def test_unpickle_with_set_dpi(target, set_dpi_first, device_pixel_ratio): + fig = Figure(dpi=42) + target = fig if target == "figure" else fig.subfigures() + + if set_dpi_first: + target.set_dpi(84) + fig.canvas._set_device_pixel_ratio(device_pixel_ratio) + else: + fig.canvas._set_device_pixel_ratio(device_pixel_ratio) + target.set_dpi(84) + + assert fig.dpi == 84 * device_pixel_ratio + restored = pickle.loads(pickle.dumps(fig)) + assert restored.dpi == 84 + np.testing.assert_allclose( + fig.bbox.max / device_pixel_ratio, restored.bbox.max) + + def test_gridspec_no_mutate_input(): gs = {'left': .1} gs_orig = dict(gs)