Enlightenment CVS committal

Author  : barbieri
Project : e17
Module  : proto/python-efl

Dir     : e17/proto/python-efl/python-evas/evas


Modified Files:
        evas.c_evas_object_image.pxi 


Log Message:
Implement data_get() using Python Buffer API, related methods and add comments.

===================================================================
RCS file: 
/cvs/e/e17/proto/python-efl/python-evas/evas/evas.c_evas_object_image.pxi,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -3 -r1.10 -r1.11
--- evas.c_evas_object_image.pxi        8 Oct 2007 15:09:01 -0000       1.10
+++ evas.c_evas_object_image.pxi        21 Oct 2007 00:51:02 -0000      1.11
@@ -1,8 +1,95 @@
 # This file is included verbatim by c_evas.pyx
 
+cdef int _data_size_get(Evas_Object *obj):
+    cdef int stride, h, bpp, cspace, have_alpha
+    stride = evas_object_image_stride_get(obj)
+    evas_object_image_size_get(obj, NULL, &h)
+    cspace = evas_object_image_colorspace_get(obj)
+    have_alpha = evas_object_image_alpha_get(obj)
+    if cspace == EVAS_COLORSPACE_ARGB8888:
+        bpp = 4
+    elif cspace == EVAS_COLORSPACE_RGB565_A5P:
+        if have_alpha == 0:
+            bpp = 2
+        else:
+            bpp = 3
+    else:
+        return 0 # XXX not supported.
+
+    return stride * h * bpp
+
+
 cdef public class Image(Object) [object PyEvasImage, type PyEvasImage_Type]:
     """Image from file or buffer.
 
+    Introduction
+    ============
+
+    Image will consider the object's L{geometry<Object.geometry_set()>} as
+    the area to paint with tiles as described by L{fill_set()} and the real
+    pixels (image data) will be stored as described by
+    L{image_size<image_size_set()>}. This can be tricky to understand at
+    first, but gives flexibility to do everything.
+
+    If an image is loaded from file, it will have
+    L{image_size<image_size_set()>} set to its original size, unless some
+    other size was set with L{load_size_set()}, L{load_dpi_set()} or
+    L{load_scale_down_set()}.
+
+    Pixels will be scaled to match size specified by L{fill_set()}
+    using either sampled or smooth methods, these can be specified with
+    L{smooth_scale_set()}. The scale will consider borders as specified by
+    L{border_set()} and L{border_center_fill_set()}, while the former specify
+    the border dimensions (top and bottom will scale horizontally, while
+    right and left will do vertically, corners are kept unscaled), the latter
+    says whenever the center of the image will be used (useful to create
+    frames).
+
+    Contents will be tiled using L{fill_set()} information in order to paint
+    L{geometry<Object.geometry_set()>}, so if you want an image to be drawn
+    just once, you should match every L{geometry_set(x, y, w, h)} by a call
+    to L{fill_set(0, 0, w, h)}. L{FilledImage} does that for you.
+
+    Pixel data and buffer API
+    =========================
+
+    Images implement the Python Buffer API, so it's possible to use it
+    where buffers are expected (ie: file.write()). Available data will
+    depend on L{alpha<alpha_set()>}, L{colorspace<colorspace_set()>} and
+    L{image_size<image_size_set()>}, lines should be considered multiple
+    of L{stride<stride_get()>}, with the following considerations about
+    colorspace:
+     - B{EVAS_COLORSPACE_ARGB8888:} This pixel format is a linear block of
+       pixels, starting at the top-left row by row until the bottom right of
+       the image or pixel region. All pixels are 32-bit unsigned int's with
+       the high-byte being alpha and the low byte being blue in the format
+       ARGB. Alpha may or may not be used by evas depending on the alpha flag
+       of the image, but if not used, should be set to 0xff anyway.
+       This colorspace uses premultiplied alpha. That means that R, G and B
+       cannot exceed A in value. The conversion from non-premultiplied
+       colorspace is::
+         R = (r * a) / 255; G = (g * a) / 255; B = (b * a) / 255;
+       So 50% transparent blue will be: 0x80000080. This will not be "dark" -
+       just 50% transparent. Values are 0 == black, 255 == solid or full
+       red, green or blue.
+     - B{EVAS_COLORSPACE_RGB565_A5P:} In the process of being implemented in
+       1 engine only. This may change. This is a pointer to image data for
+       16-bit half-word pixel data in 16bpp RGB 565 format (5 bits red,
+       6 bits green, 5 bits blue), with the high-byte containing red and the
+       low byte containing blue, per pixel. This data is packed row by row
+       from the top-left to the bottom right. If the image has an alpha
+       channel enabled there will be an extra alpha plane B{after} the color
+       pixel plane. If not, then this data will not exist and should not be
+       accessed in any way. This plane is a set of pixels with 1 byte per
+       pixel defining the alpha values of all pixels in the image from
+       the top-left to the bottom right of the image, row by row. Even though
+       the values of the alpha pixels can be 0 to 255, only values 0 through
+       to 31 are used, 31 being solid and 0 being transparent.
+       RGB values can be 0 to 31 for red and blue and 0 to 63 for green, with 0
+       being black and 31 or 63 being full red, green or blue respectively.
+       This colorspace is also pre-multiplied like EVAS_COLORSPACE_ARGB8888 
so::
+         R = (r * a) / 32; G = (g * a) / 32; B = (b * a) / 32;
+
     @note: if an image is resized it will B{tile} it's contents respecting
       geometry set by L{fill_set()}, so if you want the contents to be
       B{scaled} you need to call L{fill_set()} with C{x=0, y=0, w=new_width,
@@ -14,8 +101,8 @@
        load_dpi_set, load_dpi_get, load_dpi,
        load_scale_down_set, load_scale_down_get, load_scale_down
     @group Often unused: alpha_set, alpha_get, alpha, colorspace_set,
-       colorspace_set, colorspace, pixels_dirty_set, pixels_dirty_get,
-       pixels_dirty
+       colorspace_get, colorspace, pixels_dirty_set, pixels_dirty_get,
+       pixels_dirty, image_data_set, image_data_update_add
     """
     def __init__(self, Canvas canvas not None, **kargs):
         Object.__init__(self, canvas)
@@ -180,6 +267,13 @@
         larger, then the image will be treated as if it were in the upper
         left hand corner of a larger image that is otherwise transparent.
 
+        This method will force pixels to be allocated if they weren't, so
+        you should use this before accessing the image as a buffer in order
+        to allocate the pixels.
+
+        This method will recalculate L{stride} (L{stride_get()}) based on
+        width and the colorspace.
+
         @parm: B{w}
         @parm: B{h}
         """
@@ -192,6 +286,30 @@
         def __set__(self, spec):
             self.image_size_set(*spec)
 
+    def stride_get(self):
+        """Get the row stride (in pixels) being used to draw this image.
+
+           While image have logical dimension of width and height set by
+           L{image_size_set()}, the line can be a bit larger than width to
+           improve memory alignment.
+
+           The amount of bytes will change based on colorspace, while using
+           ARGB8888 it will be multiple of 4 bytes, with colors being laid
+           out interleaved, RGB565_A5P will have the first part being RGB
+           data using stride in multiple of 2 bytes and after that an
+           alpha plane with data using stride in multiple of 1 byte.
+
+           @note: This value can change after L{image_size_set()}.
+           @note: Unit is pixels, not bytes.
+
+           @rtype: int
+        """
+        return evas_object_image_stride_get(self.obj)
+
+    property stride:
+        def __get__(self):
+            return self.stride_get()
+
     def alpha_get(self):
         "@rtype: bool"
         return bool(evas_object_image_alpha_get(self.obj))
@@ -342,6 +460,81 @@
         else:
             f = NULL
         evas_object_image_save(self.obj, filename, key, flags)
+
+    def __getsegcount__(self, int *p_len):
+        if p_len == NULL:
+            return 1
+
+        p_len[0] = _data_size_get(self.obj)
+        return 1
+
+    def __getreadbuffer__(self, int segment, void **ptr):
+        ptr[0] = evas_object_image_data_get(self.obj, 0)
+        if ptr[0] == NULL:
+            raise SystemError("image has no allocated buffer.")
+        # XXX: keep Evas pixels_checked_out counter to 0 and allow
+        # XXX: image to reload and unload its data.
+        # XXX: may cause problems if buffer is used after these
+        # XXX: functions are called, but buffers aren't expected to
+        # XXX: live much.
+        evas_object_image_data_set(self.obj, ptr[0])
+        return _data_size_get(self.obj)
+
+    def __getwritebuffer__(self, int segment, void **ptr):
+        ptr[0] = evas_object_image_data_get(self.obj, 1)
+        if ptr[0] == NULL:
+            raise SystemError("image has no allocated buffer.")
+        # XXX: keep Evas pixels_checked_out counter to 0 and allow
+        # XXX: image to reload and unload its data.
+        # XXX: may cause problems if buffer is used after these
+        # XXX: functions are called, but buffers aren't expected to
+        # XXX: live much.
+        evas_object_image_data_set(self.obj, ptr[0])
+        return _data_size_get(self.obj)
+
+    def __getcharbuffer__(self, int segment, char **ptr):
+        ptr[0] = <char *>evas_object_image_data_get(self.obj, 0)
+        if ptr[0] == NULL:
+            raise SystemError("image has no allocated buffer.")
+        # XXX: keep Evas pixels_checked_out counter to 0 and allow
+        # XXX: image to reload and unload its data.
+        # XXX: may cause problems if buffer is used after these
+        # XXX: functions are called, but buffers aren't expected to
+        # XXX: live much.
+        evas_object_image_data_set(self.obj, ptr[0])
+        return _data_size_get(self.obj)
+
+    def image_data_set(self, buf):
+        """Sets the raw image data.
+
+        The given buffer will be B{copied}, so it's safe to give it a
+        temporary object.
+
+        @note: that the raw data must be of the same size and colorspace
+           of the image. If data is None the current image data will be freed.
+        """
+        cdef void *p_data
+        cdef Py_ssize_t size, expected_size
+
+        if buf is None:
+            evas_object_image_data_set(self.obj, NULL)
+            return
+
+        python.PyObject_AsReadBuffer(buf, &p_data, &size)
+        if p_data != NULL:
+            expected_size = _data_size_get(self.obj)
+            if size < expected_size:
+                raise ValueError(("buffer size (%d) is smalled than expected "
+                                  "(%d)!") % (size, expected_size))
+        evas_object_image_data_set(self.obj, p_data)
+
+    def image_data_update_add(self, x, y, w, h):
+        """Mark a sub-region of the image to be redrawn.
+
+        This function schedules a particular rectangular region
+        to be updated (redrawn) at the next render.
+        """
+        evas_object_image_data_update_add(self.obj, x, y, w, h)
 
 
 cdef extern from "Python.h":



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to