diff options
Diffstat (limited to 'src/resources/image.cpp')
-rw-r--r-- | src/resources/image.cpp | 157 |
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) |