[Bf-python] Resubmission of patch for Draw.Image()

Campbell J Barton cbarton at metavr.com
Wed Nov 24 16:09:31 CET 2004


Hi, I like this function, its better in some ways then using glLoad()

glLoad seams to be a bit buggy, I have a scene with 130 images in it and 
whenever a do a glLoad (using my thumbnail browser) it segfaults on some 
images every time. - needs to be looked into,

But yours sidesteps the issue of having to have all textures loaded into 
openGL memory it once.

- Cam



Jonathan Merritt wrote:

> Hi Everyone,
>
> Is it time yet for me to re-submit my patch for Blender.Draw.Image()?  
> I've attached it to this email again, against the current CVS.  I'm 
> not sure whether I'm meant to wait for BCon-1 to come back up again on 
> blender.org, but I noticed a string of commits earlier today, so I 
> thought we might be rolling again. :-]  I'm really quite eager to get 
> this in so that I can start re-structuring a lot of my stuff around it.
>
> Just a quick summary once more:
>
> Blender.Draw.Image(image, x, y, zoomx=1.0, zoomy=1.0, clipx=0, 
> clipy=0, clipw=-1, cliph=-1):
>
>  Draws a Blender.Image on the screen using raster operations.
>
>  (image) - Blender.Image to draw.
>  (x, y) - Raster coordinates of the lower-left corner of the image 
> (can be negative).
>  (zoomx, zoomy) - Horizontal and vertical zoom factors.
>  (clipx, clipy, clipw, cliph) - Image space clipping rectangle.
>
> The method itself, and epydoc documentation (more extensive than the 
> quick summary above) are both provided in the patch.  btw: is this the 
> correct mailing list for these patches?  It's terribly unclear whether 
> Python extension module patches should be submitted here or to 
> bf-committers... :-/
>
> Thanks, :-)
>
> Jonathan Merritt.
>
>------------------------------------------------------------------------
>
>Index: source/blender/python/api2_2x/Draw.c
>===================================================================
>RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/Draw.c,v
>retrieving revision 1.31
>diff -u -r1.31 Draw.c
>--- source/blender/python/api2_2x/Draw.c	9 Nov 2004 14:07:25 -0000	1.31
>+++ source/blender/python/api2_2x/Draw.c	24 Nov 2004 12:58:31 -0000
>@@ -55,6 +55,7 @@
> #include "DNA_text_types.h"
> 
> #include "BKE_global.h"
>+#include "BKE_image.h"
> #include "BKE_library.h"
> #include "BKE_object.h"
> 
>@@ -67,6 +68,10 @@
> 
> #include "BPI_script.h"		/* script struct */
> 
>+#include "Image.h"              /* for accessing Blender.Image objects */
>+#include "IMB_imbuf_types.h"    /* for the IB_rect define */
>+#include "blendef.h"            /* for the CLAMP() macro */
>+
> #include "interface.h"
> #include "mydevice.h"		/*@ for all the event constants */
> 
>@@ -112,6 +117,8 @@
> static PyObject *Method_PupIntInput( PyObject * self, PyObject * args );
> static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args );
> static PyObject *Method_PupStrInput( PyObject * self, PyObject * args );
>+/* next by Jonathan Merritt (lancelet): */
>+static PyObject *Method_Image( PyObject * self, PyObject * args);
> 
> static uiBlock *Get_uiBlock( void );
> static void py_slider_update( void *butv, void *data2_unused );
>@@ -267,6 +274,14 @@
> the float value show.\n\
> Return the user input value or None on user exit";
> 
>+static char Method_Image_doc[] =
>+	"(image, x, y, zoomx = 1.0, zoomy = 1.0, [clipx, clipy, clipw, cliph])) \n\
>+    - Draw an image.\n\
>+(image) - Blender.Image to draw.\n\
>+(x, y) - floats specifying the location of the image.\n\
>+(zoomx, zoomy) - float zoom factors in horizontal and vertical directions.\n\
>+(clipx, clipy, clipw, cliph) - integers specifying a clipping rectangle within the original image.";
>+
> static char Method_PupStrInput_doc[] =
> 	"(text, default, max = 20) - Display a float pop-up input.\n\
> (text) - text string to display on the button;\n\
>@@ -304,6 +319,7 @@
> 	MethodDef( PupIntInput ),
> 	MethodDef( PupFloatInput ),
> 	MethodDef( PupStrInput ),
>+	MethodDef( Image ),
> 	MethodDef( Exit ),
> 	MethodDef( Redraw ),
> 	MethodDef( Draw ),
>@@ -1196,6 +1212,107 @@
> 				      "couldn't create a PyString" );
> }
> 
>+/*****************************************************************************
>+ * Function:            Method_Image                                         *
>+ * Python equivalent:   Blender.Draw.Image                                   *
>+ *                                                                           *
>+ * @author Jonathan Merritt <j.merritt at pgrad.unimelb.edu.au>                 *
>+ ****************************************************************************/
>+static PyObject *Method_Image( PyObject * self, PyObject * args )
>+{
>+	PyObject *pyObjImage;
>+	BPy_Image *py_img;
>+	Image *image;
>+	float originX, originY;
>+	float zoomX = 1.0, zoomY = 1.0;
>+	int clipX = 0, clipY = 0, clipW = -1, clipH = -1;
>+	GLfloat scissorBox[4];
>+
>+	/* parse the arguments passed-in from Python */
>+	if( !PyArg_ParseTuple( args, "Off|ffiiii", &pyObjImage, 
>+		&originX, &originY, &zoomX, &zoomY, 
>+		&clipX, &clipY, &clipW, &clipH ) )
>+		return EXPP_ReturnPyObjError( PyExc_TypeError,
>+			"expected a Blender.Image and 2 floats, and " \
>+			"optionally 2 floats and 4 ints as arguments" );
>+	/* check that the first PyObject is actually a Blender.Image */
>+	if( !Image_CheckPyObject( pyObjImage ) )
>+		return EXPP_ReturnPyObjError( PyExc_TypeError,
>+			"expected a Blender.Image and 2 floats, and " \
>+			"optionally 2 floats and 4 ints as arguments" );
>+	/* check that the zoom factors are valid */
>+	if( ( zoomX <= 0.0 ) || ( zoomY <= 0.0 ) )
>+		return EXPP_ReturnPyObjError( PyExc_TypeError,
>+			"invalid zoom factors - they must be >= 0.0" );
>+
>+	/* fetch a C Image pointer from the passed-in Python object */
>+	py_img = ( BPy_Image * ) pyObjImage;
>+	image = py_img->image;
>+
>+	/* load the image data if necessary */
>+	if( !image->ibuf )      /* if no image data is available ... */
>+		load_image( image, IB_rect, "", 0 );    /* ... load it */
>+	if( !image->ibuf )      /* if failed to load the image */
>+		return EXPP_ReturnPyObjError( PyExc_RuntimeError,
>+			"couldn't load image data in Blender" );
>+
>+	/* set up a valid clipping rectangle.  if no clip rectangle was
>+	 * given, this results in inclusion of the entire image.  otherwise,
>+	 * the clipping is just checked against the bounds of the image.
>+	 * if clipW or clipH are less than zero then they include as much of
>+	 * the image as they can. */
>+	CLAMP( clipX, 0, image->ibuf->x );
>+	CLAMP( clipY, 0, image->ibuf->y );
>+	if( ( clipW < 0 ) || ( clipW > ( image->ibuf->x - clipW ) ) )
>+		clipW = image->ibuf->x - clipX;
>+	if( ( clipH < 0 ) || ( clipH > ( image->ibuf->y - clipH ) ) )
>+		clipH = image->ibuf->y - clipY;
>+
>+	/* -- we are "Go" to Draw! -- */
>+
>+	/* set the raster position.
>+	 *
>+	 * If the raster position is negative, then using glRasterPos2i() 
>+	 * directly would cause it to be clipped.  Instead, we first establish 
>+	 * a valid raster position within the clipping rectangle of the 
>+	 * window and then use glBitmap() with a NULL image pointer to offset 
>+	 * it to the true position we require.  To pick an initial valid 
>+	 * raster position within the viewport, we query the clipping rectangle
>+	 * and use its lower-left pixel.
>+	 *
>+	 * This particular technique is documented in the glRasterPos() man
>+	 * page, although I haven't seen it used elsewhere in Blender.
>+	 */
>+	glGetFloatv( GL_SCISSOR_BOX, scissorBox );
>+	glRasterPos2i( scissorBox[0], scissorBox[1] );
>+	glBitmap( 0, 0, 0.0, 0.0, 
>+		originX-scissorBox[0], originY-scissorBox[1], NULL );
>+
>+	/* set the zoom */
>+	glPixelZoom( zoomX, zoomY );
>+
>+	/* set the width of the image (ROW_LENGTH), and the offset to the
>+	 * clip origin within the image in x (SKIP_PIXELS) and 
>+	 * y (SKIP_ROWS) */
>+	glPixelStorei( GL_UNPACK_ROW_LENGTH,  image->ibuf->x );
>+	glPixelStorei( GL_UNPACK_SKIP_PIXELS, clipX );
>+	glPixelStorei( GL_UNPACK_SKIP_ROWS,   clipY );
>+
>+	/* draw the image */
>+	glDrawPixels( clipW, clipH, GL_RGBA, GL_UNSIGNED_BYTE, 
>+		image->ibuf->rect );
>+
>+	/* restore the defaults for some parameters (we could also use a
>+	 * glPushClientAttrib() and glPopClientAttrib() pair). */
>+	glPixelZoom( 1.0, 1.0 );
>+	glPixelStorei( GL_UNPACK_SKIP_ROWS,   0 );
>+	glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
>+	glPixelStorei( GL_UNPACK_ROW_LENGTH,  0 );
>+
>+	Py_INCREF( Py_None );
>+	return Py_None;
>+
>+}
> 
> PyObject *Draw_Init( void )
> {
>Index: source/blender/python/api2_2x/doc/Draw.py
>===================================================================
>RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/doc/Draw.py,v
>retrieving revision 1.13
>diff -u -r1.13 Draw.py
>--- source/blender/python/api2_2x/doc/Draw.py	16 Jul 2004 03:08:43 -0000	1.13
>+++ source/blender/python/api2_2x/doc/Draw.py	24 Nov 2004 12:58:34 -0000
>@@ -594,6 +594,67 @@
>   @return: The width of I{string} drawn with the chosen I{fontsize}.
>   """
> 
>+def Image(image, x, y, zoomx=1.0, zoomy=1.0, clipx=0, clipy=0, clipw=-1, cliph=-1):
>+  """
>+  Draw an image on the screen.
>+
>+  The image is drawn at the location specified by the coordinates (x,y).  A
>+  pair of optional zoom factors (in horizontal and vertical directions) can
>+  be applied to the image as it is drawn, and an additional clipping rectangle
>+  can be applied to extract a particular sub-region of the image to draw.
>+
>+  Note that the clipping rectangle is given in image space coordinates.  In
>+  image space, the origin is located at the bottom left, with x coordinates 
>+  increasing to the right and y coordinates increasing upwards.  No matter 
>+  where the clipping rectangle is placed in image space, the lower-left pixel 
>+  drawn on the screen is always placed at the coordinates (x,y).  The
>+  clipping rectangle is itself clipped to the dimensions of the image.  If
>+  either the width or the height of the clipping rectangle are negative then
>+  the corresponding dimension (width or height) is set to include as much of 
>+  the image as possible.
>+
>+  Example::
>+   import Blender
>+   from Blender import BGL, Image, Draw
>+
>+   myimage = Image.Load('myimage.png')
>+
>+   def gui():
>+        Draw.Image(myimage, 50, 50)
>+   def event(evt, val):
>+        if evt == Draw.ESCKEY:
>+              Draw.Exit()
>+
>+   Draw.Register(gui, event, None)
>+
>+  @type image: Blender.Image
>+  @param image: The image to draw.
>+  @type x: int
>+  @param x: The lower left x (horizontal) position of the origin of the image.
>+  @type y: int
>+  @param y: The lower left y (vertical) position of the origin of the image.
>+  @type zoomx: float
>+  @param zoomx: The x (horizontal) zoom factor to use when drawing the image.
>+  @type zoomy: float
>+  @param zoomy: The y (vertical) zoom factor to use when drawing the image.
>+  @type clipx: int
>+  @param clipx: The lower left x (horizontal) origin of the clipping rectangle
>+                within the image.  A value of 0 indicates the left of the
>+                image.
>+  @type clipy: int
>+  @param clipy: The lower left y (vertical) origin of the clipping rectangle
>+                within the image.  A value of 0 indicates the bottom of the
>+                image.
>+  @type clipw: int
>+  @param clipw: The width of the clipping rectangle within the image. If this
>+                value is negative then the clipping rectangle includes as much
>+                of the image as possible in the x (horizontal) direction.
>+  @type cliph: int
>+  @param cliph: The height of the clipping rectangle within the image. If this
>+                value is negative then the clipping rectangle includes as much
>+                of the image as possible in the y (vertical) direction.
>+  """
>+
> class Button:
>   """
>   The Button object
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>Bf-python mailing list
>Bf-python at projects.blender.org
>http://projects.blender.org/mailman/listinfo/bf-python
>  
>


-- 
Campbell J Barton

133 Hope Street
Geelong West, Victoria 3218 Australia

URL:    http://www.metavr.com
e-mail: cbarton at metavr.com
phone: AU (03) 5229 0241




More information about the Bf-python mailing list