mirror of
https://github.com/love2d/love.git
synced 2026-08-20 12:40:20 +02:00
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:
@@ -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];
|
||||||
|
|||||||
@@ -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.
|
||||||
**/
|
**/
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user