5520: Warn about pnglite-incompatible PNGs on load r=def- a=heinrich5991

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.

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


5624: Move message copy inside `SendPackMsgTranslate` r=def- a=Robyt3

Fix clang warning: Address of stack memory associated with local variable 'aBuf' is still referred to by the stack variable 'tmp' upon returning to the caller.  This will be a dangling reference [clang-analyzer-core.StackAddressEscape]

Mark the input parameters as const pointers and mark the protocol message `Pack` methods as const.

And remove a null check that only serves to hide programmer errors.

## Checklist

- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2022-07-14 16:38:08 +00:00 committed by GitHub
commit 482f15a711
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 120 additions and 75 deletions

View file

@ -288,7 +288,7 @@ class NetMessage(NetObject):
extra = []
extra += ["\tint MsgID() const { return %s; }" % self.enum_name]
extra += ["\t"]
extra += ["\tbool Pack(CMsgPacker *pPacker)"]
extra += ["\tbool Pack(CMsgPacker *pPacker) const"]
extra += ["\t{"]
#extra += ["\t\tmsg_pack_start(%s, flags);"%self.enum_name]
for v in self.variables:

View file

@ -268,7 +268,7 @@ class NetMessage(NetObject):
extra += ["\tusing is_sixup = char;"]
extra += ["\tint MsgID() const { return %s; }" % self.enum_name]
extra += ["\t"]
extra += ["\tbool Pack(CMsgPacker *pPacker)"]
extra += ["\tbool Pack(CMsgPacker *pPacker) const"]
extra += ["\t{"]
#extra += ["\t\tmsg_pack_start(%s, flags);"%self.enum_name]
for v in self.variables:

View file

@ -2501,6 +2501,8 @@ void CClient::LoadDDNetInfo()
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
@ -3125,6 +3127,10 @@ void CClient::Run()
m_pEditor->Save(arg);
return;*/
m_ServerBrowser.OnInit();
// loads the existing ddnet info file if it exists
LoadDDNetInfo();
// load data
if(!LoadData())
return;
@ -3135,7 +3141,6 @@ void CClient::Run()
}
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));
if(GIT_SHORTREV_HASH)
@ -3168,9 +3173,7 @@ void CClient::Run()
InitChecksum();
m_pConsole->InitChecksum(ChecksumData());
// loads the existing ddnet info file if it exists
LoadDDNetInfo();
// but still request the new one from server
// request the new ddnet info from server if already past the welcome dialog
if(g_Config.m_ClShowWelcome)
g_Config.m_ClShowWelcome = 0;
else

View file

@ -640,7 +640,8 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
uint8_t *pImgBuffer = NULL;
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;
@ -653,6 +654,30 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
free(pImgBuffer);
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
{
@ -2513,6 +2538,11 @@ void CGraphics_Threaded::Maximize()
m_pBackend->Maximize();
}
void CGraphics_Threaded::WarnPngliteIncompatibleImages(bool Warn)
{
m_WarnPngliteIncompatibleImages = Warn;
}
void CGraphics_Threaded::SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing)
{
m_pBackend->SetWindowParams(FullscreenMode, IsBorderless, AllowResizing);

View file

@ -7,8 +7,8 @@
#include <cstddef>
#include <vector>
#define CMD_BUFFER_DATA_BUFFER_SIZE 1024 * 1024 * 2
#define CMD_BUFFER_CMD_BUFFER_SIZE 1024 * 256
constexpr int CMD_BUFFER_DATA_BUFFER_SIZE = 1024 * 1024 * 2;
constexpr int CMD_BUFFER_CMD_BUFFER_SIZE = 1024 * 256;
class CCommandBuffer
{
@ -824,6 +824,8 @@ class CGraphics_Threaded : public IEngineGraphics
std::vector<uint8_t> m_vSpriteHelper;
bool m_WarnPngliteIncompatibleImages = false;
std::vector<SWarning> m_vWarnings;
// 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;
void Minimize() override;
void Maximize() override;
void WarnPngliteIncompatibleImages(bool Warn) override;
void SetWindowParams(int FullscreenMode, bool IsBorderless, bool AllowResizing) override;
bool SetWindowScreen(int Index) override;
void Move(int x, int y) override;

View file

@ -26,8 +26,8 @@ static void LibPNGWarning(png_structp png_ptr, png_const_charp warning_msg)
static bool FileMatchesImageType(SImageByteBuffer &ByteLoader)
{
if(ByteLoader.m_pLoadedImageBytes->size() >= 8)
return png_sig_cmp((png_bytep)ByteLoader.m_pLoadedImageBytes->data(), 0, 8) == 0;
if(ByteLoader.m_pvLoadedImageBytes->size() >= 8)
return png_sig_cmp((png_bytep)ByteLoader.m_pvLoadedImageBytes->data(), 0, 8) == 0;
return false;
}
@ -37,9 +37,9 @@ static void ReadDataFromLoadedBytes(png_structp pPNGStruct, png_bytep pOutBytes,
SImageByteBuffer *pByteLoader = (SImageByteBuffer *)pIO_Ptr;
if(pByteLoader->m_pLoadedImageBytes->size() >= pByteLoader->m_LoadOffset + (size_t)ByteCountToRead)
if(pByteLoader->m_pvLoadedImageBytes->size() >= pByteLoader->m_LoadOffset + (size_t)ByteCountToRead)
{
mem_copy(pOutBytes, &(*pByteLoader->m_pLoadedImageBytes)[pByteLoader->m_LoadOffset], (size_t)ByteCountToRead);
mem_copy(pOutBytes, &(*pByteLoader->m_pvLoadedImageBytes)[pByteLoader->m_LoadOffset], (size_t)ByteCountToRead);
pByteLoader->m_LoadOffset += (size_t)ByteCountToRead;
}
@ -79,12 +79,12 @@ static void LibPNGDeleteReadStruct(png_structp pPNGStruct, png_infop pPNGInfo)
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 BitDepth = png_get_bit_depth(pPNGStruct, pPNGInfo);
int InterlaceType = png_get_interlace_type(pPNGStruct, pPNGInfo);
bool Unsupported = false;
int Result = 0;
switch(ColorType)
{
case PNG_COLOR_TYPE_GRAY:
@ -93,8 +93,8 @@ static bool IsUnsupportedByPnglite(png_structp pPNGStruct, png_infop pPNGInfo)
case PNG_COLOR_TYPE_GRAY_ALPHA:
break;
default:
log_error("png", "color type %d unsupported by pnglite", ColorType);
Unsupported = true;
log_debug("png", "color type %d unsupported by pnglite", ColorType);
Result |= PNGLITE_COLOR_TYPE;
}
switch(BitDepth)
@ -103,33 +103,29 @@ static bool IsUnsupportedByPnglite(png_structp pPNGStruct, png_infop pPNGInfo)
case 16:
break;
default:
log_error("png", "bit depth %d unsupported by pnglite", BitDepth);
Unsupported = true;
log_debug("png", "bit depth %d unsupported by pnglite", BitDepth);
Result |= PNGLITE_BIT_DEPTH;
}
switch(InterlaceType)
if(InterlaceType != PNG_INTERLACE_NONE)
{
case PNG_INTERLACE_NONE:
break;
default:
log_error("png", "interlace type %d unsupported by pnglite", InterlaceType);
Unsupported = true;
log_debug("png", "interlace type %d unsupported by pnglite", InterlaceType);
Result |= PNGLITE_INTERLACE_TYPE;
}
if(png_get_compression_type(pPNGStruct, pPNGInfo) != PNG_COMPRESSION_TYPE_BASE || png_get_filter_type(pPNGStruct, pPNGInfo) != PNG_FILTER_TYPE_BASE)
if(png_get_compression_type(pPNGStruct, pPNGInfo) != PNG_COMPRESSION_TYPE_BASE)
{
log_error("png", "non-default compression type or non-default filter type unsupported by pnglite");
Unsupported = true;
log_debug("png", "non-default compression type unsupported by pnglite");
Result |= PNGLITE_COMPRESSION_TYPE;
}
if(Unsupported)
if(png_get_filter_type(pPNGStruct, pPNGInfo) != PNG_FILTER_TYPE_BASE)
{
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);
@ -175,8 +171,9 @@ bool LoadPNG(SImageByteBuffer &ByteLoader, const char *pFileName, int &Width, in
Height = png_get_image_height(pPNGStruct, pPNGInfo);
int ColorType = png_get_color_type(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)
{
@ -254,9 +251,9 @@ static void WriteDataFromLoadedBytes(png_structp pPNGStruct, png_bytep pOutBytes
SImageByteBuffer *pByteLoader = (SImageByteBuffer *)pIO_Ptr;
size_t NewSize = pByteLoader->m_LoadOffset + (size_t)ByteCountToWrite;
pByteLoader->m_pLoadedImageBytes->resize(NewSize);
pByteLoader->m_pvLoadedImageBytes->resize(NewSize);
mem_copy(&(*pByteLoader->m_pLoadedImageBytes)[pByteLoader->m_LoadOffset], pOutBytes, (size_t)ByteCountToWrite);
mem_copy(&(*pByteLoader->m_pvLoadedImageBytes)[pByteLoader->m_LoadOffset], pOutBytes, (size_t)ByteCountToWrite);
pByteLoader->m_LoadOffset = NewSize;
}
}
@ -295,7 +292,7 @@ bool SavePNG(EImageFormat ImageFormat, const uint8_t *pRawBuffer, SImageByteBuff
}
WrittenBytes.m_LoadOffset = 0;
WrittenBytes.m_pLoadedImageBytes->clear();
WrittenBytes.m_pvLoadedImageBytes->clear();
png_set_write_fn(pPNGStruct, (png_bytep)&WrittenBytes, WriteDataFromLoadedBytes, FlushPNGWrite);

View file

@ -15,14 +15,23 @@ enum EImageFormat
typedef std::vector<uint8_t> TImageByteBuffer;
struct SImageByteBuffer
{
SImageByteBuffer(TImageByteBuffer *pBuff) :
m_LoadOffset(0), m_pLoadedImageBytes(pBuff), m_Err(0) {}
SImageByteBuffer(std::vector<uint8_t> *pvBuff) :
m_LoadOffset(0), m_pvLoadedImageBytes(pvBuff), m_Err(0) {}
size_t m_LoadOffset;
TImageByteBuffer *m_pLoadedImageBytes;
std::vector<uint8_t> *m_pvLoadedImageBytes;
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);
#endif // ENGINE_GFX_IMAGE_LOADER_H

View file

@ -251,6 +251,7 @@ public:
int WindowWidth() const { return m_ScreenWidth / 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 bool SetWindowScreen(int Index) = 0;
virtual bool SetVSync(bool State) = 0;

View file

@ -64,29 +64,24 @@ public:
virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) = 0;
template<class T, typename std::enable_if<!protocol7::is_sixup<T>::value, int>::type = 0>
inline int SendPackMsg(T *pMsg, int Flags, int ClientID)
inline int SendPackMsg(const T *pMsg, int Flags, int ClientID)
{
int Result = 0;
T tmp;
if(ClientID == -1)
{
for(int i = 0; i < MaxClients(); i++)
if(ClientIngame(i))
{
mem_copy(&tmp, pMsg, sizeof(T));
Result = SendPackMsgTranslate(&tmp, Flags, i);
}
Result = SendPackMsgTranslate(pMsg, Flags, i);
}
else
{
mem_copy(&tmp, pMsg, sizeof(T));
Result = SendPackMsgTranslate(&tmp, Flags, ClientID);
Result = SendPackMsgTranslate(pMsg, Flags, ClientID);
}
return Result;
}
template<class T, typename std::enable_if<protocol7::is_sixup<T>::value, int>::type = 1>
inline int SendPackMsg(T *pMsg, int Flags, int ClientID)
inline int SendPackMsg(const T *pMsg, int Flags, int ClientID)
{
int Result = 0;
if(ClientID == -1)
@ -102,50 +97,57 @@ public:
}
template<class T>
int SendPackMsgTranslate(T *pMsg, int Flags, int ClientID)
int SendPackMsgTranslate(const T *pMsg, int Flags, int ClientID)
{
return SendPackMsgOne(pMsg, Flags, ClientID);
}
int SendPackMsgTranslate(CNetMsg_Sv_Emoticon *pMsg, int Flags, int ClientID)
int SendPackMsgTranslate(const CNetMsg_Sv_Emoticon *pMsg, int Flags, int ClientID)
{
return Translate(pMsg->m_ClientID, ClientID) && SendPackMsgOne(pMsg, Flags, ClientID);
CNetMsg_Sv_Emoticon MsgCopy;
mem_copy(&MsgCopy, pMsg, sizeof(MsgCopy));
return Translate(MsgCopy.m_ClientID, ClientID) && SendPackMsgOne(&MsgCopy, Flags, ClientID);
}
int SendPackMsgTranslate(CNetMsg_Sv_Chat *pMsg, int Flags, int ClientID)
int SendPackMsgTranslate(const CNetMsg_Sv_Chat *pMsg, int Flags, int ClientID)
{
CNetMsg_Sv_Chat MsgCopy;
mem_copy(&MsgCopy, pMsg, sizeof(MsgCopy));
char aBuf[1000];
if(pMsg->m_ClientID >= 0 && !Translate(pMsg->m_ClientID, ClientID))
if(MsgCopy.m_ClientID >= 0 && !Translate(MsgCopy.m_ClientID, ClientID))
{
str_format(aBuf, sizeof(aBuf), "%s: %s", ClientName(pMsg->m_ClientID), pMsg->m_pMessage);
pMsg->m_pMessage = aBuf;
pMsg->m_ClientID = VANILLA_MAX_CLIENTS - 1;
str_format(aBuf, sizeof(aBuf), "%s: %s", ClientName(MsgCopy.m_ClientID), MsgCopy.m_pMessage);
MsgCopy.m_pMessage = aBuf;
MsgCopy.m_ClientID = VANILLA_MAX_CLIENTS - 1;
}
if(IsSixup(ClientID))
{
protocol7::CNetMsg_Sv_Chat Msg7;
Msg7.m_ClientID = pMsg->m_ClientID;
Msg7.m_pMessage = pMsg->m_pMessage;
Msg7.m_Mode = pMsg->m_Team > 0 ? protocol7::CHAT_TEAM : protocol7::CHAT_ALL;
Msg7.m_ClientID = MsgCopy.m_ClientID;
Msg7.m_pMessage = MsgCopy.m_pMessage;
Msg7.m_Mode = MsgCopy.m_Team > 0 ? protocol7::CHAT_TEAM : protocol7::CHAT_ALL;
Msg7.m_TargetID = -1;
return SendPackMsgOne(&Msg7, Flags, ClientID);
}
return SendPackMsgOne(pMsg, Flags, ClientID);
return SendPackMsgOne(&MsgCopy, Flags, ClientID);
}
int SendPackMsgTranslate(CNetMsg_Sv_KillMsg *pMsg, int Flags, int ClientID)
int SendPackMsgTranslate(const CNetMsg_Sv_KillMsg *pMsg, int Flags, int ClientID)
{
if(!Translate(pMsg->m_Victim, ClientID))
CNetMsg_Sv_KillMsg MsgCopy;
mem_copy(&MsgCopy, pMsg, sizeof(MsgCopy));
if(!Translate(MsgCopy.m_Victim, ClientID))
return 0;
if(!Translate(pMsg->m_Killer, ClientID))
pMsg->m_Killer = pMsg->m_Victim;
return SendPackMsgOne(pMsg, Flags, ClientID);
if(!Translate(MsgCopy.m_Killer, ClientID))
MsgCopy.m_Killer = MsgCopy.m_Victim;
return SendPackMsgOne(&MsgCopy, Flags, ClientID);
}
template<class T>
int SendPackMsgOne(T *pMsg, int Flags, int ClientID)
int SendPackMsgOne(const T *pMsg, int Flags, int ClientID)
{
dbg_assert(ClientID != -1, "SendPackMsgOne called with -1");
CMsgPacker Packer(pMsg->MsgID(), false, protocol7::is_sixup<T>::value);

View file

@ -835,9 +835,6 @@ static inline bool RepackMsg(const CMsgPacker *pMsg, CPacker &Packer, bool Sixup
int CServer::SendMsg(CMsgPacker *pMsg, int Flags, int ClientID)
{
CNetChunk Packet;
if(!pMsg)
return -1;
mem_zero(&Packet, sizeof(CNetChunk));
if(Flags & MSGFLAG_VITAL)
Packet.m_Flags |= NETSENDFLAG_VITAL;

View file

@ -26,7 +26,8 @@ int DilateFile(const char *pFilename)
uint8_t *pImgBuffer = NULL;
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)
{

View file

@ -43,7 +43,8 @@ int LoadPNG(CImageInfo *pImg, const char *pFilename)
uint8_t *pImgBuffer = NULL;
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;

View file

@ -41,7 +41,8 @@ int LoadPNG(CImageInfo *pImg, const char *pFilename)
uint8_t *pImgBuffer = NULL;
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))
{