mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +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
|
||||
demo.cpp
|
||||
demo.h
|
||||
dilate.cpp
|
||||
dilate.h
|
||||
econ.cpp
|
||||
econ.h
|
||||
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(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")
|
||||
|
||||
|
|
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/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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue