From e1a563612fefd8bf714e61050f0b09e67a533191 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 17 Mar 2017 10:14:46 +0800 Subject: [PATCH] Avoid calling gamma correction on non-srgb png --- lib/irrlicht/include/IImageLoader.h | 2 +- .../source/Irrlicht/CImageLoaderBMP.cpp | 2 +- .../source/Irrlicht/CImageLoaderBMP.h | 2 +- .../source/Irrlicht/CImageLoaderJPG.cpp | 2 +- .../source/Irrlicht/CImageLoaderJPG.h | 2 +- .../source/Irrlicht/CImageLoaderPNG.cpp | 24 ++++++++++--------- .../source/Irrlicht/CImageLoaderPNG.h | 2 +- src/graphics/hq_mipmap_generator.cpp | 21 ++++++++++++---- src/graphics/stk_tex_manager.cpp | 4 ++-- src/graphics/stk_texture.cpp | 19 +++++++++++++-- src/graphics/stk_texture.hpp | 2 ++ 11 files changed, 57 insertions(+), 25 deletions(-) diff --git a/lib/irrlicht/include/IImageLoader.h b/lib/irrlicht/include/IImageLoader.h index ba0da6886..40872a132 100644 --- a/lib/irrlicht/include/IImageLoader.h +++ b/lib/irrlicht/include/IImageLoader.h @@ -42,7 +42,7 @@ public: //! Creates a surface from the file /** \param file File handle to check. \return Pointer to newly created image, or 0 upon error. */ - virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const = 0; + virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false, bool gamma_correction = true) const = 0; virtual core::dimension2du getImageSize(io::IReadFile* file) const { return core::dimension2du(0, 0); } virtual bool supportThreadedLoading() const { return false; } }; diff --git a/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.cpp b/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.cpp index 7bed41196..2b7e2a838 100644 --- a/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.cpp +++ b/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.cpp @@ -216,7 +216,7 @@ void CImageLoaderBMP::decompress4BitRLE(u8*& bmpData, s32 size, s32 width, s32 h //! creates a surface from the file -IImage* CImageLoaderBMP::loadImage(io::IReadFile* file, bool skip_checking) const +IImage* CImageLoaderBMP::loadImage(io::IReadFile* file, bool skip_checking, bool gamma_correction) const { SBMPHeader header; diff --git a/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.h b/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.h index c5708dcc5..a6275913a 100644 --- a/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.h +++ b/lib/irrlicht/source/Irrlicht/CImageLoaderBMP.h @@ -81,7 +81,7 @@ public: virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file - virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const; + virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false, bool gamma_correction = true) const; private: diff --git a/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.cpp b/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.cpp index f9e77dff0..958adc8a7 100644 --- a/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.cpp +++ b/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.cpp @@ -135,7 +135,7 @@ bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const } //! creates a surface from the file -IImage* CImageLoaderJPG::loadImage(io::IReadFile* file, bool skip_checking) const +IImage* CImageLoaderJPG::loadImage(io::IReadFile* file, bool skip_checking, bool gamma_correction) const { #ifndef _IRR_COMPILE_WITH_LIBJPEG_ os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG); diff --git a/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.h b/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.h index d15c06dbe..e548635ae 100644 --- a/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.h +++ b/lib/irrlicht/source/Irrlicht/CImageLoaderJPG.h @@ -49,7 +49,7 @@ public: virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file - virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const; + virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false, bool gamma_correction = true) const; private: diff --git a/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.cpp b/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.cpp index bb957abc9..e14ac78a2 100644 --- a/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.cpp +++ b/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.cpp @@ -86,7 +86,7 @@ bool CImageLoaderPng::isALoadableFileFormat(io::IReadFile* file) const // load in the image data -IImage* CImageLoaderPng::loadImage(io::IReadFile* file, bool skip_checking) const +IImage* CImageLoaderPng::loadImage(io::IReadFile* file, bool skip_checking, bool gamma_correction) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file) @@ -174,18 +174,20 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file, bool skip_checking) cons if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); - int intent; - const double screen_gamma = 2.2; - - if (png_get_sRGB(png_ptr, info_ptr, &intent)) - png_set_gamma(png_ptr, screen_gamma, 0.45455); - else + if (gamma_correction) { - double image_gamma; - if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) - png_set_gamma(png_ptr, screen_gamma, image_gamma); - else + int intent; + const double screen_gamma = 2.2; + if (png_get_sRGB(png_ptr, info_ptr, &intent)) png_set_gamma(png_ptr, screen_gamma, 0.45455); + else + { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) + png_set_gamma(png_ptr, screen_gamma, image_gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + } } // Update the changes in between, as we need to get the new color type diff --git a/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.h b/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.h index 789cfdd18..f2e5ff7ca 100644 --- a/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.h +++ b/lib/irrlicht/source/Irrlicht/CImageLoaderPNG.h @@ -33,7 +33,7 @@ public: virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file - virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false) const; + virtual IImage* loadImage(io::IReadFile* file, bool skip_checking = false, bool gamma_correction = true) const; virtual core::dimension2du getImageSize(io::IReadFile* file) const; virtual bool supportThreadedLoading() const { return true; } }; diff --git a/src/graphics/hq_mipmap_generator.cpp b/src/graphics/hq_mipmap_generator.cpp index 228f7a0e8..d710c4981 100644 --- a/src/graphics/hq_mipmap_generator.cpp +++ b/src/graphics/hq_mipmap_generator.cpp @@ -19,7 +19,7 @@ #include "graphics/hq_mipmap_generator.hpp" #include "graphics/stk_tex_manager.hpp" -#undef DUMP_MIPMAP +#define DUMP_MIPMAP #ifdef DUMP_MIPMAP #include "graphics/irr_driver.hpp" #include "utils/string_utils.hpp" @@ -75,13 +75,26 @@ void HQMipmapGenerator::threadedReload(void* ptr, void* param) const #endif for (unsigned int i = 0; i < m_mipmap_sizes.size(); i++) { + const unsigned size = m_mipmap_sizes[i].first.getArea() * 4; memcpy((uint8_t*)ptr + m_mipmap_sizes[i].second, - mm_cascade->mipmap[i + 1], - m_mipmap_sizes[i].first.getArea() * 4); + mm_cascade->mipmap[i + 1], size); #ifdef DUMP_MIPMAP + uint8_t* data = (uint8_t*)(mm_cascade->mipmap[i + 1]); + if (!m_tex_config->m_srgb) + { + for (unsigned int j = 0; j < size / 4; j++) + { + data[j * 4] = + (uint8_t)(powf(data[j * 4] / 255.f , 2.2f) * 255); + data[j * 4 + 1] = + (uint8_t)(powf(data[j * 4 + 1] / 255.f , 2.2f) * 255); + data[j * 4 + 2] = + (uint8_t)(powf(data[j * 4 + 2] / 255.f , 2.2f) * 255); + } + } video::IImage* image = irr_driver->getVideoDriver() ->createImageFromData(video::ECF_A8R8G8B8, m_mipmap_sizes[i].first, - mm_cascade->mipmap[i + 1], false/*ownForeignMemory*/); + data, false/*ownForeignMemory*/); irr_driver->getVideoDriver()->writeImageToFile(image, std::string (StringUtils::toString(i) + "_" + StringUtils::getBasename(NamedPath.getPtr())).c_str()); diff --git a/src/graphics/stk_tex_manager.cpp b/src/graphics/stk_tex_manager.cpp index 80fbb81d6..279638d9c 100644 --- a/src/graphics/stk_tex_manager.cpp +++ b/src/graphics/stk_tex_manager.cpp @@ -105,12 +105,12 @@ void STKTexManager::destroyThreadedTexLoaders() } delete delete_ttl; glDeleteBuffers(1, &m_pbo); + pthread_mutex_destroy(&m_threaded_load_textures_mutex); + pthread_cond_destroy(&m_cond_request); m_pbo = 0; m_thread_size = 0; m_threaded_load_textures_counter = 0; m_all_tex_loaders.clear(); - pthread_mutex_destroy(&m_threaded_load_textures_mutex); - pthread_cond_destroy(&m_cond_request); } #endif } // destroyThreadedTexLoaders diff --git a/src/graphics/stk_texture.cpp b/src/graphics/stk_texture.cpp index 3a6a078f7..6b15f4e98 100644 --- a/src/graphics/stk_texture.cpp +++ b/src/graphics/stk_texture.cpp @@ -187,7 +187,8 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data, } else { - orig_img = m_img_loader->loadImage(m_file); + orig_img = m_img_loader->loadImage(m_file, + false/*skip_checking*/, handleGamma()); m_file->drop(); m_file = NULL; if (orig_img == NULL || orig_img->getDimension().Width == 0 || @@ -597,7 +598,7 @@ void STKTexture::threadedReload(void* ptr, void* param) const { #if !(defined(SERVER_ONLY) || defined(USE_GLES2)) video::IImage* orig_img = - m_img_loader->loadImage(m_file, true/*skip_checking*/); + m_img_loader->loadImage(m_file, true/*skip_checking*/, handleGamma()); orig_img = resizeImage(orig_img); uint8_t* data = (uint8_t*)orig_img->lock(); if (m_single_channel) @@ -677,3 +678,17 @@ bool STKTexture::isMeshTexture() const { return m_tex_config && m_tex_config->m_mesh_tex; } // isMeshTexture + +//----------------------------------------------------------------------------- +bool STKTexture::handleGamma() const +{ +#ifndef SERVER_ONLY + if (!CVS->isGLSL() || !m_tex_config) +#endif + return true; + + if ((m_tex_config->m_mesh_tex && m_tex_config->m_srgb) || + (!m_tex_config->m_mesh_tex && !m_tex_config->m_srgb)) + return true; + return false; +} // handleGamma diff --git a/src/graphics/stk_texture.hpp b/src/graphics/stk_texture.hpp index 3eb09c0b2..52f3dfb8b 100644 --- a/src/graphics/stk_texture.hpp +++ b/src/graphics/stk_texture.hpp @@ -85,6 +85,8 @@ private: bool isSrgb() const; // ------------------------------------------------------------------------ bool isPremulAlpha() const; + // ------------------------------------------------------------------------ + bool handleGamma() const; public: // ------------------------------------------------------------------------