mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-14 03:58:18 +00:00
Warn about pnglite-incompatible PNGs on load
This allows a larger range of PNGs to be loaded while still maintaining backward compatibility with older clients by annoying the user. This warning can be enabled by the `warn-pnglite-incompatible-images` key in the https://info2.ddnet.tw/info JSON, if the key is not there or the JSON hasn't been obtained yet, the warning is disabled. Since the JSON is cached across restarts, it'll be effective for initially loaded images from the second start.
This commit is contained in:
parent
4292c9ed77
commit
994324b059
|
@ -2501,6 +2501,8 @@ void CClient::LoadDDNetInfo()
|
||||||
log_debug("info", "got global tcp ip address: %s", (const char *)ConnectingIp);
|
log_debug("info", "got global tcp ip address: %s", (const char *)ConnectingIp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const json_value &WarnPngliteIncompatibleImages = DDNetInfo["warn-pnglite-incompatible-images"];
|
||||||
|
Graphics()->WarnPngliteIncompatibleImages(WarnPngliteIncompatibleImages.type == json_boolean && (bool)WarnPngliteIncompatibleImages);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CClient::ConnectNetTypes() const
|
int CClient::ConnectNetTypes() const
|
||||||
|
@ -3125,6 +3127,10 @@ void CClient::Run()
|
||||||
m_pEditor->Save(arg);
|
m_pEditor->Save(arg);
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
|
m_ServerBrowser.OnInit();
|
||||||
|
// loads the existing ddnet info file if it exists
|
||||||
|
LoadDDNetInfo();
|
||||||
|
|
||||||
// load data
|
// load data
|
||||||
if(!LoadData())
|
if(!LoadData())
|
||||||
return;
|
return;
|
||||||
|
@ -3135,7 +3141,6 @@ void CClient::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
GameClient()->OnInit();
|
GameClient()->OnInit();
|
||||||
m_ServerBrowser.OnInit();
|
|
||||||
|
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", "version " GAME_RELEASE_VERSION " on " CONF_PLATFORM_STRING " " CONF_ARCH_STRING, ColorRGBA(0.7f, 0.7f, 1, 1.0f));
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", "version " GAME_RELEASE_VERSION " on " CONF_PLATFORM_STRING " " CONF_ARCH_STRING, ColorRGBA(0.7f, 0.7f, 1, 1.0f));
|
||||||
if(GIT_SHORTREV_HASH)
|
if(GIT_SHORTREV_HASH)
|
||||||
|
@ -3168,9 +3173,7 @@ void CClient::Run()
|
||||||
InitChecksum();
|
InitChecksum();
|
||||||
m_pConsole->InitChecksum(ChecksumData());
|
m_pConsole->InitChecksum(ChecksumData());
|
||||||
|
|
||||||
// loads the existing ddnet info file if it exists
|
// request the new ddnet info from server if already past the welcome dialog
|
||||||
LoadDDNetInfo();
|
|
||||||
// but still request the new one from server
|
|
||||||
if(g_Config.m_ClShowWelcome)
|
if(g_Config.m_ClShowWelcome)
|
||||||
g_Config.m_ClShowWelcome = 0;
|
g_Config.m_ClShowWelcome = 0;
|
||||||
else
|
else
|
||||||
|
|
|
@ -640,7 +640,8 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
|
||||||
|
|
||||||
uint8_t *pImgBuffer = NULL;
|
uint8_t *pImgBuffer = NULL;
|
||||||
EImageFormat ImageFormat;
|
EImageFormat ImageFormat;
|
||||||
if(::LoadPNG(ImageByteBuffer, pFilename, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
int PngliteIncompatible;
|
||||||
|
if(::LoadPNG(ImageByteBuffer, pFilename, PngliteIncompatible, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
||||||
{
|
{
|
||||||
pImg->m_pData = pImgBuffer;
|
pImg->m_pData = pImgBuffer;
|
||||||
|
|
||||||
|
@ -653,6 +654,30 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
|
||||||
free(pImgBuffer);
|
free(pImgBuffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_WarnPngliteIncompatibleImages && PngliteIncompatible != 0)
|
||||||
|
{
|
||||||
|
SWarning Warning;
|
||||||
|
str_format(Warning.m_aWarningMsg, sizeof(Warning.m_aWarningMsg), Localize("\"%s\" is not compatible with pnglite and cannot be loaded by old DDNet versions: "), pFilename);
|
||||||
|
static const int FLAGS[] = {PNGLITE_COLOR_TYPE, PNGLITE_BIT_DEPTH, PNGLITE_INTERLACE_TYPE, PNGLITE_COMPRESSION_TYPE, PNGLITE_FILTER_TYPE};
|
||||||
|
static const char *EXPLANATION[] = {"color type", "bit depth", "interlace type", "compression type", "filter type"};
|
||||||
|
|
||||||
|
bool First = true;
|
||||||
|
for(int i = 0; i < (int)std::size(FLAGS); i++)
|
||||||
|
{
|
||||||
|
if((PngliteIncompatible & FLAGS[i]) != 0)
|
||||||
|
{
|
||||||
|
if(!First)
|
||||||
|
{
|
||||||
|
str_append(Warning.m_aWarningMsg, ", ", sizeof(Warning.m_aWarningMsg));
|
||||||
|
}
|
||||||
|
str_append(Warning.m_aWarningMsg, EXPLANATION[i], sizeof(Warning.m_aWarningMsg));
|
||||||
|
First = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str_append(Warning.m_aWarningMsg, Localize(" unsupported"), sizeof(Warning.m_aWarningMsg));
|
||||||
|
m_vWarnings.emplace_back(Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2513,6 +2538,11 @@ void CGraphics_Threaded::Maximize()
|
||||||
m_pBackend->Maximize();
|
m_pBackend->Maximize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGraphics_Threaded::WarnPngliteIncompatibleImages(bool Warn)
|
||||||
|
{
|
||||||
|
m_WarnPngliteIncompatibleImages = Warn;
|
||||||
|
}
|
||||||
|
|
||||||
void CGraphics_Threaded::SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing)
|
void CGraphics_Threaded::SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing)
|
||||||
{
|
{
|
||||||
m_pBackend->SetWindowParams(FullscreenMode, IsBorderless, AllowResizing);
|
m_pBackend->SetWindowParams(FullscreenMode, IsBorderless, AllowResizing);
|
||||||
|
|
|
@ -824,6 +824,8 @@ class CGraphics_Threaded : public IEngineGraphics
|
||||||
|
|
||||||
std::vector<uint8_t> m_vSpriteHelper;
|
std::vector<uint8_t> m_vSpriteHelper;
|
||||||
|
|
||||||
|
bool m_WarnPngliteIncompatibleImages = false;
|
||||||
|
|
||||||
std::vector<SWarning> m_vWarnings;
|
std::vector<SWarning> m_vWarnings;
|
||||||
|
|
||||||
// is a non full windowed (in a sense that the viewport won't include the whole window),
|
// is a non full windowed (in a sense that the viewport won't include the whole window),
|
||||||
|
@ -1249,6 +1251,7 @@ public:
|
||||||
int GetNumScreens() const override;
|
int GetNumScreens() const override;
|
||||||
void Minimize() override;
|
void Minimize() override;
|
||||||
void Maximize() override;
|
void Maximize() override;
|
||||||
|
void WarnPngliteIncompatibleImages(bool Warn) override;
|
||||||
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override;
|
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override;
|
||||||
bool SetWindowScreen(int Index) override;
|
bool SetWindowScreen(int Index) override;
|
||||||
void Move(int x, int y) override;
|
void Move(int x, int y) override;
|
||||||
|
|
|
@ -79,12 +79,12 @@ static void LibPNGDeleteReadStruct(png_structp pPNGStruct, png_infop pPNGInfo)
|
||||||
png_destroy_read_struct(&pPNGStruct, NULL, NULL);
|
png_destroy_read_struct(&pPNGStruct, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsUnsupportedByPnglite(png_structp pPNGStruct, png_infop pPNGInfo)
|
static int PngliteIncompatibility(png_structp pPNGStruct, png_infop pPNGInfo)
|
||||||
{
|
{
|
||||||
int ColorType = png_get_color_type(pPNGStruct, pPNGInfo);
|
int ColorType = png_get_color_type(pPNGStruct, pPNGInfo);
|
||||||
int BitDepth = png_get_bit_depth(pPNGStruct, pPNGInfo);
|
int BitDepth = png_get_bit_depth(pPNGStruct, pPNGInfo);
|
||||||
int InterlaceType = png_get_interlace_type(pPNGStruct, pPNGInfo);
|
int InterlaceType = png_get_interlace_type(pPNGStruct, pPNGInfo);
|
||||||
bool Unsupported = false;
|
int Result = 0;
|
||||||
switch(ColorType)
|
switch(ColorType)
|
||||||
{
|
{
|
||||||
case PNG_COLOR_TYPE_GRAY:
|
case PNG_COLOR_TYPE_GRAY:
|
||||||
|
@ -93,8 +93,8 @@ static bool IsUnsupportedByPnglite(png_structp pPNGStruct, png_infop pPNGInfo)
|
||||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_error("png", "color type %d unsupported by pnglite", ColorType);
|
log_debug("png", "color type %d unsupported by pnglite", ColorType);
|
||||||
Unsupported = true;
|
Result |= PNGLITE_COLOR_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(BitDepth)
|
switch(BitDepth)
|
||||||
|
@ -103,33 +103,29 @@ static bool IsUnsupportedByPnglite(png_structp pPNGStruct, png_infop pPNGInfo)
|
||||||
case 16:
|
case 16:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_error("png", "bit depth %d unsupported by pnglite", BitDepth);
|
log_debug("png", "bit depth %d unsupported by pnglite", BitDepth);
|
||||||
Unsupported = true;
|
Result |= PNGLITE_BIT_DEPTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(InterlaceType)
|
if(InterlaceType != PNG_INTERLACE_NONE)
|
||||||
{
|
{
|
||||||
case PNG_INTERLACE_NONE:
|
log_debug("png", "interlace type %d unsupported by pnglite", InterlaceType);
|
||||||
break;
|
Result |= PNGLITE_INTERLACE_TYPE;
|
||||||
default:
|
|
||||||
log_error("png", "interlace type %d unsupported by pnglite", InterlaceType);
|
|
||||||
Unsupported = true;
|
|
||||||
}
|
}
|
||||||
|
if(png_get_compression_type(pPNGStruct, pPNGInfo) != PNG_COMPRESSION_TYPE_BASE)
|
||||||
if(png_get_compression_type(pPNGStruct, pPNGInfo) != PNG_COMPRESSION_TYPE_BASE || png_get_filter_type(pPNGStruct, pPNGInfo) != PNG_FILTER_TYPE_BASE)
|
|
||||||
{
|
{
|
||||||
log_error("png", "non-default compression type or non-default filter type unsupported by pnglite");
|
log_debug("png", "non-default compression type unsupported by pnglite");
|
||||||
Unsupported = true;
|
Result |= PNGLITE_COMPRESSION_TYPE;
|
||||||
}
|
}
|
||||||
|
if(png_get_filter_type(pPNGStruct, pPNGInfo) != PNG_FILTER_TYPE_BASE)
|
||||||
if(Unsupported)
|
|
||||||
{
|
{
|
||||||
log_error("png", "refusing to load PNG because it would be unsupported by pnglite");
|
log_debug("png", "non-default filter type unsupported by pnglite");
|
||||||
|
Result |= PNGLITE_FILTER_TYPE;
|
||||||
}
|
}
|
||||||
return Unsupported;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &Width, int &Height, uint8_t *&pImageBuff, EImageFormat &ImageFormat)
|
bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &PngliteIncompatible, int &Width, int &Height, uint8_t *&pImageBuff, EImageFormat &ImageFormat)
|
||||||
{
|
{
|
||||||
png_structp pPNGStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
png_structp pPNGStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
@ -175,8 +171,9 @@ bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &Width, in
|
||||||
Height = png_get_image_height(pPNGStruct, pPNGInfo);
|
Height = png_get_image_height(pPNGStruct, pPNGInfo);
|
||||||
int ColorType = png_get_color_type(pPNGStruct, pPNGInfo);
|
int ColorType = png_get_color_type(pPNGStruct, pPNGInfo);
|
||||||
png_byte BitDepth = png_get_bit_depth(pPNGStruct, pPNGInfo);
|
png_byte BitDepth = png_get_bit_depth(pPNGStruct, pPNGInfo);
|
||||||
|
PngliteIncompatible = PngliteIncompatibility(pPNGStruct, pPNGInfo);
|
||||||
|
|
||||||
bool PNGErr = IsUnsupportedByPnglite(pPNGStruct, pPNGInfo);
|
bool PNGErr = false;
|
||||||
|
|
||||||
if(BitDepth == 16)
|
if(BitDepth == 16)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,16 @@ struct SImageByteBuffer
|
||||||
int m_Err;
|
int m_Err;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &Width, int &Height, uint8_t *&pImageBuff, EImageFormat &ImageFormat);
|
enum
|
||||||
|
{
|
||||||
|
PNGLITE_COLOR_TYPE = 1 << 0,
|
||||||
|
PNGLITE_BIT_DEPTH = 1 << 1,
|
||||||
|
PNGLITE_INTERLACE_TYPE = 1 << 2,
|
||||||
|
PNGLITE_COMPRESSION_TYPE = 1 << 3,
|
||||||
|
PNGLITE_FILTER_TYPE = 1 << 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &PngliteIncompatible, int &Width, int &Height, uint8_t *&pImageBuff, EImageFormat &ImageFormat);
|
||||||
bool SavePNG(EImageFormat ImageFormat, const uint8_t *pRawBuffer, SImageByteBuffer &WrittenBytes, int Width, int Height);
|
bool SavePNG(EImageFormat ImageFormat, const uint8_t *pRawBuffer, SImageByteBuffer &WrittenBytes, int Width, int Height);
|
||||||
|
|
||||||
#endif // ENGINE_GFX_IMAGE_LOADER_H
|
#endif // ENGINE_GFX_IMAGE_LOADER_H
|
||||||
|
|
|
@ -251,6 +251,7 @@ public:
|
||||||
int WindowWidth() const { return m_ScreenWidth / m_ScreenHiDPIScale; }
|
int WindowWidth() const { return m_ScreenWidth / m_ScreenHiDPIScale; }
|
||||||
int WindowHeight() const { return m_ScreenHeight / m_ScreenHiDPIScale; }
|
int WindowHeight() const { return m_ScreenHeight / m_ScreenHiDPIScale; }
|
||||||
|
|
||||||
|
virtual void WarnPngliteIncompatibleImages(bool Warn) = 0;
|
||||||
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
|
virtual void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) = 0;
|
||||||
virtual bool SetWindowScreen(int Index) = 0;
|
virtual bool SetWindowScreen(int Index) = 0;
|
||||||
virtual bool SetVSync(bool State) = 0;
|
virtual bool SetVSync(bool State) = 0;
|
||||||
|
|
|
@ -26,7 +26,8 @@ int DilateFile(const char *pFilename)
|
||||||
|
|
||||||
uint8_t *pImgBuffer = NULL;
|
uint8_t *pImgBuffer = NULL;
|
||||||
EImageFormat ImageFormat;
|
EImageFormat ImageFormat;
|
||||||
if(LoadPNG(ImageByteBuffer, pFilename, Img.m_Width, Img.m_Height, pImgBuffer, ImageFormat))
|
int PngliteIncompatible;
|
||||||
|
if(LoadPNG(ImageByteBuffer, pFilename, PngliteIncompatible, Img.m_Width, Img.m_Height, pImgBuffer, ImageFormat))
|
||||||
{
|
{
|
||||||
if(ImageFormat != IMAGE_FORMAT_RGBA)
|
if(ImageFormat != IMAGE_FORMAT_RGBA)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,8 @@ int LoadPNG(CImageInfo *pImg, const char *pFilename)
|
||||||
|
|
||||||
uint8_t *pImgBuffer = NULL;
|
uint8_t *pImgBuffer = NULL;
|
||||||
EImageFormat ImageFormat;
|
EImageFormat ImageFormat;
|
||||||
if(LoadPNG(ImageByteBuffer, pFilename, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
int PngliteIncompatible;
|
||||||
|
if(LoadPNG(ImageByteBuffer, pFilename, PngliteIncompatible, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
||||||
{
|
{
|
||||||
pImg->m_pData = pImgBuffer;
|
pImg->m_pData = pImgBuffer;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@ int LoadPNG(CImageInfo *pImg, const char *pFilename)
|
||||||
|
|
||||||
uint8_t *pImgBuffer = NULL;
|
uint8_t *pImgBuffer = NULL;
|
||||||
EImageFormat ImageFormat;
|
EImageFormat ImageFormat;
|
||||||
if(LoadPNG(ImageByteBuffer, pFilename, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
int PngliteIncompatible;
|
||||||
|
if(LoadPNG(ImageByteBuffer, pFilename, PngliteIncompatible, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
||||||
{
|
{
|
||||||
if((ImageFormat == IMAGE_FORMAT_RGBA || ImageFormat == IMAGE_FORMAT_RGB) && pImg->m_Width <= (2 << 13) && pImg->m_Height <= (2 << 13))
|
if((ImageFormat == IMAGE_FORMAT_RGBA || ImageFormat == IMAGE_FORMAT_RGB) && pImg->m_Width <= (2 << 13) && pImg->m_Height <= (2 << 13))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue