Browse Source

Make love.image automatically pad ImageData (and thus all images) to PO2.

Two notes:
- I don't think I ever clear the textures, so are they only transparent by coincidence?
- Maybe it's best if we surround the actually po2-ifying with ifs if we ever find a way to test if it's needed.
Bart van Strien 14 years ago
parent
commit
cf60754ef0
2 changed files with 58 additions and 57 deletions
  1. 52 57
      src/modules/image/devil/ImageData.cpp
  2. 6 0
      src/modules/image/devil/ImageData.h

+ 52 - 57
src/modules/image/devil/ImageData.cpp

@@ -33,13 +33,54 @@ namespace image
 {
 {
 namespace devil
 namespace devil
 {
 {
+	void ImageData::createPo2(int width, int height, void * data)
+	{
+		//create the image
+		ilGenImages(1, &image);
+
+		//bind it
+		ilBindImage(image);
+
+		//scale to nearest bigger po2
+		width = pow(2, ceil(log((double) width)/log(2.0)));
+		height = pow(2, ceil(log((double) height)/log(2.0)));
+
+		//create and populate the image
+		bool success = (ilTexImage(width, height, 1, bpp, IL_RGBA, IL_UNSIGNED_BYTE, data) == IL_TRUE);
+
+		if(!success) {
+			int err = ilGetError();
+			if (err != IL_NO_ERROR){
+				switch (err) {
+					case IL_ILLEGAL_OPERATION:
+						throw love::Exception("Error: Illegal operation");
+						break;
+					case IL_INVALID_PARAM:
+						throw love::Exception("Error: invalid parameters");
+						break;
+					case IL_OUT_OF_MEMORY:
+						throw love::Exception("Error: out of memory");
+						break;
+					default:
+						throw love::Exception("Error: unknown error");
+						break;
+				}
+			}
+			throw love::Exception("Could not decode image data.");
+		}
+	}
+
 	void ImageData::load(Data * data)
 	void ImageData::load(Data * data)
 	{
 	{
+		// Create a temporary image to store
+		// the decoded image in.
+		ILuint tempimage;
+
 		// Generate DevIL image.
 		// Generate DevIL image.
-		ilGenImages(1, &image);
+		ilGenImages(1, &tempimage);
 
 
 		// Bind the image.
 		// Bind the image.
-		ilBindImage(image);
+		ilBindImage(tempimage);
 
 
 		// Try to load the image.
 		// Try to load the image.
 		ILboolean success = ilLoadL(IL_TYPE_UNKNOWN, (void*)data->getData(), data->getSize());
 		ILboolean success = ilLoadL(IL_TYPE_UNKNOWN, (void*)data->getData(), data->getSize());
@@ -47,6 +88,7 @@ namespace devil
 		// Check for errors
 		// Check for errors
 		if(!success)
 		if(!success)
 		{
 		{
+			ilDeleteImages(1, &tempimage);
 			throw love::Exception("Could not decode image!");
 			throw love::Exception("Could not decode image!");
 			return;
 			return;
 		}
 		}
@@ -63,9 +105,15 @@ namespace devil
 
 
 		if(bpp != 4)
 		if(bpp != 4)
 		{
 		{
+			ilDeleteImages(1, &tempimage);
 			std::cerr << "Bits per pixel != 4" << std::endl;
 			std::cerr << "Bits per pixel != 4" << std::endl;
 			return;
 			return;
 		}
 		}
+
+		// Create a new, PO2, image based on it
+		createPo2(width, height, ilGetData());
+		// Delete the temporary image.
+		ilDeleteImages(1, &tempimage);
 	}
 	}
 
 
 	ImageData::ImageData(Data * data)
 	ImageData::ImageData(Data * data)
@@ -83,34 +131,7 @@ namespace devil
 	ImageData::ImageData(int width, int height)
 	ImageData::ImageData(int width, int height)
 		: width(width), height(height), origin(IL_ORIGIN_UPPER_LEFT), bpp(4)
 		: width(width), height(height), origin(IL_ORIGIN_UPPER_LEFT), bpp(4)
 	{
 	{
-		// Generate DevIL image.
-		ilGenImages(1, &image);
-
-		// Bind the image.
-		ilBindImage(image);
-
-		bool success = (ilTexImage(width, height, 1, bpp, IL_RGBA, IL_UNSIGNED_BYTE, 0) == IL_TRUE);
-
-		if(!success) {
-			int err = ilGetError();
-			if (err != IL_NO_ERROR){
-				switch (err) {
-					case IL_ILLEGAL_OPERATION:
-						throw love::Exception("Error: Illegal operation");
-						break;
-					case IL_INVALID_PARAM:
-						throw love::Exception("Error: invalid parameters");
-						break;
-					case IL_OUT_OF_MEMORY:
-						throw love::Exception("Error: out of memory");
-						break;
-					default:
-						throw love::Exception("Error: unknown error");
-						break;
-				}
-			}
-			throw love::Exception("Could not decode image data.");
-		}
+		createPo2(width, height);
 
 
 		// Set to black.
 		// Set to black.
 		memset((void*)ilGetData(), 0, width*height*4);
 		memset((void*)ilGetData(), 0, width*height*4);
@@ -119,33 +140,7 @@ namespace devil
 	ImageData::ImageData(int width, int height, void *data)
 	ImageData::ImageData(int width, int height, void *data)
 	: width(width), height(height), origin(IL_ORIGIN_UPPER_LEFT), bpp(4)
 	: width(width), height(height), origin(IL_ORIGIN_UPPER_LEFT), bpp(4)
 	{
 	{
-		// Generate DevIL image.
-		ilGenImages(1, &image);
-		// Bind the image.
-		ilBindImage(image);
-		// Try to load the data.
-		bool success = (ilTexImage(width, height, 1, bpp, IL_RGBA, IL_UNSIGNED_BYTE, data) == IL_TRUE);
-
-		if(!success) {
-			int err = ilGetError();
-			if (err != IL_NO_ERROR){
-				switch (err) {
-					case IL_ILLEGAL_OPERATION:
-						throw love::Exception("Error: Illegal operation");
-						break;
-					case IL_INVALID_PARAM:
-						throw love::Exception("Error: invalid parameters");
-						break;
-					case IL_OUT_OF_MEMORY:
-						throw love::Exception("Error: out of memory");
-						break;
-					default:
-						throw love::Exception("Error: unknown error");
-						break;
-				}
-			}
-			throw love::Exception("Could not decode image data.");
-		}
+		createPo2(width, height, data);
 	}
 	}
 
 
 	ImageData::~ImageData()
 	ImageData::~ImageData()

+ 6 - 0
src/modules/image/devil/ImageData.h

@@ -32,6 +32,9 @@
 // String
 // String
 #include <string.h>
 #include <string.h>
 
 
+// Math
+#include <math.h>
+
 namespace love
 namespace love
 {
 {
 namespace image
 namespace image
@@ -57,6 +60,9 @@ namespace devil
 		// DevIL image identifier.
 		// DevIL image identifier.
 		ILuint image;
 		ILuint image;
 
 
+		// Create PO2 imagedata.
+		void createPo2(int width, int height, void * data = 0);
+
 		void load(Data * data);
 		void load(Data * data);
 
 
 	public:
 	public: