mirror of https://github.com/kivy/kivy.git
Make blit_buffer accept memoryviews and objects that implement the buffer interface in additon to bytes. Use new conversion function.
This commit is contained in:
parent
1565c28cc2
commit
801e1ee6ce
|
@ -42,15 +42,17 @@ Blitting custom data
|
|||
--------------------
|
||||
|
||||
You can create your own data and blit it to the texture using
|
||||
:meth:`Texture.blit_data`::
|
||||
:meth:`Texture.blit_buffer`.
|
||||
|
||||
For example, to blit immutable bytes data::
|
||||
|
||||
# create a 64x64 texture, defaults to rgb / ubyte
|
||||
texture = Texture.create(size=(64, 64))
|
||||
|
||||
# create 64x64 rgb tab, and fill with value from 0 to 255
|
||||
# create 64x64 rgb tab, and fill with values from 0 to 255
|
||||
# we'll have a gradient from black to white
|
||||
size = 64 * 64 * 3
|
||||
buf = [int(x * 255 / size) for x in xrange(size)]
|
||||
buf = [int(x * 255 / size) for x in range(size)]
|
||||
|
||||
# then, convert the array to a ubyte string
|
||||
buf = b''.join(map(chr, buf))
|
||||
|
@ -63,6 +65,34 @@ You can create your own data and blit it to the texture using
|
|||
with self.canvas:
|
||||
Rectangle(texture=texture, pos=self.pos, size=(64, 64))
|
||||
|
||||
Since 1.8.1, you can blit data stored in a instance that implements the python
|
||||
buffer interface, or a memoryview thereof, such as numpy arrays, python
|
||||
`array.array`, a `bytearray`, or a cython array. This is beneficial if you
|
||||
expect to blit similar data, with perhaps a few changes in the data.
|
||||
|
||||
When using a bytes representation of the data, for every change you have to
|
||||
regenerate the bytes instance, from perhaps a list, which is very inefficient.
|
||||
When using a buffer object, you can simply edit parts of the original data.
|
||||
Similarly, unless starting with a bytes object, converting to bytes requires a
|
||||
full copy, however, when using a buffer instance, no memory is copied, except
|
||||
to upload it to the GPU.
|
||||
|
||||
Continuing with the example above::
|
||||
|
||||
from array import array
|
||||
|
||||
size = 64 * 64 * 3
|
||||
buf = [int(x * 255 / size) for x in range(size)]
|
||||
# initialize the array with the buffer values
|
||||
arr = array('B', buf)
|
||||
# now blit the array
|
||||
texture.blit_buffer(arr, colorfmt='rgb', bufferfmt='ubyte')
|
||||
|
||||
# now change some elements in the original array
|
||||
arr[24] = arr[50] = 99
|
||||
# blit again the buffer
|
||||
texture.blit_buffer(arr, colorfmt='rgb', bufferfmt='ubyte')
|
||||
|
||||
|
||||
BGR/BGRA support
|
||||
----------------
|
||||
|
@ -194,7 +224,6 @@ include "common.pxi"
|
|||
include "opengl_utils_def.pxi"
|
||||
include "img_tools.pxi"
|
||||
|
||||
from array import array
|
||||
from kivy.weakmethod import WeakMethod
|
||||
from kivy.graphics.context cimport get_context
|
||||
|
||||
|
@ -802,8 +831,15 @@ cdef class Texture:
|
|||
called in order to update the texture.
|
||||
|
||||
:Parameters:
|
||||
`pbuffer` : bytes
|
||||
Image data.
|
||||
`pbuffer` : bytes, or a class that implements the buffer interface\
|
||||
(including memoryview).
|
||||
A buffer containing the image data. It can be either a bytes
|
||||
object or a instance of a class that implements the python
|
||||
buffer interface, e.g. `array.array`, `bytearray`, numpy arrays
|
||||
etc. If it's not a bytes object, the underlying buffer must
|
||||
be contiguous, have only one dimension and must not be
|
||||
readonly, even though the data is not modified, due to a cython
|
||||
limitation. See module description for usage details.
|
||||
`size` : tuple, defaults to texture size
|
||||
Size of the image (width, height)
|
||||
`colorfmt` : str, defaults to 'rgb'
|
||||
|
@ -820,9 +856,12 @@ cdef class Texture:
|
|||
Indicate if we need to regenerate the mipmap from level 0.
|
||||
|
||||
.. versionadded:: 1.0.7
|
||||
|
||||
added `mipmap_level` and `mipmap_generation`
|
||||
|
||||
.. versionchanged:: 1.8.1
|
||||
`pbuffer` can now be any class instance that implements the python
|
||||
buffer interface and / or memoryviews thereof.
|
||||
|
||||
'''
|
||||
cdef GLuint target = self._target
|
||||
if colorfmt is None:
|
||||
|
@ -839,20 +878,27 @@ cdef class Texture:
|
|||
# time.
|
||||
self.bind()
|
||||
|
||||
# need conversion ?
|
||||
cdef bytes data
|
||||
data = pbuffer
|
||||
data, colorfmt = _convert_buffer(data, colorfmt)
|
||||
# need conversion, do check here because it seems to be faster ?
|
||||
if not gl_has_texture_native_format(colorfmt):
|
||||
pbuffer, colorfmt = convert_to_gl_format(pbuffer, colorfmt)
|
||||
cdef char [:] view
|
||||
cdef char *cdata
|
||||
cdef long datasize
|
||||
if isinstance(pbuffer, bytes): # if it's bytes, just use memory
|
||||
cdata = <bytes>pbuffer # explicit bytes
|
||||
datasize = len(pbuffer)
|
||||
else: # if it's a memoryview or buffer type, use start of memory
|
||||
view = pbuffer
|
||||
cdata = &view[0]
|
||||
datasize = view.nbytes
|
||||
|
||||
# prepare nogil
|
||||
cdef int iglfmt = _color_fmt_to_gl(self._icolorfmt)
|
||||
cdef int glfmt = _color_fmt_to_gl(colorfmt)
|
||||
cdef long datasize = len(pbuffer)
|
||||
cdef int x = pos[0]
|
||||
cdef int y = pos[1]
|
||||
cdef int w = size[0]
|
||||
cdef int h = size[1]
|
||||
cdef char *cdata = <char *>data
|
||||
cdef int glbufferfmt = bufferfmt
|
||||
cdef int is_allocated = self._is_allocated
|
||||
cdef int is_compressed = _is_compressed_fmt(colorfmt)
|
||||
|
|
3
setup.py
3
setup.py
|
@ -428,7 +428,8 @@ graphics_dependencies = {
|
|||
'texture.pxd': ['c_opengl.pxd'],
|
||||
'texture.pyx': [
|
||||
'config.pxi', 'common.pxi', 'opengl_utils_def.pxi', 'context.pxd',
|
||||
'c_opengl.pxd', 'c_opengl_debug.pxd', 'opengl_utils.pxd'],
|
||||
'c_opengl.pxd', 'c_opengl_debug.pxd', 'opengl_utils.pxd',
|
||||
'img_tools.pxi'],
|
||||
'vbo.pxd': ['buffer.pxd', 'c_opengl.pxd', 'vertex.pxd'],
|
||||
'vbo.pyx': [
|
||||
'config.pxi', 'common.pxi', 'c_opengl_debug.pxd', 'context.pxd',
|
||||
|
|
Loading…
Reference in New Issue