diff options
author | Campbell Barton <ideasman42@gmail.com> | 2008-03-10 15:17:58 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2008-03-10 15:17:58 +0300 |
commit | 2b42733105b4f7a89a880e53ea706a24515f0840 (patch) | |
tree | a0dadb144815524b7ecfbe995636f8d2e2a70cec /source/blender/python | |
parent | 0ec0f2a02fb4d6e87db8fe8c7b9027ceab0263af (diff) |
Applied [#7076] Updated Python Image API to use float buffers in getPixelF/setPixelF
and added an image.updateDisplay() function to update imbuf->rect from imbuf->rect_float
also corrected some docstrings and epydocs
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/api2_2x/Image.c | 98 | ||||
-rw-r--r-- | source/blender/python/api2_2x/bpy_data.c | 12 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/Armature.py | 10 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/Group.py | 6 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/Image.py | 16 |
5 files changed, 91 insertions, 51 deletions
diff --git a/source/blender/python/api2_2x/Image.c b/source/blender/python/api2_2x/Image.c index ec822004596..a182563170d 100644 --- a/source/blender/python/api2_2x/Image.c +++ b/source/blender/python/api2_2x/Image.c @@ -38,6 +38,7 @@ #include "BKE_library.h" #include "BKE_image.h" #include "BKE_idprop.h" +#include "BKE_utildefines.h" #include "BIF_drawimage.h" #include "BLI_blenlib.h" #include "DNA_space_types.h" /* FILE_MAXDIR = 160 */ @@ -106,6 +107,7 @@ static PyObject *Image_setStart( BPy_Image * self, PyObject * args ); static PyObject *Image_setEnd( BPy_Image * self, PyObject * args ); static PyObject *Image_setSpeed( BPy_Image * self, PyObject * args ); static PyObject *Image_reload( BPy_Image * self ); +static PyObject *Image_updateDisplay( BPy_Image * self ); static PyObject *Image_glLoad( BPy_Image * self ); static PyObject *Image_glFree( BPy_Image * self ); static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ); @@ -126,11 +128,11 @@ static PyObject *Image_makeCurrent( BPy_Image * self ); static PyMethodDef BPy_Image_methods[] = { /* name, method, flags, doc */ {"getPixelF", ( PyCFunction ) Image_getPixelF, METH_VARARGS, - "(int, int) - Get pixel color as floats 0.0-1.0 returns [r,g,b,a]"}, + "(int, int) - Get pixel color as floats returns [r,g,b,a]"}, {"getPixelI", ( PyCFunction ) Image_getPixelI, METH_VARARGS, "(int, int) - Get pixel color as ints 0-255 returns [r,g,b,a]"}, {"setPixelF", ( PyCFunction ) Image_setPixelF, METH_VARARGS, - "(int, int, [f r,f g,f b,f a]) - Set pixel color using floats 0.0-1.0"}, + "(int, int, [f r,f g,f b,f a]) - Set pixel color using floats"}, {"setPixelI", ( PyCFunction ) Image_setPixelI, METH_VARARGS, "(int, int, [i r, i g, i b, i a]) - Set pixel color using ints 0-255"}, {"getMaxXY", ( PyCFunction ) Image_getMaxXY, METH_NOARGS, @@ -159,6 +161,8 @@ static PyMethodDef BPy_Image_methods[] = { "() - Return Image object's bind code value"}, {"reload", ( PyCFunction ) Image_reload, METH_NOARGS, "() - Reload the image from the filesystem"}, + {"updateDisplay", ( PyCFunction ) Image_updateDisplay, METH_NOARGS, + "() - Update the display image from the floating point buffer (if it exists)"}, {"glLoad", ( PyCFunction ) Image_glLoad, METH_NOARGS, "() - Load the image data in OpenGL texture memory.\n\ The bindcode (int) is returned."}, @@ -199,7 +203,7 @@ static PyMethodDef BPy_Image_methods[] = { static char M_Image_doc[] = "The Blender Image module\n\n"; static char M_Image_New_doc[] = - "() - return a new Image object"; + "(name, width, height, depth) - all args are optional, return a new Image object"; static char M_Image_Get_doc[] = "(name) - return the image with the name 'name', \ @@ -243,7 +247,7 @@ static PyObject *M_Image_New( PyObject * self, PyObject * args) if (width > 5000 || height > 5000 || width < 1 || height < 1) return ( EXPP_ReturnPyObjError( PyExc_TypeError, "Image width and height must be between 1 and 5000" ) ); - image = BKE_add_image_size(width, height, name, 0, 0, color); + image = BKE_add_image_size(width, height, name, depth==128 ? 1 : 0, 0, color); if( !image ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyObject Image_Type" ) ); @@ -382,27 +386,25 @@ static PyObject *M_Image_Load( PyObject * self, PyObject * value ) /** * getPixelF( x, y ) * returns float list of pixel colors in rgba order. - * returned values are floats normalized to 0.0 - 1.0. - * blender images are all 4x8 bit at the moment apr-2005 - */ + * returned values are floats , in the full range of the float image source. + */ static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ) { PyObject *attr; ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); - char *pixel; /* image data */ int index; /* offset into image data */ int x = 0; int y = 0; - int pixel_size = 4; /* each pixel is 4 x 8-bits packed in unsigned int */ + int pixel_size = 4; /* each pixel is 4 x 32 bit float */ int i; if( !PyArg_ParseTuple( args, "ii", &x, &y ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 integers" ); - if( !ibuf || !ibuf->rect ) /* loading didn't work */ + if( !ibuf || (!ibuf->rect_float && !ibuf->rect)) /* loading didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); @@ -428,15 +430,26 @@ static PyObject *Image_getPixelF( BPy_Image * self, PyObject * args ) "couldn't allocate memory for color list" ); index = ( x + y * ibuf->x ) * pixel_size; - - pixel = ( char * ) ibuf->rect; - for (i=0; i<4; i++) { - PyList_SetItem( attr, i, PyFloat_FromDouble( ( ( double ) pixel[index+i] ) / 255.0 )); + + /* if a float buffer exists, use it, otherwise convert the 8bpc buffer to float values */ + if (ibuf->rect_float) { + float *pixelf; /* image data */ + + pixelf = ibuf->rect_float; + for (i=0; i<4; i++) { + PyList_SetItem( attr, i, PyFloat_FromDouble( (double)pixelf[index+i] ) ); + } + } else { + char *pixelc; /* image data */ + + pixelc = ( char * ) ibuf->rect; + for (i=0; i<4; i++) { + PyList_SetItem( attr, i, PyFloat_FromDouble( ( ( double ) pixelc[index+i] ) / 255.0 )); + } } return attr; } - /** * getPixelI( x, y ) * returns integer list of pixel colors in rgba order. @@ -497,12 +510,11 @@ static PyObject *Image_getPixelI( BPy_Image * self, PyObject * args ) static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) { ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); - char *pixel; /* image data */ + float *pixel; /* image data */ int index; /* offset into image data */ int x = 0; int y = 0; - int a = 0; - int pixel_size = 4; /* each pixel is 4 x 8-bits packed in unsigned int */ + int pixel_size = 4; /* each pixel is 4 x 32 bit float */ float p[4]; if( !PyArg_ParseTuple @@ -510,7 +522,7 @@ static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 integers and an array of 4 floats" ); - if( !ibuf || !ibuf->rect ) /* didn't work */ + if( !ibuf ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); @@ -522,28 +534,16 @@ static PyObject *Image_setPixelF( BPy_Image * self, PyObject * args ) || y > ( ibuf->y - 1 ) || x < ibuf->xorig || y < ibuf->yorig ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "x or y is out of ruange" ); - - for( a = 0; a < 4; a++ ) { - if( p[a] > 1.0 || p[a] < 0.0 ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "r, g, b, or a is out of range" ); - } - - - /* - assumption: from looking at source, skipx is often not set, - so we calc ourselves - */ + "x or y is out of range" ); + /* if no float buffer already exists, add it */ + if (!ibuf->rect_float) imb_addrectfloatImBuf(ibuf); + index = ( x + y * ibuf->x ) * pixel_size; - pixel = ( char * ) ibuf->rect; - - pixel[index] = ( char ) ( p[0] * 255.0 ); - pixel[index + 1] = ( char ) ( p[1] * 255.0 ); - pixel[index + 2] = ( char ) ( p[2] * 255.0 ); - pixel[index + 3] = ( char ) ( p[3] * 255.0 ); + pixel = ibuf->rect_float + index; + + QUATCOPY(pixel, p); ibuf->userflags |= IB_BITMAPDIRTY; Py_RETURN_NONE; @@ -821,8 +821,11 @@ static PyObject *Image_getDepth( BPy_Image * self ) if( !ibuf ) /* didn't work */ return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't load image data in Blender" ); - - return PyInt_FromLong( (long)ibuf->depth ); + if (ibuf->rect_float) { + return PyInt_FromLong( (long)128 ); + } else { + return PyInt_FromLong( (long)ibuf->depth ); + } } @@ -865,6 +868,21 @@ static PyObject *Image_reload( BPy_Image * self ) Py_RETURN_NONE; } +static PyObject *Image_updateDisplay( BPy_Image * self ) +{ + ImBuf *ibuf= BKE_image_get_ibuf(self->image, NULL); + + if( !ibuf ) /* didn't work */ + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "couldn't load image data in Blender" ); + + IMB_rect_from_float(ibuf); + + Py_RETURN_NONE; +} + + + static PyObject *Image_glFree( BPy_Image * self ) { Image *image = self->image; diff --git a/source/blender/python/api2_2x/bpy_data.c b/source/blender/python/api2_2x/bpy_data.c index 3fb58146ca9..428f8cc6d9a 100644 --- a/source/blender/python/api2_2x/bpy_data.c +++ b/source/blender/python/api2_2x/bpy_data.c @@ -394,7 +394,7 @@ PyObject *LibBlockSeq_new(BPy_LibBlockSeq *self, PyObject * args, PyObject *kwd) { ID *id = NULL; char *name=NULL, *filename=NULL, *data_type=NULL; - int img_width=256, img_height=256; + int img_width=256, img_height=256, img_depth=32; float color[] = {0, 0, 0, 1}; short data_code = 0; int user_count = 0; @@ -456,8 +456,8 @@ PyObject *LibBlockSeq_new(BPy_LibBlockSeq *self, PyObject * args, PyObject *kwd) /* New Data */ if (self->type == ID_IM) { - /* Image, accepts width and height*/ - if( !PyArg_ParseTuple( args, "|sii", &name, &img_width, &img_height ) ) + /* Image, accepts width and height, depth */ + if( !PyArg_ParseTuple( args, "|siii", &name, &img_width, &img_height, &img_depth ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "one string and two ints expected as arguments" ); CLAMP(img_width, 4, 5000); @@ -538,7 +538,7 @@ PyObject *LibBlockSeq_new(BPy_LibBlockSeq *self, PyObject * args, PyObject *kwd) break; case ID_IM: { - id = (ID *)BKE_add_image_size(img_width, img_height, name?name:"Image", 0, 0, color); + id = (ID *)BKE_add_image_size(img_width, img_height, name?name:"Image", img_depth==128 ? 1:0, 0, color); if( !id ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyObject Image_Type" ) ); @@ -562,14 +562,14 @@ PyObject *LibBlockSeq_new(BPy_LibBlockSeq *self, PyObject * args, PyObject *kwd) break; case ID_VF: return EXPP_ReturnPyObjError( PyExc_TypeError, - "Cannot create new fonts, use the load() function to load from a file" ); + "Cannot create new fonts, use the new(name, filename) function to load from a file" ); case ID_TXT: id = (ID *)add_empty_text( name?name:"Text" ); user_count = 1; break; case ID_SO: return EXPP_ReturnPyObjError( PyExc_TypeError, - "Cannot create new sounds, use the load() function to load from a file" ); + "Cannot create new sounds, use the new(name, filename) function to load from a file" ); case ID_GR: id = (ID *)add_group( name?name:"Group" ); user_count = 1; diff --git a/source/blender/python/api2_2x/doc/Armature.py b/source/blender/python/api2_2x/doc/Armature.py index 0dbaf28d6f8..68916af6166 100644 --- a/source/blender/python/api2_2x/doc/Armature.py +++ b/source/blender/python/api2_2x/doc/Armature.py @@ -192,6 +192,16 @@ class Armature: @note: Must have called makeEditable() first. @rtype: None """ + def copy(): + """ + Return a copy of this armature. + @rtype: Armature + """ + def __copy__(): + """ + Return a copy of this armature. + @rtype: Armature + """ import id_generics Armature.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Group.py b/source/blender/python/api2_2x/doc/Group.py index aca7c56b4a5..6bd6e105ec3 100644 --- a/source/blender/python/api2_2x/doc/Group.py +++ b/source/blender/python/api2_2x/doc/Group.py @@ -121,6 +121,12 @@ class Group: @rtype: Group @return: a copy of this group """ + def copy (): + """ + Make a copy of this group + @rtype: Group + @return: a copy of this group + """ import id_generics Group.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Image.py b/source/blender/python/api2_2x/doc/Image.py index 6d613b3c8fe..6b725fa9f78 100644 --- a/source/blender/python/api2_2x/doc/Image.py +++ b/source/blender/python/api2_2x/doc/Image.py @@ -48,7 +48,7 @@ def New (name, width, height, depth): @type height: int @param height: The height of the new Image object, between 1 and 5000. @type depth: int - @param depth: The colour depth of the new Image object. (8:Grey, 24:RGB, 32:RGBA). (Not implimented yet, all new images will be 24bit) + @param depth: The colour depth of the new Image object. (32:RGBA 8bit channels, 128:RGBA 32bit high dynamic range float channels). @rtype: Blender Image @return: A new Blender Image object. """ @@ -83,7 +83,7 @@ class Image: @type filename: string @ivar size: The [width, height] dimensions of the image (in pixels). @type size: list - @ivar depth: The pixel depth of the image. [8, 16, 18, 24, 32] + @ivar depth: The pixel depth of the image, read only. [8, 16, 18, 24, 32, 128 (for 32bit float color channels)] @type depth: int @ivar xrep: Texture tiling: the number of repetitions in the x (horizontal) axis. [1, 16]. @@ -137,14 +137,14 @@ class Image: def getDepth(): """ - Get the pixel depth of this image. + Get the pixel depth of this image. [8,16,24,32,128 for 32bit float images] @rtype: int """ def getPixelF(x, y): """ Get the the colors of the current pixel in the form [r,g,b,a]. - Returned values are floats normalized to 0.0 - 1.0. + For float image types, returned values can be greater then the useual [0.0, 1.0] range. Pixel coordinates are in the range from 0 to N-1. See L{getMaxXY} @returns: [ r, g, b, a] @rtype: list of 4 floats @@ -229,6 +229,12 @@ class Image: @returns: None """ + def updateDisplay(): + """ + Update the display image from the floating point buffer (if it exists) + @returns: None + """ + def glLoad(): """ Load this image's data into OpenGL texture memory, if it is not already @@ -306,7 +312,7 @@ class Image: def setPixelF(x, y, (r, g, b,a )): """ Set the the colors of the current pixel in the form [r,g,b,a]. - Color values must be floats in the range 0.0 - 1.0. + For float image types, returned values can be greater then the useual [0.0, 1.0] range. Pixel coordinates are in the range from 0 to N-1. See L{getMaxXY} @type x: int @type y: int |