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

Skip to content

Commit 003dea9

Browse files
authored
Merge pull request matplotlib#6602 from jenshnielsen/cairoimage
Fix image plotting in Cairo backends
2 parents c1410f9 + 5aa9b50 commit 003dea9

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

lib/matplotlib/backends/backend_cairo.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
6868
BYTE_FORMAT = 1 # ARGB
6969

7070

71+
class ArrayWrapper:
72+
"""Thin wrapper around numpy ndarray to expose the interface
73+
expected by cairocffi. Basically replicates the
74+
array.array interface.
75+
"""
76+
def __init__(self, myarray):
77+
self.__array = myarray
78+
self.__data = myarray.ctypes.data
79+
self.__size = len(myarray.flatten())
80+
self.itemsize = myarray.itemsize
81+
82+
def buffer_info(self):
83+
return (self.__data, self.__size)
84+
85+
7186
class RendererCairo(RendererBase):
7287
fontweights = {
7388
100 : cairo.FONT_WEIGHT_NORMAL,
@@ -175,9 +190,25 @@ def draw_image(self, gc, x, y, im):
175190
im = im[:, :, (2, 1, 0, 3)]
176191
else:
177192
im = im[:, :, (3, 0, 1, 2)]
178-
surface = cairo.ImageSurface.create_for_data(
179-
memoryview(im.flatten()), cairo.FORMAT_ARGB32, im.shape[1], im.shape[0],
180-
im.shape[1]*4)
193+
if HAS_CAIRO_CFFI:
194+
# cairocffi tries to use the buffer_info from array.array
195+
# that we replicate in ArrayWrapper and alternatively falls back
196+
# on ctypes to get a pointer to the numpy array. This works
197+
# correctly on a numpy array in python3 but not 2.7. We replicate
198+
# the array.array functionality here to get cross version support.
199+
imbuffer = ArrayWrapper(im.flatten())
200+
else:
201+
# py2cairo uses PyObject_AsWriteBuffer
202+
# to get a pointer to the numpy array this works correctly
203+
# on a regular numpy array but not on a memory view.
204+
# At the time of writing the latest release version of
205+
# py3cairo still does not support create_for_data
206+
imbuffer = im.flatten()
207+
surface = cairo.ImageSurface.create_for_data(imbuffer,
208+
cairo.FORMAT_ARGB32,
209+
im.shape[1],
210+
im.shape[0],
211+
im.shape[1]*4)
181212
ctx = gc.ctx
182213
y = self.height - y - im.shape[0]
183214

0 commit comments

Comments
 (0)