mirror of
https://github.com/love2d/love.git
synced 2026-08-13 17:10:54 +02:00
ImageData (and Images loaded from them) now support different data formats. Resolves issue #1048.
Currently exposed formats are rgba8 and rgba16 (normalized), and rgba16f and rgba32f (floating-point). Some systems, especially mobile ones, won't support every format when creating a love.graphics Image. Use love.graphics.getRawImageFormats to check for support. love.image.newImageData now takes an optional format parameter as its third argument when creating an empty sized ImageData. It defaults to rgba8. 16-bit PNGs, .hdr images, and floating-point OpenEXR images can now be loaded via love.image.newImageData and love.graphics.newImage. --HG-- branch : minor
This commit is contained in:
@@ -38,7 +38,7 @@ ImageData::~ImageData()
|
||||
|
||||
size_t ImageData::getSize() const
|
||||
{
|
||||
return size_t(getWidth()*getHeight())*sizeof(pixel);
|
||||
return size_t(getWidth() * getHeight()) * getPixelSize();
|
||||
}
|
||||
|
||||
void *ImageData::getData() const
|
||||
@@ -51,6 +51,11 @@ bool ImageData::inside(int x, int y) const
|
||||
return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
|
||||
}
|
||||
|
||||
ImageData::Format ImageData::getFormat() const
|
||||
{
|
||||
return format;
|
||||
}
|
||||
|
||||
int ImageData::getWidth() const
|
||||
{
|
||||
return width;
|
||||
@@ -61,47 +66,41 @@ int ImageData::getHeight() const
|
||||
return height;
|
||||
}
|
||||
|
||||
void ImageData::setPixel(int x, int y, pixel c)
|
||||
void ImageData::setPixel(int x, int y, const Pixel &p)
|
||||
{
|
||||
if (!inside(x, y))
|
||||
throw love::Exception("Attempt to set out-of-range pixel!");
|
||||
|
||||
size_t pixelsize = getPixelSize();
|
||||
unsigned char *pixeldata = data + ((y * width + x) * pixelsize);
|
||||
|
||||
Lock lock(mutex);
|
||||
|
||||
pixel *pixels = (pixel *) getData();
|
||||
pixels[y*width+x] = c;
|
||||
memcpy(pixeldata, &p, pixelsize);
|
||||
}
|
||||
|
||||
void ImageData::setPixelUnsafe(int x, int y, pixel c)
|
||||
{
|
||||
pixel *pixels = (pixel *) getData();
|
||||
pixels[y*width+x] = c;
|
||||
}
|
||||
|
||||
pixel ImageData::getPixel(int x, int y) const
|
||||
void ImageData::getPixel(int x, int y, Pixel &p) const
|
||||
{
|
||||
if (!inside(x, y))
|
||||
throw love::Exception("Attempt to get out-of-range pixel!");
|
||||
|
||||
size_t pixelsize = getPixelSize();
|
||||
|
||||
Lock lock(mutex);
|
||||
|
||||
const pixel *pixels = (const pixel *) getData();
|
||||
return pixels[y*width+x];
|
||||
}
|
||||
|
||||
pixel ImageData::getPixelUnsafe(int x, int y) const
|
||||
{
|
||||
const pixel *pixels = (const pixel *) getData();
|
||||
return pixels[y*width+x];
|
||||
memcpy(&p, data + ((y * width + x) * pixelsize), pixelsize);
|
||||
}
|
||||
|
||||
void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, int sh)
|
||||
{
|
||||
if (getFormat() != src->getFormat())
|
||||
throw love::Exception("ImageData formats must match!");
|
||||
|
||||
Lock lock2(src->mutex);
|
||||
Lock lock1(mutex);
|
||||
|
||||
pixel *s = (pixel *)src->getData();
|
||||
pixel *d = (pixel *)getData();
|
||||
uint8 *s = (uint8 *) src->getData();
|
||||
uint8 *d = (uint8 *) getData();
|
||||
|
||||
size_t pixelsize = getPixelSize();
|
||||
|
||||
// Check bounds; if the data ends up completely out of bounds, get out early.
|
||||
if (sx >= src->getWidth() || sx + sw < 0 || sy >= src->getHeight() || sy + sh < 0
|
||||
@@ -150,13 +149,13 @@ void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, in
|
||||
if (sw == getWidth() && getWidth() == src->getWidth()
|
||||
&& sh == getHeight() && getHeight() == src->getHeight())
|
||||
{
|
||||
memcpy(d, s, sizeof(pixel) * sw * sh);
|
||||
memcpy(d, s, pixelsize * sw * sh);
|
||||
}
|
||||
else if (sw > 0)
|
||||
{
|
||||
// Otherwise, copy each row individually.
|
||||
for (int i = 0; i < sh; i++)
|
||||
memcpy(d + dx + (i + dy) * getWidth(), s + sx + (i + sy) * src->getWidth(), sizeof(pixel) * sw);
|
||||
memcpy(d + dx + (i + dy) * getWidth(), s + (sx + (i + sy) * src->getWidth()) * pixelsize, pixelsize * sw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +164,37 @@ love::thread::Mutex *ImageData::getMutex() const
|
||||
return mutex;
|
||||
}
|
||||
|
||||
size_t ImageData::getPixelSize() const
|
||||
{
|
||||
return getPixelSize(format);
|
||||
}
|
||||
|
||||
size_t ImageData::getPixelSize(Format format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_RGBA8:
|
||||
return 4;
|
||||
case FORMAT_RGBA16:
|
||||
case FORMAT_RGBA16F:
|
||||
return 8;
|
||||
case FORMAT_RGBA32F:
|
||||
return 16;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageData::getConstant(const char *in, Format &out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
bool ImageData::getConstant(Format in, const char *&out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
bool ImageData::getConstant(const char *in, EncodedFormat &out)
|
||||
{
|
||||
return encodedFormats.find(in, out);
|
||||
@@ -175,6 +205,17 @@ bool ImageData::getConstant(EncodedFormat in, const char *&out)
|
||||
return encodedFormats.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<ImageData::Format, ImageData::FORMAT_MAX_ENUM>::Entry ImageData::formatEntries[] =
|
||||
{
|
||||
{"rgba8", FORMAT_RGBA8 },
|
||||
{"rgba16", FORMAT_RGBA16 },
|
||||
{"rgba16f", FORMAT_RGBA16F},
|
||||
{"rgba32f", FORMAT_RGBA32F},
|
||||
};
|
||||
|
||||
StringMap<ImageData::Format, ImageData::FORMAT_MAX_ENUM> ImageData::formats(ImageData::formatEntries, sizeof(ImageData::formatEntries));
|
||||
|
||||
|
||||
StringMap<ImageData::EncodedFormat, ImageData::ENCODED_MAX_ENUM>::Entry ImageData::encodedFormatEntries[] =
|
||||
{
|
||||
{"tga", ENCODED_TGA},
|
||||
|
||||
Reference in New Issue
Block a user