FIX: make_image should not modify original array#29892
Conversation
| ax3.imshow(rgbau) | ||
|
|
||
|
|
||
| def test_imshow_rgba_multi_draw(): |
There was a problem hiding this comment.
You do this conditionally - may be helpful to test the conditions where you are not doing the copy to demonstrate that they work fine on redraw
|
This adds another copy of the input image, which for medium to large images is not neglegible. Running the script below I get a peak memory usage of ~450 MB, but with this PR I get a peak usage of ~580MB (as expected the difference is ~one copy of the input image, which is ~120MB). I guess the other way to fix this is to multiply in-place, then divide in place after the resample. That would avoid the extra memory, but if it's constantly happening during a window resize I could imagine it has performace implications, and perhaps floating point errors could accumulate pretty fast with all the multiplications and divisions? I can't think of another option to solve this without going back to applying alpha in resampled space (ie undoing #29776). Perhaps @anntzer has some thoughts as the original PR author? import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
rgba = np.random.random((2000, 2000, 4))
fig, ax = plt.subplots()
ax.imshow(rgba)
fig.canvas.draw() |
|
The fix looks correct to me, sorry for introducing the bug. re: performance:
Thoughts? |
|
I guess we can add "input was uint8" to my list of reasons not to copy, since we already cast to float. |
|
In my opinion #29776 should remain. The previous results were incorrect, and I think having correct results should trump efficiency. We copy the user data in |
|
👍 to doing the right thing at the expense of memory - at a glance I think there might be ways to save creating extra memory for the alpha channel, but for simplicity I think worth getting this in as is and then optimizing (if possible) later. |
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
Either #29453, or some not-yet-pushed version of it, does attempt to do some of this deduplication. I don't have time to look at that again until I finish the text stuff, but it may yet be a possibility to reduce the memory footprint, which can be done after this PR at least fixes the bug. |
|
That's fine as long as we remember to remove the extra copy this introduces. |
|
I thought #29776 removed a copy (from |
|
Sure? But we still will want to remove this copy? |
|
I just want to clarify the issue is that we are modifying our copy of the array not the object the user passed to us. |
Yes, this is correct |
PR summary
Fixes #29891. 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.
PR checklist