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

Skip to content

Commit bf441fe

Browse files
committed
Simplify webagg blitting.
- Directly reuse FigureCanvasAgg.get_renderer. We don't need to init _last_buff there as we can just use buff.copy() in get_diff_image() (If we really care about reusing the same array whenever possible, we could add a shape check before the removed copyto() and reuse the old array if the shapes match, but I doubt it matters.) Instead, init it once to a non-valid shape in the constructor. Note that the comments in the function were outdated since 78c182d. - First creating `pixels` and then viewing it as `buff` is slighly simpler than doing it the other way round.
1 parent e60b757 commit bf441fe

File tree

1 file changed

+13
-35
lines changed

1 file changed

+13
-35
lines changed

lib/matplotlib/backends/backend_webagg_core.py

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ def __init__(self, *args, **kwargs):
171171
# sent to the clients will be a full frame.
172172
self._force_full = True
173173

174+
# The last buffer, for diff mode.
175+
self._last_buff = np.empty((0, 0))
176+
174177
# Store the current image mode so that at any point, clients can
175178
# request the information. This should be changed by calling
176179
# self.set_image_mode(mode) so that the notification can be given
@@ -227,17 +230,18 @@ def get_diff_image(self):
227230
if self._png_is_old:
228231
renderer = self.get_renderer()
229232

233+
pixels = np.asarray(renderer.buffer_rgba())
230234
# The buffer is created as type uint32 so that entire
231235
# pixels can be compared in one numpy call, rather than
232236
# needing to compare each plane separately.
233-
buff = (np.frombuffer(renderer.buffer_rgba(), dtype=np.uint32)
234-
.reshape((renderer.height, renderer.width)))
235-
236-
# If any pixels have transparency, we need to force a full
237-
# draw as we cannot overlay new on top of old.
238-
pixels = buff.view(dtype=np.uint8).reshape(buff.shape + (4,))
239-
240-
if self._force_full or np.any(pixels[:, :, 3] != 255):
237+
buff = pixels.view(np.uint32).squeeze(2)
238+
239+
if (self._force_full
240+
# If the buffer has changed size we need to do a full draw.
241+
or buff.shape != self._last_buff.shape
242+
# If any pixels have transparency, we need to force a full
243+
# draw as we cannot overlay new on top of old.
244+
or (pixels[:, :, 3] != 255).any()):
241245
self.set_image_mode('full')
242246
output = buff
243247
else:
@@ -246,7 +250,7 @@ def get_diff_image(self):
246250
output = np.where(diff, buff, 0)
247251

248252
# Store the current buffer so we can compute the next diff.
249-
np.copyto(self._last_buff, buff)
253+
self._last_buff = buff.copy()
250254
self._force_full = False
251255
self._png_is_old = False
252256

@@ -255,32 +259,6 @@ def get_diff_image(self):
255259
Image.fromarray(data).save(png, format="png")
256260
return png.getvalue()
257261

258-
@_api.delete_parameter("3.6", "cleared", alternative="renderer.clear()")
259-
def get_renderer(self, cleared=None):
260-
# Mirrors super.get_renderer, but caches the old one so that we can do
261-
# things such as produce a diff image in get_diff_image.
262-
w, h = self.figure.bbox.size.astype(int)
263-
key = w, h, self.figure.dpi
264-
try:
265-
self._lastKey, self._renderer
266-
except AttributeError:
267-
need_new_renderer = True
268-
else:
269-
need_new_renderer = (self._lastKey != key)
270-
271-
if need_new_renderer:
272-
self._renderer = backend_agg.RendererAgg(
273-
w, h, self.figure.dpi)
274-
self._lastKey = key
275-
self._last_buff = np.copy(np.frombuffer(
276-
self._renderer.buffer_rgba(), dtype=np.uint32
277-
).reshape((self._renderer.height, self._renderer.width)))
278-
279-
elif cleared:
280-
self._renderer.clear()
281-
282-
return self._renderer
283-
284262
def handle_event(self, event):
285263
e_type = event['type']
286264
handler = getattr(self, 'handle_{0}'.format(e_type),

0 commit comments

Comments
 (0)