Browse Source

ImageData: limited support for integer pixel formats.

For now this doesn't support conversions (get/set/mapPixel, etc). Just the ability for ImageData to contain integer pixel contents, for example via Canvas:newImageData.
Alex Szpakowski 3 years ago
parent
commit
e61a664a8b

+ 12 - 0
src/common/pixelformat.cpp

@@ -240,11 +240,23 @@ const PixelFormatInfo &getPixelFormatInfo(PixelFormat format)
 	return formatInfo[format];
 	return formatInfo[format];
 }
 }
 
 
+const char *getPixelFormatName(PixelFormat format)
+{
+	const char *name = "unknown";
+	getConstant(format, name);
+	return name;
+}
+
 bool isPixelFormatCompressed(PixelFormat format)
 bool isPixelFormatCompressed(PixelFormat format)
 {
 {
 	return formatInfo[format].compressed;
 	return formatInfo[format].compressed;
 }
 }
 
 
+bool isPixelFormatColor(PixelFormat format)
+{
+	return formatInfo[format].color;
+}
+
 bool isPixelFormatDepthStencil(PixelFormat format)
 bool isPixelFormatDepthStencil(PixelFormat format)
 {
 {
 	const PixelFormatInfo &info = formatInfo[format];
 	const PixelFormatInfo &info = formatInfo[format];

+ 10 - 0
src/common/pixelformat.h

@@ -157,11 +157,21 @@ bool getConstant(const char *in, PixelFormat &out);
 
 
 const PixelFormatInfo &getPixelFormatInfo(PixelFormat format);
 const PixelFormatInfo &getPixelFormatInfo(PixelFormat format);
 
 
+/**
+ * Gets the name of the specified pixel format.
+ **/
+const char *getPixelFormatName(PixelFormat format);
+
 /**
 /**
  * Gets whether the specified pixel format is a compressed type.
  * Gets whether the specified pixel format is a compressed type.
  **/
  **/
 bool isPixelFormatCompressed(PixelFormat format);
 bool isPixelFormatCompressed(PixelFormat format);
 
 
+/**
+ * Gets whether the specified pixel format is a color type.
+ **/
+bool isPixelFormatColor(PixelFormat format);
+
 /**
 /**
  * Gets whether the specified pixel format is a depth or stencil type.
  * Gets whether the specified pixel format is a depth or stencil type.
  **/
  **/

+ 11 - 49
src/modules/image/ImageData.cpp

@@ -43,7 +43,7 @@ ImageData::ImageData(int width, int height, PixelFormat format)
 	: ImageDataBase(format, width, height)
 	: ImageDataBase(format, width, height)
 {
 {
 	if (!validPixelFormat(format))
 	if (!validPixelFormat(format))
-		throw love::Exception("Unsupported pixel format for ImageData");
+		throw love::Exception("ImageData does not support the %s pixel format.", getPixelFormatName(format));
 
 
 	create(width, height, format);
 	create(width, height, format);
 
 
@@ -55,7 +55,7 @@ ImageData::ImageData(int width, int height, PixelFormat format, void *data, bool
 	: ImageDataBase(format, width, height)
 	: ImageDataBase(format, width, height)
 {
 {
 	if (!validPixelFormat(format))
 	if (!validPixelFormat(format))
-		throw love::Exception("Unsupported pixel format for ImageData");
+		throw love::Exception("ImageData does not support the %s pixel format.", getPixelFormatName(format));
 
 
 	if (own)
 	if (own)
 		this->data = (unsigned char *) data;
 		this->data = (unsigned char *) data;
@@ -196,11 +196,7 @@ love::filesystem::FileData *ImageData::encode(FormatHandler::EncodedFormat encod
 	}
 	}
 
 
 	if (encoder == nullptr || encodedimage.data == nullptr)
 	if (encoder == nullptr || encodedimage.data == nullptr)
-	{
-		const char *fname = "unknown";
-		love::getConstant(format, fname);
-		throw love::Exception("No suitable image encoder for %s format.", fname);
-	}
+		throw love::Exception("No suitable image encoder for the %s pixel format.", getPixelFormatName(format));
 
 
 	love::filesystem::FileData *filedata = nullptr;
 	love::filesystem::FileData *filedata = nullptr;
 
 
@@ -540,7 +536,7 @@ void ImageData::setPixel(int x, int y, const Colorf &c)
 	Pixel *p = (Pixel *) (data + ((y * width + x) * pixelsize));
 	Pixel *p = (Pixel *) (data + ((y * width + x) * pixelsize));
 
 
 	if (pixelSetFunction == nullptr)
 	if (pixelSetFunction == nullptr)
-		throw love::Exception("Unhandled pixel format %d in ImageData::setPixel", format);
+		throw love::Exception("ImageData:setPixel does not currently support the %s pixel format.", getPixelFormatName(format));
 
 
 	Lock lock(mutex);
 	Lock lock(mutex);
 
 
@@ -556,7 +552,7 @@ void ImageData::getPixel(int x, int y, Colorf &c) const
 	const Pixel *p = (const Pixel *) (data + ((y * width + x) * pixelsize));
 	const Pixel *p = (const Pixel *) (data + ((y * width + x) * pixelsize));
 
 
 	if (pixelGetFunction == nullptr)
 	if (pixelGetFunction == nullptr)
-		throw love::Exception("Unhandled pixel format %d in ImageData::setPixel", format);
+		throw love::Exception("ImageData:getPixel does not currently support the %s pixel format.", getPixelFormatName(format));
 
 
 	Lock lock(mutex);
 	Lock lock(mutex);
 
 
@@ -759,7 +755,7 @@ void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, in
 			else if (srcformat == PIXELFORMAT_RGBA32_FLOAT && dstformat == PIXELFORMAT_RGBA16_FLOAT)
 			else if (srcformat == PIXELFORMAT_RGBA32_FLOAT && dstformat == PIXELFORMAT_RGBA16_FLOAT)
 				pasteRGBA32FtoRGBA16F(rowsrc, rowdst, sw);
 				pasteRGBA32FtoRGBA16F(rowsrc, rowdst, sw);
 
 
-			else
+			else if (getfunction != nullptr && setfunction != nullptr)
 			{
 			{
 				// Slow path: convert src -> Colorf -> dst.
 				// Slow path: convert src -> Colorf -> dst.
 				Colorf c;
 				Colorf c;
@@ -771,6 +767,10 @@ void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, in
 					setfunction(c, dstp);
 					setfunction(c, dstp);
 				}
 				}
 			}
 			}
+			else if (getfunction == nullptr)
+				throw love::Exception("ImageData:paste does not currently support converting from the %s pixel format.", getPixelFormatName(srcformat));
+			else
+				throw love::Exception("ImageData:paste does not currently support converting to the %s pixel format.", getPixelFormatName(dstformat));
 		}
 		}
 	}
 	}
 }
 }
@@ -787,45 +787,7 @@ size_t ImageData::getPixelSize() const
 
 
 bool ImageData::validPixelFormat(PixelFormat format)
 bool ImageData::validPixelFormat(PixelFormat format)
 {
 {
-	switch (format)
-	{
-	case PIXELFORMAT_R8_UNORM:
-	case PIXELFORMAT_RG8_UNORM:
-	case PIXELFORMAT_RGBA8_UNORM:
-	case PIXELFORMAT_R16_UNORM:
-	case PIXELFORMAT_RG16_UNORM:
-	case PIXELFORMAT_RGBA16_UNORM:
-	case PIXELFORMAT_R16_FLOAT:
-	case PIXELFORMAT_RG16_FLOAT:
-	case PIXELFORMAT_RGBA16_FLOAT:
-	case PIXELFORMAT_R32_FLOAT:
-	case PIXELFORMAT_RG32_FLOAT:
-	case PIXELFORMAT_RGBA32_FLOAT:
-	case PIXELFORMAT_RGBA4_UNORM:
-	case PIXELFORMAT_RGB5A1_UNORM:
-	case PIXELFORMAT_RGB565_UNORM:
-	case PIXELFORMAT_RGB10A2_UNORM:
-	case PIXELFORMAT_RG11B10_FLOAT:
-		return true;
-	default:
-		return false;
-	}
-}
-
-bool ImageData::canPaste(PixelFormat src, PixelFormat dst)
-{
-	if (src == dst)
-		return true;
-
-	if (!(src == PIXELFORMAT_RGBA8_UNORM || src == PIXELFORMAT_RGBA16_UNORM
-		|| src == PIXELFORMAT_RGBA16_FLOAT || src == PIXELFORMAT_RGBA32_FLOAT))
-		return false;
-
-	if (!(dst == PIXELFORMAT_RGBA8_UNORM || dst == PIXELFORMAT_RGBA16_UNORM
-		|| dst == PIXELFORMAT_RGBA16_FLOAT || dst == PIXELFORMAT_RGBA32_FLOAT))
-		return false;
-
-	return true;
+	return isPixelFormatColor(format) && !isPixelFormatCompressed(format);
 }
 }
 
 
 ImageData::PixelSetFunction ImageData::getPixelSetFunction(PixelFormat format)
 ImageData::PixelSetFunction ImageData::getPixelSetFunction(PixelFormat format)

+ 0 - 1
src/modules/image/ImageData.h

@@ -124,7 +124,6 @@ public:
 	PixelGetFunction getPixelGetFunction() const { return pixelGetFunction; }
 	PixelGetFunction getPixelGetFunction() const { return pixelGetFunction; }
 
 
 	static bool validPixelFormat(PixelFormat format);
 	static bool validPixelFormat(PixelFormat format);
-	static bool canPaste(PixelFormat src, PixelFormat dst);
 
 
 	static PixelSetFunction getPixelSetFunction(PixelFormat format);
 	static PixelSetFunction getPixelSetFunction(PixelFormat format);
 	static PixelGetFunction getPixelGetFunction(PixelFormat format);
 	static PixelGetFunction getPixelGetFunction(PixelFormat format);

+ 9 - 3
src/modules/image/wrap_ImageData.lua

@@ -368,9 +368,9 @@ local objectcache = setmetatable({}, {
 			width = width,
 			width = width,
 			height = height,
 			height = height,
 			format = format,
 			format = format,
-			pointer = ffi.cast(conv.pointer, imagedata:getFFIPointer()),
-			tolua = conv.tolua,
-			fromlua = conv.fromlua,
+			pointer = conv == nil and nil or ffi.cast(conv.pointer, imagedata:getFFIPointer()),
+			tolua = conv == nil and nil or conv.tolua,
+			fromlua = conv == nil and nil or conv.fromlua,
 		}
 		}
 
 
 		self[imagedata] = p
 		self[imagedata] = p
@@ -395,6 +395,8 @@ function ImageData:_mapPixelUnsafe(func, ix, iy, iw, ih)
 	local p = objectcache[self]
 	local p = objectcache[self]
 	local idw, idh = p.width, p.height
 	local idw, idh = p.width, p.height
 
 
+	if p.pointer == nil then error("ImageData:mapPixel does not currently support the "..p.format.." pixel format.", 2) end
+
 	ix = floor(ix)
 	ix = floor(ix)
 	iy = floor(iy)
 	iy = floor(iy)
 	iw = floor(iw)
 	iw = floor(iw)
@@ -423,6 +425,8 @@ function ImageData:getPixel(x, y)
 	local p = objectcache[self]
 	local p = objectcache[self]
 	if not inside(x, y, p.width, p.height) then error("Attempt to get out-of-range pixel!", 2) end
 	if not inside(x, y, p.width, p.height) then error("Attempt to get out-of-range pixel!", 2) end
 
 
+	if p.pointer == nil then error("ImageData:getPixel does not currently support the "..p.format.." pixel format.", 2) end
+
 	ffifuncs.lockMutex(self)
 	ffifuncs.lockMutex(self)
 	local pixel = p.pointer[y * p.width + x]
 	local pixel = p.pointer[y * p.width + x]
 	local r, g, b, a = p.tolua(pixel)
 	local r, g, b, a = p.tolua(pixel)
@@ -451,6 +455,8 @@ function ImageData:setPixel(x, y, r, g, b, a)
 	local p = objectcache[self]
 	local p = objectcache[self]
 	if not inside(x, y, p.width, p.height) then error("Attempt to set out-of-range pixel!", 2) end
 	if not inside(x, y, p.width, p.height) then error("Attempt to set out-of-range pixel!", 2) end
 
 
+	if p.pointer == nil then error("ImageData:setPixel does not currently support the "..p.format.." pixel format.", 2) end
+
 	ffifuncs.lockMutex(self)
 	ffifuncs.lockMutex(self)
 	p.fromlua(p.pointer[y * p.width + x], r, g, b, a)
 	p.fromlua(p.pointer[y * p.width + x], r, g, b, a)
 	ffifuncs.unlockMutex(self)
 	ffifuncs.unlockMutex(self)