|
@@ -29,6 +29,10 @@
|
|
|
#include <common/math.h>
|
|
|
#include <filesystem/File.h>
|
|
|
|
|
|
+using love::thread::Lock;
|
|
|
+
|
|
|
+static Mutex devilMutex;
|
|
|
+
|
|
|
namespace love
|
|
|
{
|
|
|
namespace image
|
|
@@ -37,6 +41,9 @@ namespace devil
|
|
|
{
|
|
|
void ImageData::create(int width, int height, void * data)
|
|
|
{
|
|
|
+ Lock lock(devilMutex); //automatically lock and unlock
|
|
|
+ ILuint image;
|
|
|
+
|
|
|
//create the image
|
|
|
ilGenImages(1, &image);
|
|
|
|
|
@@ -66,10 +73,24 @@ namespace devil
|
|
|
}
|
|
|
throw love::Exception("Could not decode image data.");
|
|
|
}
|
|
|
+
|
|
|
+ try {
|
|
|
+ this->data = new unsigned char[width*height*bpp];
|
|
|
+ } catch(std::bad_alloc) {
|
|
|
+ ilDeleteImages(1, &image);
|
|
|
+ throw love::Exception("Out of memory");
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(this->data, ilGetData(), width*height*bpp);
|
|
|
+
|
|
|
+ ilDeleteImages(1, &image);
|
|
|
}
|
|
|
|
|
|
void ImageData::load(Data * data)
|
|
|
{
|
|
|
+ Lock lock(devilMutex);
|
|
|
+ ILuint image;
|
|
|
+
|
|
|
// Generate DevIL image.
|
|
|
ilGenImages(1, &image);
|
|
|
|
|
@@ -101,6 +122,20 @@ namespace devil
|
|
|
std::cerr << "Bits per pixel != 4" << std::endl;
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ this->data = new unsigned char[width*height*bpp];
|
|
|
+ }
|
|
|
+ catch(std::bad_alloc)
|
|
|
+ {
|
|
|
+ ilDeleteImages(1, &image);
|
|
|
+ throw love::Exception("Out of memory");
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(this->data, ilGetData(), width*height*bpp);
|
|
|
+
|
|
|
+ ilDeleteImages(1, &image);
|
|
|
}
|
|
|
|
|
|
ImageData::ImageData(Data * data)
|
|
@@ -121,7 +156,7 @@ namespace devil
|
|
|
create(width, height);
|
|
|
|
|
|
// Set to black.
|
|
|
- memset((void*)ilGetData(), 0, width*height*4);
|
|
|
+ memset(data, 0, width*height*4);
|
|
|
}
|
|
|
|
|
|
ImageData::ImageData(int width, int height, void *data)
|
|
@@ -132,7 +167,7 @@ namespace devil
|
|
|
|
|
|
ImageData::~ImageData()
|
|
|
{
|
|
|
- ilDeleteImages(1, &image);
|
|
|
+ delete[] data;
|
|
|
}
|
|
|
|
|
|
int ImageData::getWidth() const
|
|
@@ -147,8 +182,7 @@ namespace devil
|
|
|
|
|
|
void * ImageData::getData() const
|
|
|
{
|
|
|
- ilBindImage(image);
|
|
|
- return ilGetData();
|
|
|
+ return data;
|
|
|
}
|
|
|
|
|
|
int ImageData::getSize() const
|
|
@@ -158,6 +192,7 @@ namespace devil
|
|
|
|
|
|
void ImageData::setPixel(int x, int y, pixel c)
|
|
|
{
|
|
|
+ Lock lock(mutex);
|
|
|
//int tx = x > width-1 ? width-1 : x;
|
|
|
//int ty = y > height-1 ? height-1 : y; // not using these seems to not break anything
|
|
|
if (x > width-1 || y > height-1 || x < 0 || y < 0) throw love::Exception("Attempt to set out-of-range pixel!");
|
|
@@ -165,8 +200,9 @@ namespace devil
|
|
|
pixels[y*width+x] = c;
|
|
|
}
|
|
|
|
|
|
- pixel ImageData::getPixel(int x, int y) const
|
|
|
+ pixel ImageData::getPixel(int x, int y)
|
|
|
{
|
|
|
+ Lock lock(mutex);
|
|
|
//int tx = x > width-1 ? width-1 : x;
|
|
|
//int ty = y > height-1 ? height-1 : y; // not using these seems to not break anything
|
|
|
if (x > width-1 || y > height-1 || x < 0 || y < 0) throw love::Exception("Attempt to get out-of-range pixel!");
|
|
@@ -175,7 +211,41 @@ namespace devil
|
|
|
}
|
|
|
|
|
|
void ImageData::encode(love::filesystem::File * f, ImageData::Format format) {
|
|
|
- ilBindImage(image);
|
|
|
+ Lock lock(devilMutex);
|
|
|
+ Lock lock2(mutex);
|
|
|
+
|
|
|
+ ILuint tempimage;
|
|
|
+ ilGenImages(1, &tempimage);
|
|
|
+ ilBindImage(tempimage);
|
|
|
+
|
|
|
+ while(ilGetError() != IL_NO_ERROR);
|
|
|
+
|
|
|
+ bool success = ilTexImage(width, height, 1, bpp, IL_RGBA, IL_UNSIGNED_BYTE, this->data) == IL_TRUE;
|
|
|
+
|
|
|
+ ILenum err = ilGetError();
|
|
|
+ while(ilGetError() != IL_NO_ERROR);
|
|
|
+
|
|
|
+ if(!success) {
|
|
|
+ ilDeleteImages(1, &tempimage);
|
|
|
+
|
|
|
+ if(err != IL_NO_ERROR) {
|
|
|
+ switch (err) {
|
|
|
+ case IL_ILLEGAL_OPERATION:
|
|
|
+ throw love::Exception("Illegal operation");
|
|
|
+ case IL_INVALID_PARAM:
|
|
|
+ throw love::Exception("Invalid parameters");
|
|
|
+ case IL_OUT_OF_MEMORY:
|
|
|
+ throw love::Exception("Out of memory");
|
|
|
+ default:
|
|
|
+ throw love::Exception("Unknown error (%d)", (int) err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw love::Exception("Could not create image for the encoding!");
|
|
|
+ }
|
|
|
+
|
|
|
+ ilRegisterOrigin(IL_ORIGIN_UPPER_LEFT);
|
|
|
+
|
|
|
ILuint ilFormat;
|
|
|
switch (format) {
|
|
|
case ImageData::FORMAT_BMP:
|
|
@@ -195,13 +265,29 @@ namespace devil
|
|
|
ilFormat = IL_PNG;
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
ILuint size = ilSaveL(ilFormat, NULL, 0);
|
|
|
- ILubyte * data = new ILubyte[size];
|
|
|
- ilSaveL(ilFormat, data, size);
|
|
|
+ if(!size) {
|
|
|
+ ilDeleteImages(1, &tempimage);
|
|
|
+ throw love::Exception("Could not encode image!");
|
|
|
+ }
|
|
|
+
|
|
|
+ ILubyte * encoded_data;
|
|
|
+ try {
|
|
|
+ encoded_data = new ILubyte[size];
|
|
|
+ } catch(std::bad_alloc) {
|
|
|
+ ilDeleteImages(1, &tempimage);
|
|
|
+ throw love::Exception("Out of memory");
|
|
|
+ }
|
|
|
+
|
|
|
+ ilSaveL(ilFormat, encoded_data, size);
|
|
|
+ ilDeleteImages(1, &tempimage);
|
|
|
+
|
|
|
f->open(love::filesystem::File::WRITE);
|
|
|
- f->write(data, size);
|
|
|
+ f->write(encoded_data, size);
|
|
|
f->close();
|
|
|
- delete[] data;
|
|
|
+
|
|
|
+ delete[] encoded_data;
|
|
|
}
|
|
|
|
|
|
} // devil
|