diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2005-06-21 18:41:45 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2005-06-21 18:41:45 +0000 |
commit | c2a830c71ef0e271e48ef57a80ee5b00a977a4de (patch) | |
tree | 9c8f13688ddbf159a34640ad4cf4fdda3eb20ecf /src/resources | |
parent | c392a1aa234b304b634c4ace6375ad96397a30b9 (diff) | |
download | mana-c2a830c71ef0e271e48ef57a80ee5b00a977a4de.tar.gz mana-c2a830c71ef0e271e48ef57a80ee5b00a977a4de.tar.bz2 mana-c2a830c71ef0e271e48ef57a80ee5b00a977a4de.tar.xz mana-c2a830c71ef0e271e48ef57a80ee5b00a977a4de.zip |
Image loader now automatically determines whether to use masked drawing or
an alpha layer.
Diffstat (limited to 'src/resources')
-rw-r--r-- | src/resources/image.cpp | 157 | ||||
-rw-r--r-- | src/resources/image.h | 9 | ||||
-rw-r--r-- | src/resources/mapreader.cpp | 2 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 12 | ||||
-rw-r--r-- | src/resources/resourcemanager.h | 6 |
5 files changed, 114 insertions, 72 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) diff --git a/src/resources/image.h b/src/resources/image.h index ebc2c971..14aa4550 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -31,10 +31,6 @@ #endif #include <string> -// This flag causes image alpha channel to be preserved, otherwise masking is -// used. -#define IMG_ALPHA 1 - // Forward declarations class SubImage; @@ -56,14 +52,11 @@ class Image : public Resource * * @param buffer The memory buffer containing the image data. * @param bufferSize The size of the memory buffer in bytes. - * @param flags These flags allow controlling the way the image is - * loaded. Currently only IMG_ALPHA is supported, which - * causes alpha layer to be preserved. * * @return <code>NULL</code> if the an error occurred, a valid pointer * otherwise. */ - static Image *load(void* buffer, unsigned int bufferSize, int flags); + static Image *load(void* buffer, unsigned int bufferSize); /** * Frees the resources created by SDL. diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index b62e6029..abd269d0 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -265,7 +265,7 @@ Tileset* MapReader::readTileset( sourceStr.erase(0, 3); // Remove "../" ResourceManager *resman = ResourceManager::getInstance(); - Image* tilebmp = resman->getImage(sourceStr, IMG_ALPHA); + Image* tilebmp = resman->getImage(sourceStr); if (tilebmp) { diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 0abc10eb..1e2f4f31 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -73,7 +73,7 @@ ResourceManager::~ResourceManager() } Resource* ResourceManager::get(const E_RESOURCE_TYPE &type, - const std::string &idPath, int flags) + const std::string &idPath) { // Check if the id exists, and return the value if it does. std::map<std::string, ResourceEntry>::iterator resIter = @@ -122,7 +122,7 @@ Resource* ResourceManager::get(const E_RESOURCE_TYPE &type, if (buffer != NULL) { // Let the image class load it - resource = Image::load(buffer, fileSize, flags); + resource = Image::load(buffer, fileSize); // Cleanup free(buffer); @@ -177,19 +177,19 @@ Resource* ResourceManager::get(const E_RESOURCE_TYPE &type, return resource; } -Image *ResourceManager::getImage(const std::string &idPath, int flags) +Image *ResourceManager::getImage(const std::string &idPath) { - return (Image*)get(IMAGE, idPath, flags); + return (Image*)get(IMAGE, idPath); } Music *ResourceManager::getMusic(const std::string &idPath) { - return (Music*)get(MUSIC, idPath, 0); + return (Music*)get(MUSIC, idPath); } SoundEffect *ResourceManager::getSoundEffect(const std::string &idPath) { - return (SoundEffect*)get(SOUND_EFFECT, idPath, 0); + return (SoundEffect*)get(SOUND_EFFECT, idPath); } ResourceManager* ResourceManager::getInstance() diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index 3c72eb43..2204d455 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -78,20 +78,18 @@ class ResourceManager * * @param type The type of resource to load. * @param idPath The resource identifier path. - * @param flags Flags to control the loading of certain resources. * @return A valid resource or <code>NULL</code> if the resource could * not be loaded. */ Resource *get( const E_RESOURCE_TYPE &type, - const std::string &idPath, - int flags = 0); + const std::string &idPath); /** * Convenience wrapper around ResourceManager::create for loading * images. */ - Image *getImage(const std::string &idPath, int flags = 0); + Image *getImage(const std::string &idPath); /** * Convenience wrapper around ResourceManager::create for loading |