From b30d50d31dc0f1c1e6633bd3e3e5a1d47427c04e Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Thu, 25 Sep 2014 14:47:49 +0100 Subject: [PATCH] Fixed the differencing of images for the webagg/nbagg backends. --- lib/matplotlib/backends/backend_nbagg.py | 12 +++++- .../backends/backend_webagg_core.py | 43 +++++++++++++++---- lib/matplotlib/backends/web_backend/mpl.js | 13 +++++- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/backends/backend_nbagg.py b/lib/matplotlib/backends/backend_nbagg.py index 32c9ebf988a5..bea523622454 100644 --- a/lib/matplotlib/backends/backend_nbagg.py +++ b/lib/matplotlib/backends/backend_nbagg.py @@ -35,12 +35,20 @@ def __call__(self, block=None): if not managers: return + interactive = is_interactive() + for manager in managers: manager.show() - if not is_interactive() and manager in Gcf._activeQue: - Gcf._activeQue.remove(manager) + # plt.figure adds an event which puts the figure in focus + # in the activeQue. Disable this behaviour, as it results in + # figures being put as the active figure after they have been + # shown, even in non-interactive mode. + if hasattr(manager, '_cidgcf'): + manager.canvas.mpl_disconnect(manager._cidgcf) + if not interactive and manager in Gcf._activeQue: + Gcf._activeQue.remove(manager) show = Show() diff --git a/lib/matplotlib/backends/backend_webagg_core.py b/lib/matplotlib/backends/backend_webagg_core.py index 31b641ac0982..dfd77ec450c8 100644 --- a/lib/matplotlib/backends/backend_webagg_core.py +++ b/lib/matplotlib/backends/backend_webagg_core.py @@ -65,6 +65,12 @@ def __init__(self, *args, **kwargs): # sent to the clients will be a full frame. self._force_full = True + # Store the current image mode so that at any point, clients can + # request the information. This should be changed by calling + # self.set_image_mode(mode) so that the notification can be given + # to the connected clients. + self._current_image_mode = 'full' + def show(self): # show the figure window from matplotlib.pyplot import show @@ -86,24 +92,41 @@ def draw(self): def draw_idle(self): self.send_event("draw") + def set_image_mode(self, mode): + """ + Set the image mode for any subsequent images which will be sent + to the clients. The modes may currently be either 'full' or 'diff'. + + Note: diff images may not contain transparency, therefore upon + draw this mode may be changed if the resulting image has any + transparent component. + + """ + if mode not in ['full', 'diff']: + raise ValueError('image mode must be either full or diff.') + if self._current_image_mode != mode: + self._current_image_mode = mode + self.handle_send_image_mode(None) + def get_diff_image(self): if self._png_is_old: + renderer = self.get_renderer() + # The buffer is created as type uint32 so that entire # pixels can be compared in one numpy call, rather than # needing to compare each plane separately. - renderer = self.get_renderer() buff = np.frombuffer(renderer.buffer_rgba(), dtype=np.uint32) - buff.shape = (renderer.height, renderer.width) - # If any pixels have transparency, we need to force a full draw - # as we cannot overlay new on top of old. + # If any pixels have transparency, we need to force a full + # draw as we cannot overlay new on top of old. pixels = buff.view(dtype=np.uint8).reshape(buff.shape + (4,)) - some_transparency = np.any(pixels[:, :, 3] != 255) - - output = buff - if not self._force_full and not some_transparency: + if self._force_full or np.any(pixels[:, :, 3] != 255): + self.set_image_mode('full') + output = buff + else: + self.set_image_mode('diff') last_buffer = np.frombuffer(self._last_renderer.buffer_rgba(), dtype=np.uint32) last_buffer.shape = (renderer.height, renderer.width) @@ -230,6 +253,10 @@ def handle_resize(self, event): self._png_is_old = True self.manager.resize(w, h) + def handle_send_image_mode(self, event): + # The client requests notification of what the current image mode is. + self.send_event('image_mode', mode=self._current_image_mode) + def send_event(self, event_type, **kwargs): self.manager._send_event(event_type, **kwargs) diff --git a/lib/matplotlib/backends/web_backend/mpl.js b/lib/matplotlib/backends/web_backend/mpl.js index 5856b2347e32..6d6a1f3a4e59 100644 --- a/lib/matplotlib/backends/web_backend/mpl.js +++ b/lib/matplotlib/backends/web_backend/mpl.js @@ -41,6 +41,7 @@ mpl.figure = function(figure_id, websocket, ondownload, parent_element) { this.format_dropdown = undefined; this.focus_on_mousover = false; + this.image_mode = 'full'; this.root = $('
'); this.root.attr('style', 'display: inline-block'); @@ -56,11 +57,17 @@ mpl.figure = function(figure_id, websocket, ondownload, parent_element) { this.ws.onopen = function () { fig.send_message("supports_binary", {value: fig.supports_binary}); + fig.send_message("send_image_mode", {}); fig.send_message("refresh", {}); } this.imageObj.onload = function() { - fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height); + if (fig.image_mode == 'full') { + // Full images could contain transparency (where diff images + // almost always do), so we need to clear the canvas so that + // there is no ghosting. + fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height); + } fig.context.drawImage(fig.imageObj, 0, 0); fig.waiting = false; }; @@ -302,6 +309,10 @@ mpl.figure.prototype.handle_draw = function(fig, msg) { fig.send_draw_message(); } +mpl.figure.prototype.handle_image_mode = function(fig, msg) { + fig.image_mode = msg['mode']; +} + mpl.figure.prototype.updated_canvas_event = function() { // Called whenever the canvas gets updated. this.send_message("ack", {}); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy