From 5162e7162e5c7d520af5c0a551445e9d44bafb3f Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Wed, 6 Dec 2017 10:59:20 +0200 Subject: [PATCH] Fixed overbright screenshots with hardware gamma off When render buffers are used to apply gamma/brightness/contrast screenshots should not use PNG gamma correction --- src/gl/scene/gl_scene.cpp | 2 +- src/gl/system/gl_framebuffer.cpp | 6 +++++- src/gl/system/gl_framebuffer.h | 2 +- src/gl/system/gl_swframebuffer.cpp | 7 ++++--- src/gl/system/gl_swframebuffer.h | 2 +- src/m_misc.cpp | 9 +++++---- src/m_png.cpp | 4 ++-- src/m_png.h | 2 +- src/swrenderer/r_swrenderer.cpp | 4 ++-- src/v_video.cpp | 3 ++- src/v_video.h | 2 +- src/win32/fb_d3d9.cpp | 5 +++-- src/win32/win32swiface.h | 2 +- 13 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index af03af86e..bbead7737 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -969,7 +969,7 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, uint8_t * scr = (uint8_t *)M_Malloc(width * height * 3); glReadPixels(0,0,width, height,GL_RGB,GL_UNSIGNED_BYTE,scr); - M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width*3); + M_CreatePNG (file, scr + ((height-1) * width * 3), NULL, SS_RGB, width, height, -width * 3, Gamma); M_Free(scr); } diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index b10b8b418..7425271be 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -487,7 +487,7 @@ void OpenGLFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int // //=========================================================================== -void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) +void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) { const auto &viewport = GLRenderer->mOutputLetterbox; @@ -527,6 +527,10 @@ void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, pitch = -w*3; color_type = SS_RGB; buffer = ScreenshotBuffer + w * 3 * (h - 1); + + // Screenshot should not use gamma correction if it was already applied to rendered image + EXTERN_CVAR(Bool, fullscreen); + gamma = 1 == vid_hwgamma || (2 == vid_hwgamma && !fullscreen) ? 1.0f : Gamma; } //=========================================================================== diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 1d85562b3..0c7c922aa 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -51,7 +51,7 @@ public: // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer // points to the last row in the buffer, which will be the first row output. - virtual void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type); + virtual void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) override; // Releases the screenshot buffer. virtual void ReleaseScreenshotBuffer(); diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 85bddf8c6..4ea5bfc0b 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -1671,15 +1671,15 @@ void OpenGLSWFrameBuffer::SetBlendingRect(int x1, int y1, int x2, int y2) // //========================================================================== -void OpenGLSWFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) +void OpenGLSWFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) { - Super::GetScreenshotBuffer(buffer, pitch, color_type); + Super::GetScreenshotBuffer(buffer, pitch, color_type, gamma); /* LockedRect lrect; if (!Accel2D) { - Super::GetScreenshotBuffer(buffer, pitch, color_type); + Super::GetScreenshotBuffer(buffer, pitch, color_type, gamma); return; } buffer = nullptr; @@ -1702,6 +1702,7 @@ void OpenGLSWFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch buffer = (const uint8_t *)lrect.pBits; pitch = lrect.Pitch; color_type = SS_BGRA; + gamma = Gamma; } } */ diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index e29ff40ba..8c45b17af 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -44,7 +44,7 @@ public: int GetPageCount() override; void SetVSync(bool vsync) override; void NewRefreshRate() override; - void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) override; + void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) override; void ReleaseScreenshotBuffer() override; void SetBlendingRect(int x1, int y1, int x2, int y2) override; bool Begin2D(bool copy3d) override; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index c2fa021f6..8fcaf9e0c 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -521,11 +521,11 @@ void WritePCXfile (FileWriter *file, const uint8_t *buffer, const PalEntry *pale // WritePNGfile // void WritePNGfile (FileWriter *file, const uint8_t *buffer, const PalEntry *palette, - ESSType color_type, int width, int height, int pitch) + ESSType color_type, int width, int height, int pitch, float gamma) { char software[100]; mysnprintf(software, countof(software), GAMENAME " %s", GetVersionString()); - if (!M_CreatePNG (file, buffer, palette, color_type, width, height, pitch) || + if (!M_CreatePNG (file, buffer, palette, color_type, width, height, pitch, gamma) || !M_AppendPNGText (file, "Software", software) || !M_FinishPNG (file)) { @@ -626,8 +626,9 @@ void M_ScreenShot (const char *filename) const uint8_t *buffer; int pitch; ESSType color_type; + float gamma; - screen->GetScreenshotBuffer(buffer, pitch, color_type); + screen->GetScreenshotBuffer(buffer, pitch, color_type, gamma); if (buffer != NULL) { PalEntry palette[256]; @@ -651,7 +652,7 @@ void M_ScreenShot (const char *filename) else { WritePNGfile(file, buffer, palette, color_type, - screen->GetWidth(), screen->GetHeight(), pitch); + screen->GetWidth(), screen->GetHeight(), pitch, gamma); } delete file; screen->ReleaseScreenshotBuffer(); diff --git a/src/m_png.cpp b/src/m_png.cpp index 08cac8d54..a7f82ed8f 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -132,7 +132,7 @@ CVAR(Float, png_gamma, 0.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) //========================================================================== bool M_CreatePNG (FileWriter *file, const uint8_t *buffer, const PalEntry *palette, - ESSType color_type, int width, int height, int pitch) + ESSType color_type, int width, int height, int pitch, float gamma) { uint8_t work[8 + // signature 12+2*4+5 + // IHDR @@ -157,7 +157,7 @@ bool M_CreatePNG (FileWriter *file, const uint8_t *buffer, const PalEntry *palet MakeChunk (ihdr, MAKE_ID('I','H','D','R'), 2*4+5); // Assume a display exponent of 2.2 (100000/2.2 ~= 45454.5) - *gama = BigLong (int (45454.5f * (png_gamma == 0.f ? Gamma : png_gamma))); + *gama = BigLong (int (45454.5f * (png_gamma == 0.f ? gamma : png_gamma))); MakeChunk (gama, MAKE_ID('g','A','M','A'), 4); if (color_type == SS_PAL) diff --git a/src/m_png.h b/src/m_png.h index 4182440fb..7bc9b474f 100644 --- a/src/m_png.h +++ b/src/m_png.h @@ -46,7 +46,7 @@ class FileWriter; // This function writes the PNG signature and the IHDR, gAMA, PLTE, and IDAT // chunks. bool M_CreatePNG (FileWriter *file, const uint8_t *buffer, const PalEntry *pal, - ESSType color_type, int width, int height, int pitch); + ESSType color_type, int width, int height, int pitch, float gamma); // Creates a grayscale 1x1 PNG file. Used for savegames without savepics. bool M_CreateDummyPNG (FileWriter *file); diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 19bf055a6..3c18e6218 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -225,7 +225,7 @@ void FSoftwareRenderer::WriteSavePic (player_t *player, FileWriter *file, int wi r_viewwindow = mScene.MainThread()->Viewport->viewwindow; } screen->GetFlashedPalette (palette); - M_CreatePNG (file, pic->GetBuffer(), palette, SS_PAL, width, height, pic->GetPitch()); + M_CreatePNG (file, pic->GetBuffer(), palette, SS_PAL, width, height, pic->GetPitch(), Gamma); pic->Unlock (); delete pic; } @@ -399,4 +399,4 @@ uint32_t FSoftwareRenderer::GetCaps() FlagSet |= RFF_COLORMAP; return (uint32_t)FlagSet; -} \ No newline at end of file +} diff --git a/src/v_video.cpp b/src/v_video.cpp index 814dc4615..ca2e8b62a 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -329,12 +329,13 @@ void DCanvas::Dim (PalEntry color) // //========================================================================== -void DCanvas::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) +void DCanvas::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) { Lock(true); buffer = GetBuffer(); pitch = IsBgra() ? GetPitch() * 4 : GetPitch(); color_type = IsBgra() ? SS_BGRA : SS_PAL; + gamma = Gamma; } //========================================================================== diff --git a/src/v_video.h b/src/v_video.h index 1cbf565af..1d7abd581 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -256,7 +256,7 @@ public: // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer // points to the last row in the buffer, which will be the first row output. - virtual void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type); + virtual void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma); // Releases the screenshot buffer. virtual void ReleaseScreenshotBuffer(); diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index ff05faca9..fe033946b 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1755,13 +1755,13 @@ void D3DFB::SetBlendingRect(int x1, int y1, int x2, int y2) // //========================================================================== -void D3DFB::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) +void D3DFB::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) { D3DLOCKED_RECT lrect; if (!Accel2D) { - Super::GetScreenshotBuffer(buffer, pitch, color_type); + Super::GetScreenshotBuffer(buffer, pitch, color_type, gamma); return; } buffer = NULL; @@ -1784,6 +1784,7 @@ void D3DFB::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &col buffer = (const uint8_t *)lrect.pBits; pitch = lrect.Pitch; color_type = SS_BGRA; + gamma = Gamma; } } } diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index 657b120a3..d2cea2024 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -124,7 +124,7 @@ public: bool PaintToWindow (); void SetVSync (bool vsync); void NewRefreshRate(); - void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type); + void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type, float &gamma) override; void ReleaseScreenshotBuffer(); void SetBlendingRect (int x1, int y1, int x2, int y2); bool Begin2D (bool copy3d);