Fix dilate threshold & automatically apply dilate on embedded textures in the editor

This commit is contained in:
Jupeyy 2020-09-20 18:42:17 +02:00
parent 4cbcde06e5
commit 0ec7f1e1dc
6 changed files with 135 additions and 60 deletions

View file

@ -1453,6 +1453,8 @@ set_src(ENGINE_SHARED GLOB src/engine/shared
datafile.h
demo.cpp
demo.h
dilate.cpp
dilate.h
econ.cpp
econ.h
engine.cpp

View file

@ -21,6 +21,7 @@ MACRO_CONFIG_INT(ClRefreshRate, cl_refresh_rate, 0, 0, 10000, CFGFLAG_SAVE | CFG
MACRO_CONFIG_INT(ClRefreshRateInactive, cl_refresh_rate_inactive, 120, 0, 10000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Refresh rate for updating the game when the window is inactive (in Hz)")
MACRO_CONFIG_INT(ClEditor, cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
MACRO_CONFIG_INT(ClEditorUndo, cl_editorundo, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Undo function in editor")
MACRO_CONFIG_INT(ClEditorDilate, cl_editor_dilate, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Automatically dilates embedded images")
MACRO_CONFIG_INT(ClLoadCountryFlags, cl_load_country_flags, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Load and show country flags")
MACRO_CONFIG_STR(ClSkinFilterString, cl_skin_filter_string, 25, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Skin filtering string")

View file

@ -0,0 +1,86 @@
#include <base/math.h>
#include <base/system.h>
static void Dilate(int w, int h, int BPP, unsigned char *pSrc, unsigned char *pDest, unsigned char AlphaThreshold = 30)
{
int ix, iy;
const int xo[] = {0, -1, 1, 0};
const int yo[] = {-1, 0, 0, 1};
int AlphaCompIndex = BPP - 1;
int m = 0;
for(int y = 0; y < h; y++)
{
for(int x = 0; x < w; x++, m += BPP)
{
for(int i = 0; i < BPP; ++i)
pDest[m + i] = pSrc[m + i];
if(pSrc[m + AlphaCompIndex] > AlphaThreshold)
continue;
int SumOfOpaque[] = {0, 0, 0};
int Counter = 0;
for(int c = 0; c < 4; c++)
{
ix = clamp(x + xo[c], 0, w - 1);
iy = clamp(y + yo[c], 0, h - 1);
int k = iy * w * BPP + ix * BPP;
if(pSrc[k + AlphaCompIndex] > AlphaThreshold)
{
for(int p = 0; p < BPP - 1; ++p)
SumOfOpaque[p] += pSrc[k + p];
++Counter;
break;
}
}
if(Counter > 0)
{
for(int i = 0; i < BPP - 1; ++i)
{
SumOfOpaque[i] /= Counter;
pDest[m + i] = (unsigned char)SumOfOpaque[i];
}
pDest[m + AlphaCompIndex] = 255;
}
}
}
}
static void CopyColorValues(int w, int h, int BPP, unsigned char *pSrc, unsigned char *pDest)
{
int m = 0;
for(int y = 0; y < h; y++)
{
for(int x = 0; x < w; x++, m += BPP)
{
for(int i = 0; i < BPP - 1; ++i)
pDest[m + i] = pSrc[m + i];
}
}
}
void DilateImage(unsigned char *pImageBuff, int w, int h, int BPP)
{
unsigned char *pBuffer[2] = {NULL, NULL};
pBuffer[0] = (unsigned char *)malloc(w * h * sizeof(unsigned char) * BPP);
pBuffer[1] = (unsigned char *)malloc(w * h * sizeof(unsigned char) * BPP);
unsigned char *pPixelBuff = (unsigned char *)pImageBuff;
Dilate(w, h, BPP, pPixelBuff, pBuffer[0]);
for(int i = 0; i < 5; i++)
{
Dilate(w, h, BPP, pBuffer[0], pBuffer[1]);
Dilate(w, h, BPP, pBuffer[1], pBuffer[0]);
}
CopyColorValues(w, h, BPP, pBuffer[0], pPixelBuff);
free(pBuffer[0]);
free(pBuffer[1]);
}

View file

@ -0,0 +1,6 @@
#ifndef ENGINE_SHARED_DILATE_H
#define ENGINE_SHARED_DILATE_H
void DilateImage(unsigned char *pImageBuff, int w, int h, int BPP);
#endif

View file

@ -30,6 +30,8 @@
#include <game/client/ui.h>
#include <game/generated/client_data.h>
#include <engine/shared/dilate.h>
#include "auto_map.h"
#include "editor.h"
@ -3606,6 +3608,20 @@ void CEditor::ReplaceImage(const char *pFileName, int StorageType, void *pUser)
*pImg = ImgInfo;
IStorage::StripPathAndExtension(pFileName, pImg->m_aName, sizeof(pImg->m_aName));
pImg->m_External = IsVanillaImage(pImg->m_aName);
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
{
int ColorChannelCount = 0;
if(ImgInfo.m_Format == CImageInfo::FORMAT_ALPHA)
ColorChannelCount = 1;
else if(ImgInfo.m_Format == CImageInfo::FORMAT_RGB)
ColorChannelCount = 3;
else if(ImgInfo.m_Format == CImageInfo::FORMAT_RGBA)
ColorChannelCount = 4;
DilateImage((unsigned char *)ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height, ColorChannelCount);
}
pImg->m_AutoMapper.Load(pImg->m_aName);
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
ImgInfo.m_pData = 0;
@ -3643,9 +3659,23 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
CEditorImage *pImg = new CEditorImage(pEditor);
*pImg = ImgInfo;
pImg->m_External = IsVanillaImage(aBuf);
if(!pImg->m_External && g_Config.m_ClEditorDilate == 1)
{
int ColorChannelCount = 0;
if(ImgInfo.m_Format == CImageInfo::FORMAT_ALPHA)
ColorChannelCount = 1;
else if(ImgInfo.m_Format == CImageInfo::FORMAT_RGB)
ColorChannelCount = 3;
else if(ImgInfo.m_Format == CImageInfo::FORMAT_RGBA)
ColorChannelCount = 4;
DilateImage((unsigned char *)ImgInfo.m_pData, ImgInfo.m_Width, ImgInfo.m_Height, ColorChannelCount);
}
pImg->m_Texture = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
ImgInfo.m_pData = 0;
pImg->m_External = IsVanillaImage(aBuf);
str_copy(pImg->m_aName, aBuf, sizeof(pImg->m_aName));
pImg->m_AutoMapper.Load(pImg->m_aName);
pEditor->m_Map.m_lImages.add(pImg);

View file

@ -1,57 +1,13 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <base/system.h>
#include <base/math.h>
#include <base/system.h>
#include <engine/shared/dilate.h>
#include <pnglite.h>
typedef struct
{
unsigned char r, g, b, a;
} CPixel;
static void Dilate(int w, int h, CPixel *pSrc, CPixel *pDest)
{
int ix, iy;
const int xo[] = {0, -1, 1, 0};
const int yo[] = {-1, 0, 0, 1};
int m = 0;
for(int y = 0; y < h; y++)
{
for(int x = 0; x < w; x++, m++)
{
pDest[m] = pSrc[m];
if(pSrc[m].a)
continue;
for(int c = 0; c < 4; c++)
{
ix = clamp(x + xo[c], 0, w-1);
iy = clamp(y + yo[c], 0, h-1);
int k = iy*w+ix;
if(pSrc[k].a)
{
pDest[m] = pSrc[k];
pDest[m].a = 255;
break;
}
}
}
}
}
static void CopyAlpha(int w, int h, CPixel *pSrc, CPixel *pDest)
{
int m = 0;
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++, m++)
pDest[m].a = pSrc[m].a;
}
int DilateFile(const char *pFileName)
{
png_t Png;
CPixel *pBuffer[3] = {0,0,0};
png_init(0, 0);
int Error = png_open_file(&Png, pFileName);
@ -69,29 +25,23 @@ int DilateFile(const char *pFileName)
return 1;
}
pBuffer[0] = (CPixel *)malloc(Png.width * Png.height * sizeof(CPixel));
pBuffer[1] = (CPixel *)malloc(Png.width * Png.height * sizeof(CPixel));
pBuffer[2] = (CPixel *)malloc(Png.width * Png.height * sizeof(CPixel));
png_get_data(&Png, (unsigned char *)pBuffer[0]);
unsigned char *pBuffer = (unsigned char *)malloc(Png.width * Png.height * sizeof(unsigned char) * 4);
png_get_data(&Png, pBuffer);
png_close_file(&Png);
int w = Png.width;
int h = Png.height;
Dilate(w, h, pBuffer[0], pBuffer[1]);
for(int i = 0; i < 5; i++)
{
Dilate(w, h, pBuffer[1], pBuffer[2]);
Dilate(w, h, pBuffer[2], pBuffer[1]);
}
CopyAlpha(w, h, pBuffer[0], pBuffer[1]);
DilateImage(pBuffer, w, h, 4);
// save here
png_open_file_write(&Png, pFileName);
png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]);
png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer);
png_close_file(&Png);
free(pBuffer);
return 0;
}