Drop non RGBA images

This commit is contained in:
Chairn 2022-02-22 19:43:14 +01:00
parent 883c17cd2c
commit 76064bd1c8
6 changed files with 53 additions and 21 deletions

View file

@ -610,6 +610,25 @@ bool CGraphics_Threaded::CheckImageDivisibility(const char *pFileName, CImageInf
return ImageIsValid;
}
bool CGraphics_Threaded::CheckImageFormatRGBA(const char *pFileName, CImageInfo &Img)
{
if(Img.m_Format != CImageInfo::FORMAT_RGBA && Img.m_Format != CImageInfo::FORMAT_ALPHA)
{
SWarning NewWarning;
char aText[128];
aText[0] = '\0';
if(pFileName)
{
str_format(aText, sizeof(aText), "\"%s\"", pFileName);
}
str_format(NewWarning.m_aWarningMsg, sizeof(NewWarning.m_aWarningMsg),
Localize("The format of texture %s is not RGBA which will cause visual bugs."), aText);
m_Warnings.emplace_back(NewWarning);
return false;
}
return true;
}
void CGraphics_Threaded::CopyTextureBufferSub(uint8_t *pDestBuffer, uint8_t *pSourceBuffer, int FullWidth, int FullHeight, int ColorChannelCount, int SubOffsetX, int SubOffsetY, int SubCopyWidth, int SubCopyHeight)
{
for(int Y = 0; Y < SubCopyHeight; ++Y)

View file

@ -900,6 +900,7 @@ public:
void FreePNG(CImageInfo *pImg) override;
bool CheckImageDivisibility(const char *pFileName, CImageInfo &Img, int DivX, int DivY, bool AllowResize) override;
bool CheckImageFormatRGBA(const char *pFileName, CImageInfo &Img) override;
void CopyTextureBufferSub(uint8_t *pDestBuffer, uint8_t *pSourceBuffer, int FullWidth, int FullHeight, int ColorChannelCount, int SubOffsetX, int SubOffsetY, int SubCopyWidth, int SubCopyHeight) override;
void CopyTextureFromTextureBufferSub(uint8_t *pDestBuffer, int DestWidth, int DestHeight, uint8_t *pSourceBuffer, int SrcWidth, int SrcHeight, int ColorChannelCount, int SrcSubOffsetX, int SrcSubOffsetY, int SrcSubCopyWidth, int SrcSubCopyHeight) override;

View file

@ -60,6 +60,7 @@ public:
void FreePNG(CImageInfo *pImg) override{};
bool CheckImageDivisibility(const char *pFileName, CImageInfo &Img, int DivX, int DivY, bool AllowResize) override { return false; };
bool CheckImageFormatRGBA(const char *pFileName, CImageInfo &Img) override { return false; };
void CopyTextureBufferSub(uint8_t *pDestBuffer, uint8_t *pSourceBuffer, int FullWidth, int FullHeight, int ColorChannelCount, int SubOffsetX, int SubOffsetY, int SubCopyWidth, int SubCopyHeight) override{};
void CopyTextureFromTextureBufferSub(uint8_t *pDestBuffer, int DestWidth, int DestHeight, uint8_t *pSourceBuffer, int SrcWidth, int SrcHeight, int ColorChannelCount, int SrcSubOffsetX, int SrcSubOffsetY, int SrcSubCopyWidth, int SrcSubCopyHeight) override{};

View file

@ -241,6 +241,7 @@ public:
virtual void FreePNG(CImageInfo *pImg) = 0;
virtual bool CheckImageDivisibility(const char *pFileName, CImageInfo &Img, int DivX, int DivY, bool AllowResize) = 0;
virtual bool CheckImageFormatRGBA(const char *pFileName, CImageInfo &Img) = 0;
// destination and source buffer require to have the same width and height
virtual void CopyTextureBufferSub(uint8_t *pDestBuffer, uint8_t *pSourceBuffer, int FullWidth, int FullHeight, int ColorChannelCount, int SubOffsetX, int SubOffsetY, int SubCopyWidth, int SubCopyHeight) = 0;

View file

@ -133,6 +133,12 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
return 0;
}
if(!Graphics()->CheckImageFormatRGBA(pName, Info))
{
str_format(aBuf, sizeof(aBuf), "skin format is not RGBA: %s", pName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
return 0;
}
CSkin Skin;
Skin.m_IsVanilla = IsVanillaSkin(pName);
@ -175,7 +181,8 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
if(BodyWidth > Info.m_Width || BodyHeight > Info.m_Height)
return 0;
unsigned char *d = (unsigned char *)Info.m_pData;
int Pitch = Info.m_Width * 4;
const int PixelStep = 4;
int Pitch = Info.m_Width * PixelStep;
// dig out blood color
{
@ -183,12 +190,12 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
for(int y = 0; y < BodyHeight; y++)
for(int x = 0; x < BodyWidth; x++)
{
uint8_t AlphaValue = d[y * Pitch + x * 4 + 3];
uint8_t AlphaValue = d[y * Pitch + x * PixelStep + 3];
if(AlphaValue > 128)
{
aColors[0] += d[y * Pitch + x * 4 + 0];
aColors[1] += d[y * Pitch + x * 4 + 1];
aColors[2] += d[y * Pitch + x * 4 + 2];
aColors[0] += d[y * Pitch + x * PixelStep + 0];
aColors[1] += d[y * Pitch + x * PixelStep + 1];
aColors[2] += d[y * Pitch + x * PixelStep + 2];
}
}
if(aColors[0] != 0 && aColors[1] != 0 && aColors[2] != 0)
@ -208,16 +215,13 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
// get feet outline size
CheckMetrics(Skin.m_Metrics.m_Feet, d, Pitch, FeetOutlineOffsetX, FeetOutlineOffsetY, FeetOutlineWidth, FeetOutlineHeight);
// create colorless version
int Step = Info.m_Format == CImageInfo::FORMAT_RGBA ? 4 : 3;
// make the texture gray scale
for(int i = 0; i < Info.m_Width * Info.m_Height; i++)
{
int v = (d[i * Step] + d[i * Step + 1] + d[i * Step + 2]) / 3;
d[i * Step] = v;
d[i * Step + 1] = v;
d[i * Step + 2] = v;
int v = (d[i * PixelStep] + d[i * PixelStep + 1] + d[i * PixelStep + 2]) / 3;
d[i * PixelStep] = v;
d[i * PixelStep + 1] = v;
d[i * PixelStep + 2] = v;
}
int Freq[256] = {0};
@ -228,8 +232,8 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
for(int y = 0; y < BodyHeight; y++)
for(int x = 0; x < BodyWidth; x++)
{
if(d[y * Pitch + x * 4 + 3] > 128)
Freq[d[y * Pitch + x * 4]]++;
if(d[y * Pitch + x * PixelStep + 3] > 128)
Freq[d[y * Pitch + x * PixelStep]]++;
}
for(int i = 1; i < 256; i++)
@ -244,7 +248,7 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
for(int y = 0; y < BodyHeight; y++)
for(int x = 0; x < BodyWidth; x++)
{
int v = d[y * Pitch + x * 4];
int v = d[y * Pitch + x * PixelStep];
if(v <= OrgWeight && OrgWeight == 0)
v = 0;
else if(v <= OrgWeight)
@ -253,9 +257,9 @@ int CSkins::LoadSkin(const char *pName, CImageInfo &Info)
v = NewWeight;
else
v = (int)(((v - OrgWeight) / (float)InvOrgWeight) * InvNewWeight + NewWeight);
d[y * Pitch + x * 4] = v;
d[y * Pitch + x * 4 + 1] = v;
d[y * Pitch + x * 4 + 2] = v;
d[y * Pitch + x * PixelStep] = v;
d[y * Pitch + x * PixelStep + 1] = v;
d[y * Pitch + x * PixelStep + 2] = v;
}
Skin.m_ColorableSkin.m_Body = Graphics()->LoadSpriteTexture(Info, &g_pData->m_aSprites[SPRITE_TEE_BODY]);

View file

@ -2747,7 +2747,9 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
else
LoadGameSkin(pPath, true);
}
else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_HEALTH_FULL].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_HEALTH_FULL].m_pSet->m_Gridy, true))
else if(PngLoaded
&& Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_HEALTH_FULL].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_HEALTH_FULL].m_pSet->m_Gridy, true)
&& Graphics()->CheckImageFormatRGBA(aPath, ImgInfo))
{
m_GameSkin.m_SpriteHealthFull = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HEALTH_FULL]);
m_GameSkin.m_SpriteHealthEmpty = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HEALTH_EMPTY]);
@ -2900,7 +2902,9 @@ void CGameClient::LoadEmoticonsSkin(const char *pPath, bool AsDir)
else
LoadEmoticonsSkin(pPath, true);
}
else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridy, true))
else if(PngLoaded
&& Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridy, true)
&& Graphics()->CheckImageFormatRGBA(aPath, ImgInfo))
{
for(int i = 0; i < 16; ++i)
m_EmoticonsSkin.m_SpriteEmoticons[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_OOP + i]);
@ -2954,7 +2958,9 @@ void CGameClient::LoadParticlesSkin(const char *pPath, bool AsDir)
else
LoadParticlesSkin(pPath, true);
}
else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_PART_SLICE].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_PART_SLICE].m_pSet->m_Gridy, true))
else if(PngLoaded
&& Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_PART_SLICE].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_PART_SLICE].m_pSet->m_Gridy, true)
&& Graphics()->CheckImageFormatRGBA(aPath, ImgInfo))
{
m_ParticlesSkin.m_SpriteParticleSlice = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SLICE]);
m_ParticlesSkin.m_SpriteParticleBall = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_BALL]);