Skip to content

Commit c1782f6

Browse files
committed
Implemented the buffer protocol in sf.Image
The Pixels was therefore removed. Use memoryview(image) or simply image.pixels to access the underlying byte array. Other method implementations were adjusted.
1 parent 8d2f0a7 commit c1782f6

File tree

6 files changed

+46
-78
lines changed

6 files changed

+46
-78
lines changed

include/Includes/pysfml/window.pxd

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ cdef extern from "pysfml/window/window.h":
1616
cdef class sfml.window.ContextSettings [object PyContextSettingsObject]:
1717
cdef sf.ContextSettings *p_this
1818

19-
cdef class sfml.window.Pixels [object PyPixelsObject]:
20-
cdef Uint8 *p_array
21-
cdef unsigned int m_width
22-
cdef unsigned int m_height
23-
2419
cdef class sfml.window.Event [object PyEventObject]:
2520
cdef sf.Event *p_this
2621

include/Includes/sfml/sfml.pxd

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,6 @@ cdef extern from "SFML/Window.hpp" namespace "sf":
292292

293293
cimport blendmode, primitivetype, texture, shader, font, text, renderstates, transform
294294

295-
cdef extern from *:
296-
ctypedef unsigned char* const_Uint8_ptr "const unsigned char*"
297-
298-
299295
cdef extern from "SFML/Graphics.hpp" namespace "sf":
300296
cdef cppclass Rect[T]:
301297
Rect()
@@ -375,7 +371,7 @@ cdef extern from "SFML/Graphics.hpp" namespace "sf":
375371
cdef cppclass Image:
376372
Image()
377373
void create(unsigned int, unsigned int)
378-
void create(unsigned int, unsigned int, const const_Uint8_ptr)
374+
void create(unsigned int, unsigned int, const Uint8*)
379375
void create(unsigned int, unsigned int, const Color)
380376
bint loadFromFile(char*&)
381377
bint loadFromMemory(const void*, size_t)

src/sfml/graphics/DerivableDrawable.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
#include <pysfml/graphics/NumericObject.hpp>
1313
#include <pysfml/graphics/graphics_api.h>
1414

15+
const sf::Uint8* getPixelsPtr(PyObject* memoryview)
16+
{
17+
Py_buffer* buffer = PyMemoryView_GET_BUFFER(memoryview);
18+
return static_cast<const sf::Uint8*>(buffer->buf);
19+
}
20+
1521
DerivableDrawable::DerivableDrawable(PyObject* object) :
1622
m_object(object)
1723
{

src/sfml/graphics/DerivableDrawable.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "Python.h"
1414
#include <SFML/Graphics/Drawable.hpp>
1515

16+
17+
const sf::Uint8* getPixelsPtr(PyObject* memoryview);
18+
1619
class DerivableDrawable : public sf::Drawable
1720
{
1821
public:

src/sfml/graphics/graphics.pyx

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@ cdef extern from "pysfml/graphics/DerivableDrawable.hpp":
1515
cdef cppclass DerivableDrawable:
1616
DerivableDrawable(object)
1717

18+
const Uint8* getPixelsPtr(object)
19+
1820
cdef extern from "pysfml/graphics/DerivableRenderWindow.hpp":
1921
cdef cppclass DerivableRenderWindow:
2022
DerivableRenderWindow(object)
2123

22-
cdef extern from *:
23-
ctypedef void* PyUnicodeObject
24-
2524
from libc.stdlib cimport malloc, free
2625

2726
__all__ = ['BlendMode', 'PrimitiveType', 'Color', 'Rect', 'Transform',
@@ -45,8 +44,7 @@ from pysfml.system cimport Vector2, Vector3
4544
from pysfml.system cimport to_vector2i, to_vector2f
4645
from pysfml.system cimport to_string, wrap_string
4746
from pysfml.system cimport popLastErrorMessage, import_sfml__system
48-
from pysfml.window cimport VideoMode, ContextSettings, Pixels, Window
49-
from pysfml.window cimport wrap_pixels
47+
from pysfml.window cimport VideoMode, ContextSettings, Window
5048

5149
import_sfml__system()
5250

@@ -484,6 +482,22 @@ cdef public class Image[type PyImageType, object PyImageObject]:
484482
p[0] = self.p_this[0]
485483
return wrap_image(p)
486484

485+
def __getbuffer__(self, Py_buffer *buffer, int flags):
486+
buffer.buf = <char*>self.p_this.getPixelsPtr()
487+
buffer.format = 'c'
488+
buffer.internal = NULL
489+
buffer.itemsize = 1
490+
buffer.len = self.p_this.getSize().x * self.p_this.getSize().y * 4
491+
buffer.ndim = 1
492+
buffer.obj = self
493+
buffer.readonly = 1
494+
buffer.shape = NULL
495+
buffer.strides = NULL
496+
buffer.suboffsets = NULL
497+
498+
def __releasebuffer__(self, Py_buffer *buffer):
499+
pass
500+
487501
@classmethod
488502
def create(cls, unsigned int width, unsigned int height, Color color=None):
489503
cdef sf.Image *p = new sf.Image()
@@ -507,15 +521,12 @@ cdef public class Image[type PyImageType, object PyImageObject]:
507521
return wrap_image(p)
508522

509523
@classmethod
510-
def from_pixels(cls, Pixels pixels):
511-
cdef sf.Image *p
512-
513-
if pixels.p_array != NULL:
514-
p = new sf.Image()
515-
p.create(pixels.m_width, pixels.m_height, pixels.p_array)
516-
return wrap_image(p)
524+
def from_pixels(cls, int width, int height, pixels):
525+
cdef sf.Image *p = new sf.Image()
526+
cdef const sf.Uint8* pixels_ptr = getPixelsPtr(memoryview(pixels))
517527

518-
raise ValueError("Failed to create texture, invalid array (NULL)")
528+
p.create(width, height, pixels_ptr)
529+
return wrap_image(p)
519530

520531
@classmethod
521532
def from_file(cls, filename):
@@ -575,8 +586,7 @@ cdef public class Image[type PyImageType, object PyImageObject]:
575586

576587
property pixels:
577588
def __get__(self):
578-
if self.p_this.getPixelsPtr():
579-
return wrap_pixels(<Uint8*>self.p_this.getPixelsPtr(), self.width, self.height)
589+
return memoryview(self)
580590

581591
def flip_horizontally(self):
582592
self.p_this.flipHorizontally()
@@ -722,16 +732,7 @@ cdef public class Texture[type PyTextureType, object PyTextureObject]:
722732
if len(args) > 2:
723733
raise UserWarning("Too much arguments provided. It requires at most two.")
724734

725-
if type(args[0]) is Pixels:
726-
if len(args) == 2:
727-
if type(args[1]) in [Vector2, tuple]:
728-
self.update_from_pixels(args[0], args[1])
729-
else:
730-
raise UserWarning("The second argument must be either a sf.Vector2 or a tuple")
731-
else:
732-
self.update_from_pixels(args[0])
733-
734-
elif type(args[0]) is Image:
735+
if type(args[0]) is Image:
735736
if len(args) == 2:
736737
if type(args[1]) in [Vector2, tuple]:
737738
self.update_from_image(args[0], args[1])
@@ -752,13 +753,14 @@ cdef public class Texture[type PyTextureType, object PyTextureObject]:
752753
else:
753754
raise UserWarning("The first argument must be either sf.Pixels, sf.Image or sf.Window")
754755

756+
def update_from_pixels(self, pixels, *args):
757+
cdef const sf.Uint8* pixels_ptr = getPixelsPtr(memoryview(pixels))
755758

756-
def update_from_pixels(self, Pixels pixels, position=None):
757-
if not position:
758-
self.p_this.update(pixels.p_array)
759+
if not args:
760+
self.p_this.update(pixels_ptr)
759761
else:
760-
x, y = position
761-
self.p_this.update(pixels.p_array, pixels.m_width, pixels.m_height, <unsigned int>x, <unsigned int>y)
762+
width, height, x, y = args
763+
self.p_this.update(pixels_ptr, width, height, x, y)
762764

763765
def update_from_image(self, Image image, position=None):
764766
if not position:

src/sfml/window/window.pyx

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ __all__ = ['Style', 'VideoMode', 'ContextSettings', 'Event', 'EventType',
3333
'CloseEvent', 'ResizeEvent', 'FocusEvent', 'TextEvent',
3434
'KeyEvent', 'MouseWheelEvent', 'MouseButtonEvent',
3535
'MouseMoveEvent', 'MouseEvent', 'JoystickButtonEvent',
36-
'JoystickMoveEvent', 'JoystickConnectEvent', 'Pixels',
37-
'Window', 'Keyboard', 'Joystick', 'Mouse', 'Touch',
38-
'Sensor', 'Context']
36+
'JoystickMoveEvent', 'JoystickConnectEvent', 'Window',
37+
'Keyboard', 'Joystick', 'Mouse', 'Touch', 'Sensor', 'Context']
3938

4039
if PY_VERSION_HEX >= 0x03000000:
4140
unichr = chr
@@ -720,38 +719,6 @@ cdef ContextSettings wrap_contextsettings(sf.ContextSettings *v):
720719
return r
721720

722721

723-
cdef public class Pixels[type PyPixelsType, object PyPixelsObject]:
724-
cdef Uint8* p_array
725-
cdef unsigned int m_width
726-
cdef unsigned int m_height
727-
728-
def __init__(self):
729-
raise UserWarning("This class is not meant to be used directly")
730-
731-
def __repr__(self):
732-
return "Pixels(width={0}, height={1})".format(self.width, self.height)
733-
734-
def __getitem__(self, unsigned int index):
735-
return self.p_this[index]
736-
737-
property width:
738-
def __get__(self):
739-
return self.m_width
740-
741-
property height:
742-
def __get__(self):
743-
return self.m_height
744-
745-
property data:
746-
def __get__(self):
747-
return (<char*>self.p_array)[:self.width*self.height*4]
748-
749-
cdef api Pixels wrap_pixels(Uint8 *p, unsigned int w, unsigned int h):
750-
cdef Pixels r = Pixels.__new__(Pixels)
751-
r.p_array, r.m_width, r.m_height = p, w, h
752-
return r
753-
754-
755722
cdef public class Window[type PyWindowType, object PyWindowObject]:
756723
cdef sf.Window *p_window
757724

@@ -830,9 +797,8 @@ cdef public class Window[type PyWindowType, object PyWindowObject]:
830797
def __set__(self, title):
831798
self.p_window.setTitle(to_string(title))
832799

833-
property icon:
834-
def __set__(self, Pixels icon):
835-
self.p_window.setIcon(icon.m_width, icon.m_height, icon.p_array)
800+
def set_icon(self, int width, int height, bytes pixels):
801+
self.p_window.setIcon(width, height, <sf.Uint8*>pixels)
836802

837803
property visible:
838804
def __set__(self, bint visible):

0 commit comments

Comments
 (0)