-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed the differencing of images for the webagg/nbagg backends. #3567
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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']: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. throw in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that a good thing? Personally, I'd sooner let the user know that they haven't given the right parameter so that they can change it as they are developing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are only two options here so we are using this more-or-less as an enum, 'mode', 'MoDe' and 'MODE' all seem equivalent to me. I don't see the benefit of being picky here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Its such as moot point, I'm happy to change it, but I equally don't see any benefit of accepting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have now spent more time on this than it is worth, I am fine either way. |
||
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) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be done as a property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could do. There is a performance cost to using properties over methods, but I agree, it would be a more pleasant interface. Having said that, I was very tempted to put a leading underscore in the name as it is a pretty useless interface unless you are developing some code in
get_diff_image
...