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.
This commit is contained in:
Alex Szpakowski
2022-04-18 10:46:02 -03:00
parent 8d3730361b
commit e61a664a8b
5 changed files with 42 additions and 53 deletions
+12
View File
@@ -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
View File
@@ -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
View File
@@ -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)
{ throw love::Exception("No suitable image encoder for the %s pixel format.", getPixelFormatName(format));
const char *fname = "unknown";
love::getConstant(format, fname);
throw love::Exception("No suitable image encoder for %s format.", fname);
}
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) return isPixelFormatColor(format) && !isPixelFormatCompressed(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;
} }
ImageData::PixelSetFunction ImageData::getPixelSetFunction(PixelFormat format) ImageData::PixelSetFunction ImageData::getPixelSetFunction(PixelFormat format)
-1
View File
@@ -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
View File
@@ -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()), pointer = conv == nil and nil or ffi.cast(conv.pointer, imagedata:getFFIPointer()),
tolua = conv.tolua, tolua = conv == nil and nil or conv.tolua,
fromlua = conv.fromlua, 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)