Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 507f8a4

Browse filesBrowse files
committed
FIX: make_image should not modify original array
The problem is that we divide the RGB part of the array by its alpha on each draw. The simple fix is to make a copy but I assume for efficiency we should only copy when necessary. * If we didn't start with float RGBA, we already made a copy * If alpha was an array, we already made a copy * If the alpha channel is one everywhere, it does not matter
1 parent 7e997ae commit 507f8a4
Copy full SHA for 507f8a4

File tree

Expand file treeCollapse file tree

2 files changed

+32
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+32
-0
lines changed

‎lib/matplotlib/image.py

Copy file name to clipboardExpand all lines: lib/matplotlib/image.py
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
439439
if not (A.ndim == 2 or A.ndim == 3 and A.shape[-1] in (3, 4)):
440440
raise ValueError(f"Invalid shape {A.shape} for image data")
441441

442+
float_rgba_in = A.ndim == 3 and A.shape[-1] == 4 and A.dtype.kind == 'f'
443+
442444
# if antialiased, this needs to change as window sizes
443445
# change:
444446
interpolation_stage = self._interpolation_stage
@@ -520,6 +522,9 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
520522
# Resample in premultiplied alpha space. (TODO: Consider
521523
# implementing premultiplied-space resampling in
522524
# span_image_resample_rgba_affine::generate?)
525+
if float_rgba_in and np.ndim(alpha) == 0 and np.any(A[..., 3] < 1):
526+
# Do not modify original RGBA input
527+
A = A.copy()
523528
A[..., :3] *= A[..., 3:]
524529
res = _resample(self, A, out_shape, t)
525530
np.divide(res[..., :3], res[..., 3:], out=res[..., :3],

‎lib/matplotlib/tests/test_image.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_image.py
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,33 @@ def test_imshow_alpha(fig_test, fig_ref):
281281
ax3.imshow(rgbau)
282282

283283

284+
@pytest.mark.parametrize('n_channels, is_int, alpha_arr, opaque',
285+
[(3, False, False, False), # RGB float
286+
(4, False, False, False), # RGBA float
287+
(4, False, True, False), # RGBA float with alpha array
288+
(4, False, False, True), # RGBA float with solid color
289+
(4, True, False, False)]) # RGBA unint8
290+
def test_imshow_multi_draw(n_channels, is_int, alpha_arr, opaque):
291+
if is_int:
292+
array = np.random.randint(0, 256, (2, 2, n_channels))
293+
else:
294+
array = np.random.random((2, 2, n_channels))
295+
if opaque:
296+
array[:, :, 3] = 1
297+
298+
if alpha_arr:
299+
alpha = np.array([[0.3, 0.5], [1, 0.8]])
300+
else:
301+
alpha = None
302+
303+
fig, ax = plt.subplots()
304+
im = ax.imshow(array, alpha=alpha)
305+
fig.draw_without_rendering()
306+
307+
# Draw should not modify original array
308+
np.testing.assert_array_equal(array, im._A)
309+
310+
284311
def test_cursor_data():
285312
from matplotlib.backend_bases import MouseEvent
286313

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.