mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-12 19:18:20 +00:00
Fix dilate threshold & automatically apply dilate on embedded textures in the editor
This commit is contained in:
parent
4cbcde06e5
commit
0ec7f1e1dc
|
@ -1453,6 +1453,8 @@ set_src(ENGINE_SHARED GLOB src/engine/shared
|
||||||
datafile.h
|
datafile.h
|
||||||
demo.cpp
|
demo.cpp
|
||||||
demo.h
|
demo.h
|
||||||
|
dilate.cpp
|
||||||
|
dilate.h
|
||||||
econ.cpp
|
econ.cpp
|
||||||
econ.h
|
econ.h
|
||||||
engine.cpp
|
engine.cpp
|
||||||
|
|
|
@ -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(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(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(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_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")
|
MACRO_CONFIG_STR(ClSkinFilterString, cl_skin_filter_string, 25, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Skin filtering string")
|
||||||
|
|
||||||
|
|
86
src/engine/shared/dilate.cpp
Normal file
86
src/engine/shared/dilate.cpp
Normal 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]);
|
||||||
|
}
|
6
src/engine/shared/dilate.h
Normal file
6
src/engine/shared/dilate.h
Normal 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
|
|
@ -30,6 +30,8 @@
|
||||||
#include <game/client/ui.h>
|
#include <game/client/ui.h>
|
||||||
#include <game/generated/client_data.h>
|
#include <game/generated/client_data.h>
|
||||||
|
|
||||||
|
#include <engine/shared/dilate.h>
|
||||||
|
|
||||||
#include "auto_map.h"
|
#include "auto_map.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
|
@ -3606,6 +3608,20 @@ void CEditor::ReplaceImage(const char *pFileName, int StorageType, void *pUser)
|
||||||
*pImg = ImgInfo;
|
*pImg = ImgInfo;
|
||||||
IStorage::StripPathAndExtension(pFileName, pImg->m_aName, sizeof(pImg->m_aName));
|
IStorage::StripPathAndExtension(pFileName, pImg->m_aName, sizeof(pImg->m_aName));
|
||||||
pImg->m_External = IsVanillaImage(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_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);
|
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;
|
ImgInfo.m_pData = 0;
|
||||||
|
@ -3643,9 +3659,23 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
|
||||||
|
|
||||||
CEditorImage *pImg = new CEditorImage(pEditor);
|
CEditorImage *pImg = new CEditorImage(pEditor);
|
||||||
*pImg = ImgInfo;
|
*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);
|
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;
|
ImgInfo.m_pData = 0;
|
||||||
pImg->m_External = IsVanillaImage(aBuf);
|
|
||||||
str_copy(pImg->m_aName, aBuf, sizeof(pImg->m_aName));
|
str_copy(pImg->m_aName, aBuf, sizeof(pImg->m_aName));
|
||||||
pImg->m_AutoMapper.Load(pImg->m_aName);
|
pImg->m_AutoMapper.Load(pImg->m_aName);
|
||||||
pEditor->m_Map.m_lImages.add(pImg);
|
pEditor->m_Map.m_lImages.add(pImg);
|
||||||
|
|
|
@ -1,57 +1,13 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
/* (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. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#include <base/system.h>
|
|
||||||
#include <base/math.h>
|
#include <base/math.h>
|
||||||
|
#include <base/system.h>
|
||||||
|
#include <engine/shared/dilate.h>
|
||||||
#include <pnglite.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)
|
int DilateFile(const char *pFileName)
|
||||||
{
|
{
|
||||||
png_t Png;
|
png_t Png;
|
||||||
CPixel *pBuffer[3] = {0,0,0};
|
|
||||||
|
|
||||||
png_init(0, 0);
|
png_init(0, 0);
|
||||||
int Error = png_open_file(&Png, pFileName);
|
int Error = png_open_file(&Png, pFileName);
|
||||||
|
@ -69,29 +25,23 @@ int DilateFile(const char *pFileName)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pBuffer[0] = (CPixel *)malloc(Png.width * Png.height * sizeof(CPixel));
|
unsigned char *pBuffer = (unsigned char *)malloc(Png.width * Png.height * sizeof(unsigned char) * 4);
|
||||||
pBuffer[1] = (CPixel *)malloc(Png.width * Png.height * sizeof(CPixel));
|
|
||||||
pBuffer[2] = (CPixel *)malloc(Png.width * Png.height * sizeof(CPixel));
|
png_get_data(&Png, pBuffer);
|
||||||
png_get_data(&Png, (unsigned char *)pBuffer[0]);
|
|
||||||
png_close_file(&Png);
|
png_close_file(&Png);
|
||||||
|
|
||||||
int w = Png.width;
|
int w = Png.width;
|
||||||
int h = Png.height;
|
int h = Png.height;
|
||||||
|
|
||||||
Dilate(w, h, pBuffer[0], pBuffer[1]);
|
DilateImage(pBuffer, w, h, 4);
|
||||||
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]);
|
|
||||||
|
|
||||||
// save here
|
// save here
|
||||||
png_open_file_write(&Png, pFileName);
|
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);
|
png_close_file(&Png);
|
||||||
|
|
||||||
|
free(pBuffer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue