diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/client.cpp | 13 | ||||
-rw-r--r-- | src/compoundsprite.cpp | 11 | ||||
-rw-r--r-- | src/graphics.cpp | 18 | ||||
-rw-r--r-- | src/graphicsmanager.cpp | 16 | ||||
-rw-r--r-- | src/gui/debugwindow.cpp | 4 | ||||
-rw-r--r-- | src/gui/minimap.cpp | 3 | ||||
-rw-r--r-- | src/gui/sdlfont.cpp | 5 | ||||
-rw-r--r-- | src/gui/widgets/desktop.cpp | 5 | ||||
-rw-r--r-- | src/opengl1graphics.cpp | 17 | ||||
-rw-r--r-- | src/openglgraphics.cpp | 33 | ||||
-rw-r--r-- | src/resources/ambientlayer.cpp | 5 | ||||
-rw-r--r-- | src/resources/image.cpp | 642 | ||||
-rw-r--r-- | src/resources/image.h | 103 | ||||
-rw-r--r-- | src/resources/imagehelper.cpp | 582 | ||||
-rw-r--r-- | src/resources/imagehelper.h | 170 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 5 |
18 files changed, 837 insertions, 799 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c0e33dc0b..39a4d7a87 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -409,6 +409,8 @@ SET(SRCS resources/emotedb.h resources/image.cpp resources/image.h + resources/imagehelper.cpp + resources/imagehelper.h resources/imageset.h resources/imageset.cpp resources/imagewriter.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 12f107a97..518e82a7d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -423,6 +423,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/emotedb.h \ resources/image.cpp \ resources/image.h \ + resources/imagehelper.cpp \ + resources/imagehelper.h \ resources/imageset.h \ resources/imageset.cpp \ resources/imagewriter.cpp \ diff --git a/src/client.cpp b/src/client.cpp index 95317f682..35658f0f9 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -85,6 +85,7 @@ #include "resources/colordb.h" #include "resources/emotedb.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "resources/itemdb.h" #include "resources/mapdb.h" #include "resources/monsterdb.h" @@ -397,14 +398,14 @@ void Client::gameInit() } #if defined USE_OPENGL - Image::setBlur(config.getBoolValue("blur")); - Image::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache") + ImageHelper::setBlur(config.getBoolValue("blur")); + ImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache") && !config.getIntValue("opengl")); - Image::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f || config.getIntValue("opengl")); #else - Image::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache")); - Image::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); + ImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache")); + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); #endif resman->addToSearchPath(PKG_DATADIR "data/perserver/default", false); @@ -1504,7 +1505,7 @@ void Client::optionChanged(const std::string &name) else if (name == "guialpha") { setGuiAlpha(config.getFloatValue("guialpha")); - Image::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); } else if (name == "gamma") { diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index f4890fe2b..41a53467e 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -33,6 +33,7 @@ #include "map.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "utils/dtor.h" @@ -395,12 +396,12 @@ void CompoundSprite::redraw() const delete mImage; delete mAlphaImage; - mImage = Image::load(surface); + mImage = ImageHelper::load(surface); SDL_FreeSurface(surface); - if (Image::mEnableAlpha) + if (ImageHelper::mEnableAlpha) { - mAlphaImage = Image::load(surfaceA); + mAlphaImage = ImageHelper::load(surfaceA); SDL_FreeSurface(surfaceA); } else @@ -414,7 +415,7 @@ void CompoundSprite::setAlpha(float alpha) if (alpha != mAlpha) { #ifdef USE_OPENGL - if (mEnableAlphaFix && Image::mUseOpenGL == 0 && size() > 3) + if (mEnableAlphaFix && ImageHelper::mUseOpenGL == 0 && size() > 3) #else if (mEnableAlphaFix && size() > 3) #endif @@ -433,7 +434,7 @@ void CompoundSprite::setAlpha(float alpha) void CompoundSprite::updateImages() const { #ifdef USE_OPENGL - if (Image::mUseOpenGL) + if (ImageHelper::mUseOpenGL) return; #endif diff --git a/src/graphics.cpp b/src/graphics.cpp index 1d557d897..02567b5f2 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -30,6 +30,7 @@ #include "logger.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "utils/stringutils.h" #include <guichan/sdl/sdlpixel.hpp> @@ -178,23 +179,24 @@ bool Graphics::setOpenGLMode() GLint texSize; bool rectTex = graphicsManager.supportExtension( "GL_ARB_texture_rectangle"); - if (rectTex && Image::getInternalTextureType() == 4 + if (rectTex && ImageHelper::getInternalTextureType() == 4 && config.getBoolValue("rectangulartextures")) { logger->log1("using GL_ARB_texture_rectangle"); - Image::mTextureType = GL_TEXTURE_RECTANGLE_ARB; + ImageHelper::mTextureType = GL_TEXTURE_RECTANGLE_ARB; glEnable(GL_TEXTURE_RECTANGLE_ARB); glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texSize); - Image::mTextureSize = texSize; + ImageHelper::mTextureSize = texSize; logger->log("OpenGL texture size: %d pixels (rectangle textures)", - Image::mTextureSize); + ImageHelper::mTextureSize); } else { - Image::mTextureType = GL_TEXTURE_2D; + ImageHelper::mTextureType = GL_TEXTURE_2D; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize); - Image::mTextureSize = texSize; - logger->log("OpenGL texture size: %d pixels", Image::mTextureSize); + ImageHelper::mTextureSize = texSize; + logger->log("OpenGL texture size: %d pixels", + ImageHelper::mTextureSize); } return videoInfo(); #else @@ -282,7 +284,7 @@ bool Graphics::videoInfo() mDoubleBuffer = ((mTarget->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF); logger->log("Double buffer mode: %s", mDoubleBuffer ? "yes" : "no"); - Image::dumpSurfaceFormat(mTarget); + ImageHelper::dumpSurfaceFormat(mTarget); const SDL_VideoInfo *vi = SDL_GetVideoInfo(); if (!vi) diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index eaab12e03..61e157353 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -25,7 +25,7 @@ #include "graphicsvertexes.h" #include "logger.h" -#include "resources/image.h" +#include "resources/imagehelper.h" #include "utils/paths.h" #include "utils/stringutils.h" @@ -153,7 +153,7 @@ void GraphicsManager::initGraphics(bool noOpenGL) useOpenGL = config.getIntValue("opengl"); // Setup image loading for the right image format - Image::setLoadAsOpenGL(useOpenGL); + ImageHelper::setLoadAsOpenGL(useOpenGL); GraphicsVertexes::setLoadAsOpenGL(useOpenGL); // Create the graphics context @@ -210,7 +210,7 @@ void GraphicsManager::updateTextureFormat() if (formats[f] == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { delete []formats; - Image::setInternalTextureType( + ImageHelper::setInternalTextureType( GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); logger->log1("using s3tc texture compression"); return; @@ -218,19 +218,19 @@ void GraphicsManager::updateTextureFormat() else if (formats[f] == GL_COMPRESSED_RGBA_FXT1_3DFX) { delete []formats; - Image::setInternalTextureType( + ImageHelper::setInternalTextureType( GL_COMPRESSED_RGBA_FXT1_3DFX); logger->log1("using fxt1 texture compression"); return; } } - Image::setInternalTextureType(GL_COMPRESSED_RGBA_ARB); + ImageHelper::setInternalTextureType(GL_COMPRESSED_RGBA_ARB); logger->log1("using texture compression"); return; } else { - Image::setInternalTextureType(GL_COMPRESSED_RGBA_ARB); + ImageHelper::setInternalTextureType(GL_COMPRESSED_RGBA_ARB); logger->log1("using texture compression"); return; } @@ -240,12 +240,12 @@ void GraphicsManager::updateTextureFormat() // using default formats if (config.getBoolValue("newtextures")) { - Image::setInternalTextureType(GL_RGBA); + ImageHelper::setInternalTextureType(GL_RGBA); logger->log1("using RGBA texture format"); } else { - Image::setInternalTextureType(4); + ImageHelper::setInternalTextureType(4); logger->log1("using 4 texture format"); } #endif diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index 0976f73b5..6d0895426 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -41,7 +41,7 @@ #include "gui/widgets/tab.h" #include "gui/widgets/tabbedarea.h" -#include "resources/image.h" +#include "resources/imagehelper.h" #include "net/packetcounters.h" @@ -158,7 +158,7 @@ MapDebugTab::MapDebugTab() : mUpdateTime = 0; #ifdef USE_OPENGL - switch (Image::getLoadAsOpenGL()) + switch (ImageHelper::getLoadAsOpenGL()) { case 0: mFPSText = _("%d FPS (Software)"); diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index e4bf62ec6..30d9f40bb 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -36,6 +36,7 @@ #include "gui/viewport.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "resources/resourcemanager.h" #include "utils/gettext.h" @@ -142,7 +143,7 @@ void Minimap::setMap(Map *map) SDL_UnlockSurface(surface); - mMapImage = Image::load(surface); + mMapImage = ImageHelper::load(surface); mMapImage->setAlpha(Client::getGuiAlpha()); mCustomMapImage = true; SDL_FreeSurface(surface); diff --git a/src/gui/sdlfont.cpp b/src/gui/sdlfont.cpp index 8713367bc..bafc2c8e2 100644 --- a/src/gui/sdlfont.cpp +++ b/src/gui/sdlfont.cpp @@ -30,6 +30,7 @@ #include "utils/paths.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "resources/resourcemanager.h" #include "utils/stringutils.h" @@ -84,9 +85,7 @@ class SDLTextChunk return; } - img = Image::createTextSurface(surface, alpha); -// img = Image::load(surface); - + img = ImageHelper::createTextSurface(surface, alpha); SDL_FreeSurface(surface); } diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index 6352c300f..a0f2eb3fe 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -32,6 +32,7 @@ #include "gui/widgets/label.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "resources/resourcemanager.h" #include "resources/wallpaper.h" @@ -99,7 +100,7 @@ void Desktop::draw(gcn::Graphics *graphics) if (mWallpaper) { - if (!mWallpaper->useOpenGL()) + if (!ImageHelper::useOpenGL()) { g->drawImage(mWallpaper, (getWidth() - mWallpaper->getWidth()) / 2, @@ -135,7 +136,7 @@ void Desktop::setBestFittingWallpaper() if (mWallpaper) mWallpaper->decRef(); - if (!nWallPaper->useOpenGL() + if (!ImageHelper::useOpenGL() && (nWallPaper->getWidth() != getWidth() || nWallPaper->getHeight() != getHeight())) { diff --git a/src/opengl1graphics.cpp b/src/opengl1graphics.cpp index dbd983fb5..2bb6e06a2 100644 --- a/src/opengl1graphics.cpp +++ b/src/opengl1graphics.cpp @@ -30,6 +30,7 @@ #include "logger.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include <SDL.h> @@ -66,7 +67,7 @@ static inline void drawQuad(const Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height) { - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. float texX1 = static_cast<float>(srcX) @@ -104,7 +105,7 @@ static inline void drawRescaledQuad(Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, int desiredWidth, int desiredHeight) { - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. float texX1 = static_cast<float>(srcX) @@ -152,7 +153,7 @@ bool OpenGL1Graphics::drawImage(const Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -212,7 +213,7 @@ bool OpenGL1Graphics::drawRescaledImage(Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -266,7 +267,7 @@ void OpenGL1Graphics::drawImagePattern(const Image *image, int x, int y, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -312,7 +313,7 @@ void OpenGL1Graphics::drawRescaledImagePattern(Image *image, int x, int y, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -628,7 +629,7 @@ void OpenGL1Graphics::setTexturingAndBlending(bool enable) { if (!mTexture) { - glEnable(Image::mTextureType); + glEnable(ImageHelper::mTextureType); mTexture = true; } @@ -654,7 +655,7 @@ void OpenGL1Graphics::setTexturingAndBlending(bool enable) if (mTexture) { - glDisable(Image::mTextureType); + glDisable(ImageHelper::mTextureType); mTexture = false; } } diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 298580e63..3ca2a8c09 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -30,6 +30,7 @@ #include "logger.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "utils/stringutils.h" @@ -80,7 +81,7 @@ static inline void drawQuad(const Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height) { - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. const float texX1 = static_cast<float>(srcX) / @@ -142,7 +143,7 @@ static inline void drawRescaledQuad(Image *image, int width, int height, int desiredWidth, int desiredHeight) { - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. const float texX1 = static_cast<float>(srcX) / @@ -213,7 +214,7 @@ bool OpenGLGraphics::drawImage(const Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -270,7 +271,7 @@ bool OpenGLGraphics::drawRescaledImage(Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -323,14 +324,14 @@ void OpenGLGraphics::drawImagePattern(const Image *image, int x, int y, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); unsigned int vp = 0; const unsigned int vLimit = vertexBufSize * 4; // Draw a set of textured rectangles - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { float texX1 = static_cast<float>(srcX) / tw; float texY1 = static_cast<float>(srcY) / th; @@ -457,7 +458,7 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -465,7 +466,7 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image, const unsigned int vLimit = vertexBufSize * 4; // Draw a set of textured rectangles - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { const float tw = static_cast<float>(image->getTextureWidth()); const float th = static_cast<float>(image->getTextureHeight()); @@ -597,7 +598,7 @@ void OpenGLGraphics::drawImagePattern2(GraphicsVertexes *vert, OpenGLGraphicsVertexes *ogl = vert->getOGL(); glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); std::vector<GLint*> *intVertPool = ogl->getIntVertPool(); @@ -608,7 +609,7 @@ void OpenGLGraphics::drawImagePattern2(GraphicsVertexes *vert, std::vector<int>::const_iterator ivp_end = vp->end(); // Draw a set of textured rectangles - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { std::vector<GLfloat*> *floatTexPool = ogl->getFloatTexPool(); std::vector<GLfloat*>::const_iterator ft; @@ -677,7 +678,7 @@ void OpenGLGraphics::calcImagePattern(GraphicsVertexes* vert, Image *image, ogl->init(); // Draw a set of textured rectangles - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { float texX1 = static_cast<float>(srcX) / tw; float texY1 = static_cast<float>(srcY) / th; @@ -810,7 +811,7 @@ void OpenGLGraphics::calcTile(ImageVertexes *vert, int dstX, int dstY) unsigned int vp = ogl->ptr; // Draw a set of textured rectangles - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) { float texX1 = static_cast<float>(srcX) / tw; float texY1 = static_cast<float>(srcY) / th; @@ -911,10 +912,10 @@ void OpenGLGraphics::drawTile(ImageVertexes *vert) OpenGLGraphicsVertexes *ogl = vert->ogl; glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(Image::mTextureType, image->mGLImage); + bindTexture(ImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); - if (image->mTextureType == GL_TEXTURE_2D) + if (ImageHelper::mTextureType == GL_TEXTURE_2D) drawQuadArrayfi(ogl->mIntVertArray, ogl->mFloatTexArray, ogl->ptr); else drawQuadArrayii(ogl->mIntVertArray, ogl->mIntTexArray, ogl->ptr); @@ -1188,7 +1189,7 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable) { if (!mTexture) { - glEnable(Image::mTextureType); + glEnable(ImageHelper::mTextureType); mTexture = true; } @@ -1214,7 +1215,7 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable) if (mTexture) { - glDisable(Image::mTextureType); + glDisable(ImageHelper::mTextureType); mTexture = false; } } diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp index b5640904c..f2eaeab81 100644 --- a/src/resources/ambientlayer.cpp +++ b/src/resources/ambientlayer.cpp @@ -24,6 +24,7 @@ #include "graphics.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "resources/resourcemanager.h" #include "debug.h" @@ -38,7 +39,7 @@ AmbientLayer::AmbientLayer(Image *img, float parallax, if (!mImage) return; - if (keepRatio && !mImage->useOpenGL() + if (keepRatio && !ImageHelper::useOpenGL() /*&& defaultScreenWidth != 0 && defaultScreenHeight != 0*/ && mainGraphics->mWidth != defaultScreenWidth @@ -105,7 +106,7 @@ void AmbientLayer::draw(Graphics *graphics, int x, int y) if (!mImage) return; - if (!mImage->useOpenGL() || !mKeepRatio) + if (!ImageHelper::useOpenGL() || !mKeepRatio) { graphics->drawImagePattern(mImage, static_cast<int>(-mPosX), static_cast<int>(-mPosY), x + static_cast<int>(mPosX), diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 85643c8df..0e0937ce6 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -36,21 +36,13 @@ #include "utils/stringutils.h" +#include "resources/imagehelper.h" + #include <SDL_image.h> #include <SDL_rotozoom.h> #include "debug.h" -#ifdef USE_OPENGL -int Image::mUseOpenGL = 0; -int Image::mTextureType = 0; -int Image::mInternalTextureType = GL_RGBA8; -int Image::mTextureSize = 0; -bool Image::mBlur = true; -#endif -bool Image::mEnableAlphaCache = false; -bool Image::mEnableAlpha = true; - Image::Image(SDL_Surface *image, bool hasAlphaChannel0, Uint8 *alphaChannel): mAlpha(1.0f), mHasAlphaChannel(hasAlphaChannel0), @@ -63,7 +55,7 @@ Image::Image(SDL_Surface *image, bool hasAlphaChannel0, Uint8 *alphaChannel): mGLImage = 0; #endif - mUseAlphaCache = Image::mEnableAlphaCache; + mUseAlphaCache = ImageHelper::mEnableAlphaCache; mBounds.x = 0; mBounds.y = 0; @@ -123,214 +115,6 @@ Image::~Image() unload(); } -Resource *Image::load(SDL_RWops *rw) -{ - SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); - - if (!tmpImage) - { - logger->log("Error, image load failed: %s", IMG_GetError()); - return nullptr; - } - - Image *image = load(tmpImage); - - SDL_FreeSurface(tmpImage); - return image; -} - -Resource *Image::load(SDL_RWops *rw, Dye const &dye) -{ - SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); - - if (!tmpImage) - { - logger->log("Error, image load failed: %s", IMG_GetError()); - return nullptr; - } - - SDL_Surface *surf = nullptr; - SDL_PixelFormat rgba; - rgba.palette = nullptr; - rgba.BitsPerPixel = 32; - rgba.BytesPerPixel = 4; - rgba.colorkey = 0; - rgba.alpha = 255; - if (mUseOpenGL) - { - surf = convertTo32Bit(tmpImage); - SDL_FreeSurface(tmpImage); - - Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); - DyePalette *pal = dye.getSPalete(); - - if (pal) - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - Uint8 *p = (Uint8 *)pixels; - const int alpha = *p & 255; - if (!alpha) - continue; - pal->replaceOGLColor(p); - } - } - else - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - const Uint32 p = *pixels; - const int alpha = (p >> 24) & 255; - if (!alpha) - continue; - int v[3]; - v[0] = (p) & 255; - v[1] = (p >> 8) & 255; - v[2] = (p >> 16 ) & 255; - dye.update(v); - *pixels = (v[0]) | (v[1] << 8) | (v[2] << 16) | (alpha << 24); - } - } - } - else - { - rgba.Rmask = 0xFF000000; rgba.Rloss = 0; rgba.Rshift = 24; - rgba.Gmask = 0x00FF0000; rgba.Gloss = 0; rgba.Gshift = 16; - rgba.Bmask = 0x0000FF00; rgba.Bloss = 0; rgba.Bshift = 8; - rgba.Amask = 0x000000FF; rgba.Aloss = 0; rgba.Ashift = 0; - - surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); - SDL_FreeSurface(tmpImage); - - Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); - DyePalette *pal = dye.getSPalete(); - - if (pal) - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - Uint8 *p = (Uint8 *)pixels; - const int alpha = *p & 255; - if (!alpha) - continue; - pal->replaceColor(p + 1); - } - } - else - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - const Uint32 p = *pixels; - const int alpha = p & 255; - if (!alpha) - continue; - int v[3]; - v[0] = (p >> 24) & 255; - v[1] = (p >> 16) & 255; - v[2] = (p >> 8 ) & 255; - dye.update(v); - *pixels = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | alpha; - } - } - } - - Image *image = load(surf); - SDL_FreeSurface(surf); - return image; -} - -Image *Image::load(SDL_Surface *tmpImage) -{ -#ifdef USE_OPENGL - if (mUseOpenGL) - return _GLload(tmpImage); -#endif - return _SDLload(tmpImage); -} - -Image *Image::createTextSurface(SDL_Surface *tmpImage, float alpha) -{ - if (!tmpImage) - return nullptr; - - Image *img; -#ifdef USE_OPENGL - if (mUseOpenGL) - { - img = _GLload(tmpImage); - if (img) - img->setAlpha(alpha); - return img; - } -#endif - - bool hasAlpha = false; - bool converted = false; - - const int sz = tmpImage->w * tmpImage->h; - - // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[sz]; - - const SDL_PixelFormat * const fmt = tmpImage->format; - if (fmt->Amask) - { - for (int i = 0; i < sz; ++ i) - { - Uint32 c = (static_cast<Uint32*>(tmpImage->pixels))[i]; - - unsigned v = (c & fmt->Amask) >> fmt->Ashift; - Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); - - Uint8 a2 = static_cast<Uint8>(static_cast<float>(a) * alpha); - - c &= ~fmt->Amask; - c |= ((a2 >> fmt->Aloss) << fmt->Ashift & fmt->Amask); - (static_cast<Uint32*>(tmpImage->pixels))[i] = c; - - if (a != 255) - hasAlpha = true; - - alphaChannel[i] = a; - } - } - - SDL_Surface *image; - - // Convert the surface to the current display format - if (hasAlpha) - { - image = SDL_DisplayFormatAlpha(tmpImage); - } - else - { - image = SDL_DisplayFormat(tmpImage); - - // We also delete the alpha channel since - // it's not used. - delete [] alphaChannel; - alphaChannel = nullptr; - } - - if (!image) - { - logger->log1("Error: Image convert failed."); - delete [] alphaChannel; - return nullptr; - } - - if (converted) - SDL_FreeSurface(tmpImage); - - img = new Image(image, hasAlpha, alphaChannel); - img->mAlpha = alpha; - return img; -} - void Image::SDLCleanCache() { ResourceManager *resman = ResourceManager::getInstance(); @@ -374,22 +158,13 @@ void Image::unload() #endif } -int Image::useOpenGL() const -{ -#ifdef USE_OPENGL - return mUseOpenGL; -#else - return 0; -#endif -} - bool Image::hasAlphaChannel() { if (mLoaded) return mHasAlphaChannel; #ifdef USE_OPENGL - if (mUseOpenGL) + if (ImageHelper::mUseOpenGL) return true; #endif @@ -406,7 +181,7 @@ SDL_Surface *Image::getByAlpha(float alpha) void Image::setAlpha(float alpha) { - if (mAlpha == alpha || !mEnableAlpha) + if (mAlpha == alpha || !ImageHelper::mEnableAlpha) return; if (alpha < 0.0f || alpha > 1.0f) @@ -456,7 +231,7 @@ void Image::setAlpha(float alpha) } else { - mSDLSurface = Image::SDLDuplicateSurface(mSDLSurface); + mSDLSurface = ImageHelper::SDLDuplicateSurface(mSDLSurface); } // logger->log("miss"); } @@ -510,97 +285,6 @@ void Image::setAlpha(float alpha) } } -Image* Image::SDLmerge(Image *image, int x, int y) -{ - if (!mSDLSurface || !image || !image->mSDLSurface) - return nullptr; - - SDL_Surface* surface = new SDL_Surface(*(image->mSDLSurface)); - - Uint32 surface_pix, cur_pix; - Uint8 r, g, b, a, p_r, p_g, p_b, p_a; - double f_a, f_ca, f_pa; - SDL_PixelFormat *current_fmt = mSDLSurface->format; - SDL_PixelFormat *surface_fmt = surface->format; - int current_offset, surface_offset; - int offset_x, offset_y; - - SDL_LockSurface(surface); - SDL_LockSurface(mSDLSurface); - - const int x0 = (y * mBounds.w) + x; - const int maxX = std::min(image->mBounds.w, - static_cast<Uint16>(mBounds.w - x)); - const int maxY = std::min(image->mBounds.w, - static_cast<Uint16>(mBounds.h - y)); - - // for each pixel lines of a source image - for (offset_x = ((x > 0) ? 0 : -x); offset_x < maxX; offset_x++) - { - const int x1 = x0 + offset_x; - for (offset_y = ((y > 0) ? 0 : -y); offset_y < maxY; offset_y++) - { - // Computing offset on both images - current_offset = (offset_y * mBounds.w) + x1; - surface_offset = offset_y * surface->w + offset_x; - - // Retrieving a pixel to merge - surface_pix = (static_cast<Uint32*>( - surface->pixels))[surface_offset]; - cur_pix = (static_cast<Uint32*>( - mSDLSurface->pixels))[current_offset]; - - // Retreiving each channel of the pixel using pixel format - r = static_cast<Uint8>(((surface_pix & surface_fmt->Rmask) >> - surface_fmt->Rshift) << surface_fmt->Rloss); - g = static_cast<Uint8>(((surface_pix & surface_fmt->Gmask) >> - surface_fmt->Gshift) << surface_fmt->Gloss); - b = static_cast<Uint8>(((surface_pix & surface_fmt->Bmask) >> - surface_fmt->Bshift) << surface_fmt->Bloss); - a = static_cast<Uint8>(((surface_pix & surface_fmt->Amask) >> - surface_fmt->Ashift) << surface_fmt->Aloss); - - // Retreiving previous alpha value - p_a = static_cast<Uint8>(((cur_pix & current_fmt->Amask) >> - current_fmt->Ashift) << current_fmt->Aloss); - - // new pixel with no alpha or nothing on previous pixel - if (a == SDL_ALPHA_OPAQUE || (p_a == 0 && a > 0)) - { - (static_cast<Uint32 *>(surface->pixels))[current_offset] = - SDL_MapRGBA(current_fmt, r, g, b, a); - } - else if (a > 0) - { // alpha is lower => merge color with previous value - f_a = static_cast<double>(a) / 255.0; - f_ca = 1.0 - f_a; - f_pa = static_cast<double>(p_a) / 255.0; - p_r = static_cast<Uint8>(((cur_pix & current_fmt->Rmask) >> - current_fmt->Rshift) << current_fmt->Rloss); - p_g = static_cast<Uint8>(((cur_pix & current_fmt->Gmask) >> - current_fmt->Gshift) << current_fmt->Gloss); - p_b = static_cast<Uint8>(((cur_pix & current_fmt->Bmask) >> - current_fmt->Bshift) << current_fmt->Bloss); - r = static_cast<Uint8>(static_cast<double>(p_r) * f_ca - * f_pa + static_cast<double>(r) * f_a); - g = static_cast<Uint8>(static_cast<double>(p_g) * f_ca - * f_pa + static_cast<double>(g) * f_a); - b = static_cast<Uint8>(static_cast<double>(p_b) * f_ca - * f_pa + static_cast<double>(b) * f_a); - a = (a > p_a ? a : p_a); - (static_cast<Uint32 *>(surface->pixels))[current_offset] = - SDL_MapRGBA(current_fmt, r, g, b, a); - } - } - } - SDL_UnlockSurface(surface); - SDL_UnlockSurface(mSDLSurface); - - Image *newImage = new Image(surface); - - return newImage; -} - Image* Image::SDLgetScaledImage(int width, int height) { // No scaling on incorrect new values. @@ -625,312 +309,18 @@ Image* Image::SDLgetScaledImage(int width, int height) // and about freeing the given SDL_surface*. if (scaledSurface) { - scaledImage = load(scaledSurface); + scaledImage = ImageHelper::load(scaledSurface); SDL_FreeSurface(scaledSurface); } } return scaledImage; } -SDL_Surface* Image::convertTo32Bit(SDL_Surface* tmpImage) -{ - if (!tmpImage) - return nullptr; - SDL_PixelFormat RGBAFormat; - RGBAFormat.palette = nullptr; - RGBAFormat.colorkey = 0; - RGBAFormat.alpha = 0; - RGBAFormat.BitsPerPixel = 32; - RGBAFormat.BytesPerPixel = 4; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - RGBAFormat.Rmask = 0xFF000000; - RGBAFormat.Rshift = 0; - RGBAFormat.Rloss = 0; - RGBAFormat.Gmask = 0x00FF0000; - RGBAFormat.Gshift = 8; - RGBAFormat.Gloss = 0; - RGBAFormat.Bmask = 0x0000FF00; - RGBAFormat.Bshift = 16; - RGBAFormat.Bloss = 0; - RGBAFormat.Amask = 0x000000FF; - RGBAFormat.Ashift = 24; - RGBAFormat.Aloss = 0; -#else - RGBAFormat.Rmask = 0x000000FF; - RGBAFormat.Rshift = 24; - RGBAFormat.Rloss = 0; - RGBAFormat.Gmask = 0x0000FF00; - RGBAFormat.Gshift = 16; - RGBAFormat.Gloss = 0; - RGBAFormat.Bmask = 0x00FF0000; - RGBAFormat.Bshift = 8; - RGBAFormat.Bloss = 0; - RGBAFormat.Amask = 0xFF000000; - RGBAFormat.Ashift = 0; - RGBAFormat.Aloss = 0; -#endif - return SDL_ConvertSurface(tmpImage, &RGBAFormat, SDL_SWSURFACE); -} - -SDL_Surface* Image::SDLDuplicateSurface(SDL_Surface* tmpImage) -{ - if (!tmpImage || !tmpImage->format) - return nullptr; - - return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); -} - -Image *Image::_SDLload(SDL_Surface *tmpImage) -{ - if (!tmpImage) - return nullptr; - - bool hasAlpha = false; - bool converted = false; - - if (tmpImage->format->BitsPerPixel != 32) - { - tmpImage = convertTo32Bit(tmpImage); - - if (!tmpImage) - return nullptr; - converted = true; - } - - const int sz = tmpImage->w * tmpImage->h; - - // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[sz]; - - // Figure out whether the image uses its alpha layer - if (!tmpImage->format->palette) - { - const SDL_PixelFormat * const fmt = tmpImage->format; - if (fmt->Amask) - { - for (int i = 0; i < sz; ++ i) - { - unsigned v = ((static_cast<Uint32*>(tmpImage->pixels))[i] - & fmt->Amask) >> fmt->Ashift; - Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); - - if (a != 255) - hasAlpha = true; - - alphaChannel[i] = a; - } - } - else - { - if (SDL_ALPHA_OPAQUE != 255) - { - hasAlpha = true; - memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); - } - } - } - else - { - if (SDL_ALPHA_OPAQUE != 255) - { - hasAlpha = true; - memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); - } - } - - SDL_Surface *image; - - // Convert the surface to the current display format - if (hasAlpha) - { - image = SDL_DisplayFormatAlpha(tmpImage); - } - else - { - image = SDL_DisplayFormat(tmpImage); - - // We also delete the alpha channel since - // it's not used. - delete [] alphaChannel; - alphaChannel = nullptr; - } - - if (!image) - { - logger->log1("Error: Image convert failed."); - delete [] alphaChannel; - return nullptr; - } - - if (converted) - SDL_FreeSurface(tmpImage); - - return new Image(image, hasAlpha, alphaChannel); -} - -#ifdef USE_OPENGL -Image *Image::_GLload(SDL_Surface *tmpImage) -{ - if (!tmpImage) - return nullptr; - - // Flush current error flag. - glGetError(); - - int width = tmpImage->w; - int height = tmpImage->h; - int realWidth = powerOfTwo(width); - int realHeight = powerOfTwo(height); - - if (realWidth < width || realHeight < height) - { - logger->log("Warning: image too large, cropping to %dx%d texture!", - tmpImage->w, tmpImage->h); - } - - // Make sure the alpha channel is not used, but copied to destination - SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); - - // Determine 32-bit masks based on byte order - Uint32 rmask, gmask, bmask, amask; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x000000ff; - gmask = 0x0000ff00; - bmask = 0x00ff0000; - amask = 0xff000000; -#endif - - SDL_Surface *oldImage = nullptr; - if (tmpImage->format->BitsPerPixel != 32 - || realWidth != width || realHeight != height - || rmask != tmpImage->format->Rmask - || gmask != tmpImage->format->Gmask - || amask != tmpImage->format->Amask) - { - oldImage = tmpImage; - tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, - 32, rmask, gmask, bmask, amask); - - if (!tmpImage) - { - logger->log("Error, image convert failed: out of memory"); - return nullptr; - } - SDL_BlitSurface(oldImage, nullptr, tmpImage, nullptr); - } - - GLuint texture; - glGenTextures(1, &texture); - if (mUseOpenGL == 1) - OpenGLGraphics::bindTexture(mTextureType, texture); - else if (mUseOpenGL == 2) - OpenGL1Graphics::bindTexture(mTextureType, texture); - - if (SDL_MUSTLOCK(tmpImage)) - SDL_LockSurface(tmpImage); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - if (mBlur) - { - glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexImage2D(mTextureType, 0, mInternalTextureType, - tmpImage->w, tmpImage->h, - 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels); - -/* - GLint compressed; - glGetTexLevelParameteriv(mTextureType, 0, - GL_TEXTURE_COMPRESSED_ARB, &compressed); - if (compressed) - logger->log("image compressed"); - else - logger->log("image not compressed"); -*/ - -#ifdef DEBUG_OPENGL_LEAKS - textures_count ++; -#endif - - if (SDL_MUSTLOCK(tmpImage)) - SDL_UnlockSurface(tmpImage); - - if (oldImage) - SDL_FreeSurface(tmpImage); - - GLenum error = glGetError(); - if (error) - { - std::string errmsg = "Unknown error"; - switch (error) - { - case GL_INVALID_ENUM: - errmsg = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - errmsg = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - errmsg = "GL_INVALID_OPERATION"; - break; - case GL_STACK_OVERFLOW: - errmsg = "GL_STACK_OVERFLOW"; - break; - case GL_STACK_UNDERFLOW: - errmsg = "GL_STACK_UNDERFLOW"; - break; - case GL_OUT_OF_MEMORY: - errmsg = "GL_OUT_OF_MEMORY"; - break; - default: - break; - } - logger->log("Error: Image GL import failed: %s", errmsg.c_str()); - return nullptr; - } - - return new Image(texture, width, height, realWidth, realHeight); -} - -void Image::setLoadAsOpenGL(int useOpenGL) -{ - Image::mUseOpenGL = useOpenGL; -} - -int Image::powerOfTwo(int input) -{ - int value; - if (mTextureType == GL_TEXTURE_2D) - { - value = 1; - while (value < input && value < mTextureSize) - value <<= 1; - } - else - { - value = input; - } - return value >= mTextureSize ? mTextureSize : value; -} -#endif - Image *Image::getSubImage(int x, int y, int width, int height) { // Create a new clipped sub-image #ifdef USE_OPENGL - if (mUseOpenGL) + if (ImageHelper::mUseOpenGL) { return new SubImage(this, mGLImage, x, y, width, height, mTexWidth, mTexHeight); @@ -946,22 +336,6 @@ void Image::SDLTerminateAlphaCache() mUseAlphaCache = false; } -void Image::dumpSurfaceFormat(SDL_Surface *image) -{ - if (image->format) - { - const SDL_PixelFormat * const format = image->format; - logger->log("Bytes per pixel: %d", format->BytesPerPixel); - logger->log("Alpha: %d", format->alpha); - logger->log("Loss: %02x, %02x, %02x, %02x", (int)format->Rloss, - (int)format->Gloss, (int)format->Bloss, (int)format->Aloss); - logger->log("Shift: %02x, %02x, %02x, %02x", (int)format->Rshift, - (int)format->Gshift, (int)format->Bshift, (int)format->Ashift); - logger->log("Mask: %08x, %08x, %08x, %08x", format->Rmask, - format->Gmask, format->Bmask, format->Amask); - } -} - //============================================================================ // SubImage Class //============================================================================ diff --git a/src/resources/image.h b/src/resources/image.h index 96bf0f95c..2a3f16c85 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -55,6 +55,7 @@ class Image : public Resource { friend class CompoundSprite; friend class Graphics; + friend class ImageHelper; #ifdef USE_OPENGL friend class OpenGLGraphics; friend class OpenGL1Graphics; @@ -67,36 +68,6 @@ class Image : public Resource virtual ~Image(); /** - * Loads an image from an SDL_RWops structure. - * - * @param rw The SDL_RWops to load the image from. - * - * @return <code>NULL</code> if an error occurred, a valid pointer - * otherwise. - */ - static Resource *load(SDL_RWops *rw); - - /** - * Loads an image from an SDL_RWops structure and recolors it. - * - * @param rw The SDL_RWops to load the image from. - * @param dye The dye used to recolor the image. - * - * @return <code>NULL</code> if an error occurred, a valid pointer - * otherwise. - */ - static Resource *load(SDL_RWops *rw, Dye const &dye); - - /** - * Loads an image from an SDL surface. - */ - static Image *load(SDL_Surface *); - - static SDL_Surface* convertTo32Bit(SDL_Surface* tmpImage); - - static Image *createTextSurface(SDL_Surface *tmpImage, float alpha); - - /** * Frees the resources created by SDL. */ virtual void unload(); @@ -120,12 +91,6 @@ class Image : public Resource { return mBounds.h; } /** - * Tells if the image was loaded using OpenGL or SDL - * @return true if OpenGL, false if SDL. - */ - int useOpenGL() const; - - /** * Tells if the image has got an alpha channel * @return true if it's true, false otherwise. */ @@ -164,72 +129,23 @@ class Image : public Resource Image* SDLgetScaledImage(int width, int height); /** - * Merges two image SDL_Surfaces together. This is for SDL use only, as - * reducing the number of surfaces that SDL has to render can cut down - * on the number of blit operations necessary, which in turn can help - * improve overall framerates. Don't use unless you are using it to - * reduce the number of overall layers that need to be drawn through SDL. - */ - Image *SDLmerge(Image *image, int x, int y); - - /** * Get the alpha Channel of a SDL surface. */ Uint8 *SDLgetAlphaChannel() const { return mAlphaChannel; } - SDL_Surface* SDLDuplicateSurface(SDL_Surface* tmpImage); - void SDLCleanCache(); void SDLTerminateAlphaCache(); - static void SDLSetEnableAlphaCache(bool n) - { mEnableAlphaCache = n; } - - static bool SDLGetEnableAlphaCache() - { return mEnableAlphaCache; } - - static void setEnableAlpha(bool n) - { mEnableAlpha = n; } - #ifdef USE_OPENGL - // OpenGL only public functions - /** - * Sets the target image format. Use <code>false</code> for SDL and - * <code>true</code> for OpenGL. - */ - static void setLoadAsOpenGL(int useOpenGL); - - static int getLoadAsOpenGL() - { return mUseOpenGL; } - int getTextureWidth() const { return mTexWidth; } int getTextureHeight() const { return mTexHeight; } - - static int getTextureType() - { return mTextureType; } - - static int getInternalTextureType() - { return mInternalTextureType; } - - static void setInternalTextureType(int n) - { mInternalTextureType = n; } - - static void setBlur(bool n) - { mBlur = n; } - - static int mTextureType; - - static int mInternalTextureType; - - static void dumpSurfaceFormat(SDL_Surface *image); - #endif bool isHasAlphaChannel() const @@ -267,9 +183,6 @@ class Image : public Resource Image(SDL_Surface *image, bool hasAlphaChannel = false, Uint8 *alphaChannel = nullptr); - /** SDL_Surface to SDL_Surface Image loader */ - static Image *_SDLload(SDL_Surface *tmpImage); - SDL_Surface *getByAlpha(float alpha); SDL_Surface *mSDLSurface; @@ -283,9 +196,6 @@ class Image : public Resource bool mIsAlphaVisible; bool mIsAlphaCalculated; - static bool mEnableAlphaCache; - static bool mEnableAlpha; - // ----------------------- // OpenGL protected members // ----------------------- @@ -296,19 +206,8 @@ class Image : public Resource Image(GLuint glimage, int width, int height, int texWidth, int texHeight); - /** - * Returns the first power of two equal or bigger than the input. - */ - static int powerOfTwo(int input); - - static Image *_GLload(SDL_Surface *tmpImage); - GLuint mGLImage; int mTexWidth, mTexHeight; - - static int mUseOpenGL; - static int mTextureSize; - static bool mBlur; #endif }; diff --git a/src/resources/imagehelper.cpp b/src/resources/imagehelper.cpp new file mode 100644 index 000000000..9ee52267e --- /dev/null +++ b/src/resources/imagehelper.cpp @@ -0,0 +1,582 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/imagehelper.h" + +#include "resources/dye.h" +#include "resources/resourcemanager.h" + +#ifdef USE_OPENGL +#include "openglgraphics.h" +#include "opengl1graphics.h" +#endif + +#include "client.h" +#include "logger.h" +#include "main.h" + +#include "utils/stringutils.h" + +#include "resources/image.h" + +#include <SDL_image.h> +#include <SDL_rotozoom.h> + +#include "debug.h" + +#ifdef USE_OPENGL +int ImageHelper::mUseOpenGL = 0; +int ImageHelper::mTextureType = 0; +int ImageHelper::mInternalTextureType = GL_RGBA8; +int ImageHelper::mTextureSize = 0; +bool ImageHelper::mBlur = true; +#endif +bool ImageHelper::mEnableAlphaCache = false; +bool ImageHelper::mEnableAlpha = true; + +Resource *ImageHelper::load(SDL_RWops *rw) +{ + SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); + + if (!tmpImage) + { + logger->log("Error, image load failed: %s", IMG_GetError()); + return nullptr; + } + + Image *image = load(tmpImage); + + SDL_FreeSurface(tmpImage); + return image; +} + +Resource *ImageHelper::load(SDL_RWops *rw, Dye const &dye) +{ + SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); + + if (!tmpImage) + { + logger->log("Error, image load failed: %s", IMG_GetError()); + return nullptr; + } + + SDL_Surface *surf = nullptr; + SDL_PixelFormat rgba; + rgba.palette = nullptr; + rgba.BitsPerPixel = 32; + rgba.BytesPerPixel = 4; + rgba.colorkey = 0; + rgba.alpha = 255; + if (mUseOpenGL) + { + surf = convertTo32Bit(tmpImage); + SDL_FreeSurface(tmpImage); + + Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); + DyePalette *pal = dye.getSPalete(); + + if (pal) + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + Uint8 *p = (Uint8 *)pixels; + const int alpha = *p & 255; + if (!alpha) + continue; + pal->replaceOGLColor(p); + } + } + else + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + const Uint32 p = *pixels; + const int alpha = (p >> 24) & 255; + if (!alpha) + continue; + int v[3]; + v[0] = (p) & 255; + v[1] = (p >> 8) & 255; + v[2] = (p >> 16 ) & 255; + dye.update(v); + *pixels = (v[0]) | (v[1] << 8) | (v[2] << 16) | (alpha << 24); + } + } + } + else + { + rgba.Rmask = 0xFF000000; rgba.Rloss = 0; rgba.Rshift = 24; + rgba.Gmask = 0x00FF0000; rgba.Gloss = 0; rgba.Gshift = 16; + rgba.Bmask = 0x0000FF00; rgba.Bloss = 0; rgba.Bshift = 8; + rgba.Amask = 0x000000FF; rgba.Aloss = 0; rgba.Ashift = 0; + + surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); + SDL_FreeSurface(tmpImage); + + Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); + DyePalette *pal = dye.getSPalete(); + + if (pal) + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + Uint8 *p = (Uint8 *)pixels; + const int alpha = *p & 255; + if (!alpha) + continue; + pal->replaceColor(p + 1); + } + } + else + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + const Uint32 p = *pixels; + const int alpha = p & 255; + if (!alpha) + continue; + int v[3]; + v[0] = (p >> 24) & 255; + v[1] = (p >> 16) & 255; + v[2] = (p >> 8 ) & 255; + dye.update(v); + *pixels = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | alpha; + } + } + } + + Image *image = load(surf); + SDL_FreeSurface(surf); + return image; +} + +Image *ImageHelper::load(SDL_Surface *tmpImage) +{ +#ifdef USE_OPENGL + if (mUseOpenGL) + return _GLload(tmpImage); +#endif + return _SDLload(tmpImage); +} + +Image *ImageHelper::createTextSurface(SDL_Surface *tmpImage, float alpha) +{ + if (!tmpImage) + return nullptr; + + Image *img; +#ifdef USE_OPENGL + if (mUseOpenGL) + { + img = _GLload(tmpImage); + if (img) + img->setAlpha(alpha); + return img; + } +#endif + + bool hasAlpha = false; + bool converted = false; + + const int sz = tmpImage->w * tmpImage->h; + + // The alpha channel to be filled with alpha values + Uint8 *alphaChannel = new Uint8[sz]; + + const SDL_PixelFormat * const fmt = tmpImage->format; + if (fmt->Amask) + { + for (int i = 0; i < sz; ++ i) + { + Uint32 c = (static_cast<Uint32*>(tmpImage->pixels))[i]; + + unsigned v = (c & fmt->Amask) >> fmt->Ashift; + Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); + + Uint8 a2 = static_cast<Uint8>(static_cast<float>(a) * alpha); + + c &= ~fmt->Amask; + c |= ((a2 >> fmt->Aloss) << fmt->Ashift & fmt->Amask); + (static_cast<Uint32*>(tmpImage->pixels))[i] = c; + + if (a != 255) + hasAlpha = true; + + alphaChannel[i] = a; + } + } + + SDL_Surface *image; + + // Convert the surface to the current display format + if (hasAlpha) + { + image = SDL_DisplayFormatAlpha(tmpImage); + } + else + { + image = SDL_DisplayFormat(tmpImage); + + // We also delete the alpha channel since + // it's not used. + delete [] alphaChannel; + alphaChannel = nullptr; + } + + if (!image) + { + logger->log1("Error: Image convert failed."); + delete [] alphaChannel; + return nullptr; + } + + if (converted) + SDL_FreeSurface(tmpImage); + + img = new Image(image, hasAlpha, alphaChannel); + img->mAlpha = alpha; + return img; +} + +SDL_Surface* ImageHelper::convertTo32Bit(SDL_Surface* tmpImage) +{ + if (!tmpImage) + return nullptr; + SDL_PixelFormat RGBAFormat; + RGBAFormat.palette = nullptr; + RGBAFormat.colorkey = 0; + RGBAFormat.alpha = 0; + RGBAFormat.BitsPerPixel = 32; + RGBAFormat.BytesPerPixel = 4; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + RGBAFormat.Rmask = 0xFF000000; + RGBAFormat.Rshift = 0; + RGBAFormat.Rloss = 0; + RGBAFormat.Gmask = 0x00FF0000; + RGBAFormat.Gshift = 8; + RGBAFormat.Gloss = 0; + RGBAFormat.Bmask = 0x0000FF00; + RGBAFormat.Bshift = 16; + RGBAFormat.Bloss = 0; + RGBAFormat.Amask = 0x000000FF; + RGBAFormat.Ashift = 24; + RGBAFormat.Aloss = 0; +#else + RGBAFormat.Rmask = 0x000000FF; + RGBAFormat.Rshift = 24; + RGBAFormat.Rloss = 0; + RGBAFormat.Gmask = 0x0000FF00; + RGBAFormat.Gshift = 16; + RGBAFormat.Gloss = 0; + RGBAFormat.Bmask = 0x00FF0000; + RGBAFormat.Bshift = 8; + RGBAFormat.Bloss = 0; + RGBAFormat.Amask = 0xFF000000; + RGBAFormat.Ashift = 0; + RGBAFormat.Aloss = 0; +#endif + return SDL_ConvertSurface(tmpImage, &RGBAFormat, SDL_SWSURFACE); +} + +SDL_Surface* ImageHelper::SDLDuplicateSurface(SDL_Surface* tmpImage) +{ + if (!tmpImage || !tmpImage->format) + return nullptr; + + return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); +} + +Image *ImageHelper::_SDLload(SDL_Surface *tmpImage) +{ + if (!tmpImage) + return nullptr; + + bool hasAlpha = false; + bool converted = false; + + if (tmpImage->format->BitsPerPixel != 32) + { + tmpImage = convertTo32Bit(tmpImage); + + if (!tmpImage) + return nullptr; + converted = true; + } + + const int sz = tmpImage->w * tmpImage->h; + + // The alpha channel to be filled with alpha values + Uint8 *alphaChannel = new Uint8[sz]; + + // Figure out whether the image uses its alpha layer + if (!tmpImage->format->palette) + { + const SDL_PixelFormat * const fmt = tmpImage->format; + if (fmt->Amask) + { + for (int i = 0; i < sz; ++ i) + { + unsigned v = ((static_cast<Uint32*>(tmpImage->pixels))[i] + & fmt->Amask) >> fmt->Ashift; + Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); + + if (a != 255) + hasAlpha = true; + + alphaChannel[i] = a; + } + } + else + { + if (SDL_ALPHA_OPAQUE != 255) + { + hasAlpha = true; + memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); + } + } + } + else + { + if (SDL_ALPHA_OPAQUE != 255) + { + hasAlpha = true; + memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); + } + } + + SDL_Surface *image; + + // Convert the surface to the current display format + if (hasAlpha) + { + image = SDL_DisplayFormatAlpha(tmpImage); + } + else + { + image = SDL_DisplayFormat(tmpImage); + + // We also delete the alpha channel since + // it's not used. + delete [] alphaChannel; + alphaChannel = nullptr; + } + + if (!image) + { + logger->log1("Error: Image convert failed."); + delete [] alphaChannel; + return nullptr; + } + + if (converted) + SDL_FreeSurface(tmpImage); + + return new Image(image, hasAlpha, alphaChannel); +} + +#ifdef USE_OPENGL +int ImageHelper::powerOfTwo(int input) +{ + int value; + if (mTextureType == GL_TEXTURE_2D) + { + value = 1; + while (value < input && value < mTextureSize) + value <<= 1; + } + else + { + value = input; + } + return value >= mTextureSize ? mTextureSize : value; +} + +Image *ImageHelper::_GLload(SDL_Surface *tmpImage) +{ + if (!tmpImage) + return nullptr; + + // Flush current error flag. + glGetError(); + + int width = tmpImage->w; + int height = tmpImage->h; + int realWidth = powerOfTwo(width); + int realHeight = powerOfTwo(height); + + if (realWidth < width || realHeight < height) + { + logger->log("Warning: image too large, cropping to %dx%d texture!", + tmpImage->w, tmpImage->h); + } + + // Make sure the alpha channel is not used, but copied to destination + SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); + + // Determine 32-bit masks based on byte order + Uint32 rmask, gmask, bmask, amask; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; +#else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0xff000000; +#endif + + SDL_Surface *oldImage = nullptr; + if (tmpImage->format->BitsPerPixel != 32 + || realWidth != width || realHeight != height + || rmask != tmpImage->format->Rmask + || gmask != tmpImage->format->Gmask + || amask != tmpImage->format->Amask) + { + oldImage = tmpImage; + tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, + 32, rmask, gmask, bmask, amask); + + if (!tmpImage) + { + logger->log("Error, image convert failed: out of memory"); + return nullptr; + } + SDL_BlitSurface(oldImage, nullptr, tmpImage, nullptr); + } + + GLuint texture; + glGenTextures(1, &texture); + if (mUseOpenGL == 1) + OpenGLGraphics::bindTexture(mTextureType, texture); + else if (mUseOpenGL == 2) + OpenGL1Graphics::bindTexture(mTextureType, texture); + + if (SDL_MUSTLOCK(tmpImage)) + SDL_LockSurface(tmpImage); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if (mBlur) + { + glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glTexImage2D(mTextureType, 0, mInternalTextureType, + tmpImage->w, tmpImage->h, + 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels); + +/* + GLint compressed; + glGetTexLevelParameteriv(mTextureType, 0, + GL_TEXTURE_COMPRESSED_ARB, &compressed); + if (compressed) + logger->log("image compressed"); + else + logger->log("image not compressed"); +*/ + +#ifdef DEBUG_OPENGL_LEAKS + textures_count ++; +#endif + + if (SDL_MUSTLOCK(tmpImage)) + SDL_UnlockSurface(tmpImage); + + if (oldImage) + SDL_FreeSurface(tmpImage); + + GLenum error = glGetError(); + if (error) + { + std::string errmsg = "Unknown error"; + switch (error) + { + case GL_INVALID_ENUM: + errmsg = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + errmsg = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + errmsg = "GL_INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + errmsg = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + errmsg = "GL_STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + errmsg = "GL_OUT_OF_MEMORY"; + break; + default: + break; + } + logger->log("Error: Image GL import failed: %s", errmsg.c_str()); + return nullptr; + } + + return new Image(texture, width, height, realWidth, realHeight); +} + +void ImageHelper::setLoadAsOpenGL(int useOpenGL) +{ + ImageHelper::mUseOpenGL = useOpenGL; +} + +#endif + +void ImageHelper::dumpSurfaceFormat(SDL_Surface *image) +{ + if (image->format) + { + const SDL_PixelFormat * const format = image->format; + logger->log("Bytes per pixel: %d", format->BytesPerPixel); + logger->log("Alpha: %d", format->alpha); + logger->log("Loss: %02x, %02x, %02x, %02x", (int)format->Rloss, + (int)format->Gloss, (int)format->Bloss, (int)format->Aloss); + logger->log("Shift: %02x, %02x, %02x, %02x", (int)format->Rshift, + (int)format->Gshift, (int)format->Bshift, (int)format->Ashift); + logger->log("Mask: %08x, %08x, %08x, %08x", format->Rmask, + format->Gmask, format->Bmask, format->Amask); + } +} + +int ImageHelper::useOpenGL() +{ +#ifdef USE_OPENGL + return mUseOpenGL; +#else + return 0; +#endif +} diff --git a/src/resources/imagehelper.h b/src/resources/imagehelper.h new file mode 100644 index 000000000..680794625 --- /dev/null +++ b/src/resources/imagehelper.h @@ -0,0 +1,170 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IMAGEHELPER_H +#define IMAGEHELPER_H + +#include "localconsts.h" +#include "main.h" + +#include "resources/resource.h" + +#include <SDL.h> + +#ifdef USE_OPENGL + +/* The definition of OpenGL extensions by SDL is giving problems with recent + * gl.h headers, since they also include these definitions. As we're not using + * extensions anyway it's safe to just disable the SDL version. + */ +//#define NO_SDL_GLEXT +#define GL_GLEXT_PROTOTYPES 1 + +#include <SDL_opengl.h> +#endif + +#include <map> + +class Dye; +class Image; + +struct Position; + +/** + * Defines a class for loading and storing images. + */ +class ImageHelper : public Resource +{ + friend class CompoundSprite; + friend class Graphics; + friend class Image; +#ifdef USE_OPENGL + friend class OpenGLGraphics; + friend class OpenGL1Graphics; +#endif + + public: + /** + * Loads an image from an SDL_RWops structure. + * + * @param rw The SDL_RWops to load the image from. + * + * @return <code>NULL</code> if an error occurred, a valid pointer + * otherwise. + */ + static Resource *load(SDL_RWops *rw); + + /** + * Loads an image from an SDL_RWops structure and recolors it. + * + * @param rw The SDL_RWops to load the image from. + * @param dye The dye used to recolor the image. + * + * @return <code>NULL</code> if an error occurred, a valid pointer + * otherwise. + */ + static Resource *load(SDL_RWops *rw, Dye const &dye); + + /** + * Loads an image from an SDL surface. + */ + static Image *load(SDL_Surface *); + + static SDL_Surface *convertTo32Bit(SDL_Surface* tmpImage); + + static Image *createTextSurface(SDL_Surface *tmpImage, float alpha); + + static void SDLSetEnableAlphaCache(bool n) + { mEnableAlphaCache = n; } + + static bool SDLGetEnableAlphaCache() + { return mEnableAlphaCache; } + + static void setEnableAlpha(bool n) + { mEnableAlpha = n; } + +#ifdef USE_OPENGL + + // OpenGL only public functions + + /** + * Sets the target image format. Use <code>false</code> for SDL and + * <code>true</code> for OpenGL. + */ + static void setLoadAsOpenGL(int useOpenGL); + + static int getLoadAsOpenGL() + { return mUseOpenGL; } + + static int getTextureType() + { return mTextureType; } + + static int getInternalTextureType() + { return mInternalTextureType; } + + static void setInternalTextureType(int n) + { mInternalTextureType = n; } + + static void setBlur(bool n) + { mBlur = n; } + + static int mTextureType; + + static int mInternalTextureType; + + static void dumpSurfaceFormat(SDL_Surface *image); + + static SDL_Surface* SDLDuplicateSurface(SDL_Surface* tmpImage); + +#endif + + /** + * Tells if the image was loaded using OpenGL or SDL + * @return true if OpenGL, false if SDL. + */ + static int useOpenGL(); + + protected: + /** SDL_Surface to SDL_Surface Image loader */ + static Image *_SDLload(SDL_Surface *tmpImage); + + static bool mEnableAlphaCache; + static bool mEnableAlpha; + + // ----------------------- + // OpenGL protected members + // ----------------------- +#ifdef USE_OPENGL + /** + * Returns the first power of two equal or bigger than the input. + */ + static int powerOfTwo(int input); + + static Image *_GLload(SDL_Surface *tmpImage); + + static int mUseOpenGL; + static int mTextureSize; + static bool mBlur; +#endif +}; + +#endif diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 12ad310ed..62a604ebe 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -29,6 +29,7 @@ #include "resources/dye.h" #include "resources/image.h" +#include "resources/imagehelper.h" #include "resources/imageset.h" #include "resources/music.h" #include "resources/soundeffect.h" @@ -456,8 +457,8 @@ struct DyedImageLoader delete d; return nullptr; } - Resource *res = d ? Image::load(rw, *d) - : Image::load(rw); + Resource *res = d ? ImageHelper::load(rw, *d) + : ImageHelper::load(rw); delete d; return res; } |