Skip to content

Change {FigureCanvasAgg,RendererAgg}.buffer_rgba to return a memoryview. #11735

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

Merged
merged 2 commits into from
Dec 27, 2018

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Jul 22, 2018

The buffer_rgba method now allows direct access to the renderer's
underlying buffer (as a (m, n, 4)-shape memoryview) rather than
copying the data to a new bytestring. This is consistent with the
behavior on Py2, where a buffer object was returned.

While this is technically a backwards-incompatible change, memoryviews
are in fact quite compatible with bytes for most uses, and I'd argue
that the bigger compatibility break was the change from no-copy in Py2
to copy in Py3 (after all that's the main point of the method...).

See also discussion in #11726.


Added second commit: reimplement tostring_rgba, tostring_rgb using numpy to access the buffer. Note that this was one of the suggestions of the original removal of PyCXX (#3646) :-)

PR Summary

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@tacaswell tacaswell modified the milestones: v3.0, v3.1 Jul 22, 2018
The `buffer_rgba` method now allows direct access to the renderer's
underlying buffer (as a `(m, n, 4)`-shape memoryview) rather than
copying the data to a new bytestring.  This is consistent with the
behavior on Py2, where a buffer object was returned.

While this is technically a backwards-incompatible change, memoryviews
are in fact quite compatible with bytes for most uses, and I'd argue
that the bigger compatibility break was the change from no-copy in Py2
to copy in Py3 (after all that's the main point of the method...).
Copy link
Member

@pelson pelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to remove some of the old backend_agg code here, especially as it is being replaced by built-in memoryviews.

I haven't looked at the impact of downstream users of tostring_argb etc., I assume that PIL happily consumes numpy.ndarray.tobytes and memoryviews, and that PIL will be the primary target for most direct users of these methods.

@@ -15,7 +15,7 @@
fig.canvas.draw()

# grab the pixel buffer and dump it into a numpy array
X = np.array(fig.canvas.renderer._renderer)
X = np.array(fig.canvas.renderer.buffer_rgba())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wowzers. Good catch.


def tostring_argb(self):
return self._renderer.tostring_argb()
return np.asarray(self._renderer).take([3, 0, 1, 2], axis=2).tobytes()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you take a look at uses of this and tostring_rgb on things like StackOverflow to confirm that the type change would continue to work as expected in those use-cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here there is no change to the return type, it was a bytes, it's still a bytes.

There's a change in the return type of buffer_rgba() but that's sort of the whole point of the PR (and it goes back to the old Py2 behavior, and is also clearly better for performance).

@timhoffm
Copy link
Member

Not sure about the squashing/merging policy. I'd say the changes are unrelated and can go in as separate PRs. However, I can only "squash and merge" or "create a merge commit". Naturally I'd use "rebase and merge", but that's not enabled for the repo.

@QuLogic
Copy link
Member

QuLogic commented Dec 26, 2018

Why would you want to rebase and merge? It's the same as just merging, but more annoying.

@QuLogic QuLogic merged commit 529eb3d into matplotlib:master Dec 27, 2018
@anntzer anntzer deleted the aggbufferrgba branch December 27, 2018 08:07
@timhoffm
Copy link
Member

timhoffm commented Dec 28, 2018

Why would you want to rebase and merge? It's the same as just merging, but more annoying.

@QuLogic Not quite sure , if it would really be working the way I intended. But with a rebase the merge could be fast forward, so that the revision history stays more linear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants