summaryrefslogtreecommitdiff
path: root/src/resources/image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/resources/image.cpp')
-rw-r--r--src/resources/image.cpp157
1 files changed, 104 insertions, 53 deletions
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index 2669059e..c34ba42f 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -50,7 +50,7 @@ Image::~Image()
unload();
}
-Image* Image::load(void* buffer, unsigned int bufferSize, int flags)
+Image* Image::load(void* buffer, unsigned int bufferSize)
{
// Load the raw file data from the buffer in an RWops structure
SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize);
@@ -58,29 +58,12 @@ Image* Image::load(void* buffer, unsigned int bufferSize, int flags)
// Use SDL_Image to load the raw image data and have it free the data
SDL_Surface* tmpImage = IMG_Load_RW(rw, 1);
-#ifndef USE_OPENGL
-
- SDL_Surface *image;
- if (flags & IMG_ALPHA) {
- image = SDL_DisplayFormatAlpha(tmpImage);
- }
- else {
- SDL_SetColorKey(tmpImage, SDL_SRCCOLORKEY | SDL_RLEACCEL,
- SDL_MapRGB(tmpImage->format, 255, 0, 255));
- image = SDL_DisplayFormat(tmpImage);
- }
- SDL_FreeSurface(tmpImage);
-
- // Check if the file was opened and return the appropriate value.
- if (!image) {
- logger->log("Error: Image convert failed.");
+ if (tmpImage == NULL) {
+ logger->log("Error, image load failed");
return NULL;
}
- return new Image(image);
-
-#else
-
+ // Determine 32-bit masks based on byte order
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
@@ -94,21 +77,92 @@ Image* Image::load(void* buffer, unsigned int bufferSize, int flags)
amask = 0xff000000;
#endif
+ // Convert the image to a 32 bit software surface for processing
SDL_Surface *formatImage = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, 32,
rmask, gmask, bmask, amask);
if (formatImage == NULL) {
- logger->log("Error", "Image load failed: not enough memory");
+ logger->log("Error, image load failed: not enough memory");
+ SDL_FreeSurface(tmpImage);
+ return NULL;
}
SDL_Surface *image = SDL_ConvertSurface(
tmpImage, formatImage->format, SDL_SWSURFACE);
+
SDL_FreeSurface(formatImage);
- SDL_FreeSurface(tmpImage);
- unsigned int *rawData = (unsigned int *)image->pixels;
- int width = image->w;
- int height = image->h;
+ if (image == NULL) {
+ logger->log("Error, image load failed: not enough memory");
+ return NULL;
+ }
+
+ bool hasPink = false;
+ bool hasAlpha = false;
+ int i;
+ Uint32 pink = SDL_MapRGB(image->format, 255, 0, 255);
+
+ // Figure out whether the image has pink pixels
+ for (i = 0; i < image->w * image->h; ++i)
+ {
+ if (((Uint32*)image->pixels)[i] == pink)
+ {
+ hasPink = true;
+ break;
+ }
+ }
+
+ // Figure out whether the image uses its alpha layer
+ for (i = 0; i < image->w * image->h; ++i)
+ {
+ Uint8 r, g, b, a;
+ SDL_GetRGBA(
+ ((Uint32*)image->pixels)[i],
+ image->format,
+ &r, &g, &b, &a);
+
+ if (a != 255)
+ {
+ hasAlpha = true;
+ break;
+ }
+ }
+
+ SDL_FreeSurface(image);
+
+ if (hasPink && !hasAlpha) {
+ SDL_SetColorKey(tmpImage, SDL_SRCCOLORKEY | SDL_RLEACCEL,
+ SDL_MapRGB(tmpImage->format, 255, 0, 255));
+ } else if (hasAlpha) {
+ SDL_SetAlpha(tmpImage, SDL_SRCALPHA | SDL_RLEACCEL, SDL_ALPHA_OPAQUE);
+ }
+
+#ifndef USE_OPENGL
+
+ // Set color key and alpha blending optins, and convert the surface to the
+ // current display format
+ SDL_Surface *prevImage = tmpImage;
+ if (hasAlpha) {
+ image = SDL_DisplayFormatAlpha(tmpImage);
+ }
+ else {
+ image = SDL_DisplayFormat(tmpImage);
+ }
+ SDL_FreeSurface(prevImage);
+
+ if (image == NULL) {
+ logger->log("Error: Image convert failed.");
+ return NULL;
+ }
+
+ logger->log("Alpha: %d, Magic pink: %d", hasAlpha, hasPink);
+
+ return new Image(image);
+
+#else
+
+ int width = tmpImage->w;
+ int height = tmpImage->h;
int realWidth = 1, realHeight = 1;
while (realWidth < width && realWidth < 1024) {
@@ -119,47 +173,44 @@ Image* Image::load(void* buffer, unsigned int bufferSize, int flags)
realHeight *= 2;
}
- unsigned int *realData = new unsigned int[realWidth * realHeight];
- int x, y;
+ SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE);
+ SDL_Surface *oldImage = tmpImage;
+ tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, 32,
+ rmask, gmask, bmask, amask);
- for (y = 0; y < realHeight; y++)
- {
- for (x = 0; x < realWidth; x++)
- {
- if (x < width && y < height)
- {
- if (rawData[x + y * width] == 0xffff00ff)
- {
- realData[x + y * realWidth] = 0x00000000;
- }
- else
- {
- realData[x + y * realWidth] = rawData[x + y * width];
- }
- }
- else
- {
- realData[x + y * realWidth] = 0;
- }
- }
+ if (tmpImage == NULL) {
+ logger->log("Error, image convert failed: out of memory");
+ return NULL;
}
+ SDL_BlitSurface(oldImage, NULL, tmpImage, NULL);
+ SDL_FreeSurface(oldImage);
+
GLuint texture;
glGenTextures(1, &texture);
- logger->log("Binding texture %d (%dx%d)", texture, realWidth, realHeight);
+ logger->log("Binding texture %d (%dx%d)",
+ texture, tmpImage->w, tmpImage->h);
glBindTexture(GL_TEXTURE_2D, texture);
+
+ if (SDL_MUSTLOCK(tmpImage)) {
+ SDL_LockSurface(tmpImage);
+ }
+
glTexImage2D(
GL_TEXTURE_2D, 0, 4,
- realWidth, realHeight,
+ tmpImage->w, tmpImage->h,
0, GL_RGBA, GL_UNSIGNED_BYTE,
- realData);
+ tmpImage->pixels);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- delete[] realData;
- SDL_FreeSurface(image);
+ if (SDL_MUSTLOCK(tmpImage)) {
+ SDL_UnlockSurface(tmpImage);
+ }
+
+ SDL_FreeSurface(tmpImage);
GLenum error = glGetError();
if (error)