Browse Source

Removed Canvas:getPixel and added optional x/y/width/height arguments to Canvas:getImageData to specify a sub-rectangle (see issue #1001.)

--HG--
branch : minor
Alex Szpakowski 10 years ago
parent
commit
8239d472d4

+ 17 - 30
src/modules/graphics/opengl/Canvas.cpp

@@ -955,13 +955,24 @@ bool Canvas::checkCreateStencil()
 	return success;
 	return success;
 }
 }
 
 
-love::image::ImageData *Canvas::getImageData(love::image::Image *image)
+love::image::ImageData *Canvas::getImageData(love::image::Image *image, int x, int y, int w, int h)
 {
 {
+	if (x < 0 || y < 0 || w <= 0 || h <= 0 || (x + w) > width || (y + h) > height)
+		throw love::Exception("Invalid ImageData rectangle dimensions.");
+
 	resolveMSAA();
 	resolveMSAA();
 
 
-	int row = 4 * width;
-	int size = row * height;
-	GLubyte *pixels  = new GLubyte[size];
+	int row = 4 * w;
+	int size = row * h;
+	GLubyte *pixels = nullptr;
+	try
+	{
+		pixels = new GLubyte[size];
+	}
+	catch (std::bad_alloc &)
+	{
+		throw love::Exception("Out of memory.");
+	}
 
 
 	// Our texture is attached to 'resolve_fbo' when we use MSAA.
 	// Our texture is attached to 'resolve_fbo' when we use MSAA.
 	if (resolve_fbo != 0 && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
 	if (resolve_fbo != 0 && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
@@ -971,7 +982,7 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
 	else
 	else
 		strategy->bindFBO(fbo);
 		strategy->bindFBO(fbo);
 
 
-	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+	glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 
 
 	if (current)
 	if (current)
 		strategy->bindFBO(current->fbo);
 		strategy->bindFBO(current->fbo);
@@ -979,31 +990,7 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
 		strategy->bindFBO(gl.getDefaultFBO());
 		strategy->bindFBO(gl.getDefaultFBO());
 
 
 	// The new ImageData now owns the pixel data, so we don't delete it here.
 	// The new ImageData now owns the pixel data, so we don't delete it here.
-	love::image::ImageData *img = image->newImageData(width, height, (void *)pixels, true);
-	return img;
-}
-
-void Canvas::getPixel(unsigned char* pixel_rgba, int x, int y)
-{
-	if (x < 0 || x >= width || y < 0 || y >= width)
-		throw love::Exception("Attempt to get out-of-range pixel (%d,%d)!", x, y);
-
-	resolveMSAA();
-
-	// Our texture is attached to 'resolve_fbo' when we use MSAA.
-	if (resolve_fbo != 0 && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
-		glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
-	else if (resolve_fbo != 0 && GLAD_EXT_framebuffer_multisample)
-		glBindFramebufferEXT(GL_READ_FRAMEBUFFER, resolve_fbo);
-	else if (current != this)
-		strategy->bindFBO(fbo);
-
-	glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel_rgba);
-
-	if (current && current != this)
-		strategy->bindFBO(current->fbo);
-	else if (!current)
-		strategy->bindFBO(gl.getDefaultFBO());
+	return image->newImageData(w, h, pixels, true);
 }
 }
 
 
 bool Canvas::resolveMSAA()
 bool Canvas::resolveMSAA()

+ 1 - 3
src/modules/graphics/opengl/Canvas.h

@@ -91,9 +91,7 @@ public:
 	 **/
 	 **/
 	bool checkCreateStencil();
 	bool checkCreateStencil();
 
 
-	love::image::ImageData *getImageData(love::image::Image *image);
-
-	void getPixel(unsigned char* pixel_rgba, int x, int y);
+	love::image::ImageData *getImageData(love::image::Image *image, int x, int y, int w, int h);
 
 
 	inline const std::vector<Canvas *> &getAttachedCanvases() const
 	inline const std::vector<Canvas *> &getAttachedCanvases() const
 	{
 	{

+ 6 - 18
src/modules/graphics/opengl/wrap_Canvas.cpp

@@ -66,28 +66,17 @@ int w_Canvas_getImageData(lua_State *L)
 {
 {
 	Canvas *canvas = luax_checkcanvas(L, 1);
 	Canvas *canvas = luax_checkcanvas(L, 1);
 	love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
 	love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
-	love::image::ImageData *img = canvas->getImageData(image);
+	int x = luaL_optint(L, 2, 0);
+	int y = luaL_optint(L, 3, 0);
+	int w = luaL_optint(L, 4, canvas->getWidth());
+	int h = luaL_optint(L, 5, canvas->getHeight());
+
+	love::image::ImageData *img = canvas->getImageData(image, x, y, w, h);
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, img);
 	luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, img);
 	img->release();
 	img->release();
 	return 1;
 	return 1;
 }
 }
 
 
-int w_Canvas_getPixel(lua_State * L)
-{
-	Canvas * canvas = luax_checkcanvas(L, 1);
-	int x = luaL_checkint(L, 2);
-	int y = luaL_checkint(L, 3);
-	unsigned char c[4];
-
-	luax_catchexcept(L, [&](){ canvas->getPixel(c, x, y); });
-
-	lua_pushnumber(L, c[0]);
-	lua_pushnumber(L, c[1]);
-	lua_pushnumber(L, c[2]);
-	lua_pushnumber(L, c[3]);
-	return 4;
-}
-
 int w_Canvas_clear(lua_State *L)
 int w_Canvas_clear(lua_State *L)
 {
 {
 	Canvas *canvas = luax_checkcanvas(L, 1);
 	Canvas *canvas = luax_checkcanvas(L, 1);
@@ -152,7 +141,6 @@ static const luaL_Reg functions[] =
 
 
 	{ "renderTo", w_Canvas_renderTo },
 	{ "renderTo", w_Canvas_renderTo },
 	{ "getImageData", w_Canvas_getImageData },
 	{ "getImageData", w_Canvas_getImageData },
-	{ "getPixel", w_Canvas_getPixel },
 	{ "clear", w_Canvas_clear },
 	{ "clear", w_Canvas_clear },
 	{ "getFormat", w_Canvas_getFormat },
 	{ "getFormat", w_Canvas_getFormat },
 	{ "getMSAA", w_Canvas_getMSAA },
 	{ "getMSAA", w_Canvas_getMSAA },