mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-09 17:48:19 +00:00
Merge pull request #8654 from Robyt3/Image-Manipulation-Minor-Refactoring
Minor refactoring of `DilateImage`, `ResizeImage` and related functions
This commit is contained in:
commit
a1ef70c114
|
@ -2,38 +2,35 @@
|
||||||
#include <base/math.h>
|
#include <base/math.h>
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
#define TW_DILATE_ALPHA_THRESHOLD 10
|
static constexpr int DILATE_BPP = 4; // RGBA assumed
|
||||||
|
static constexpr uint8_t DILATE_ALPHA_THRESHOLD = 10;
|
||||||
|
|
||||||
static void Dilate(int w, int h, const uint8_t *pSrc, uint8_t *pDest, uint8_t AlphaThreshold = TW_DILATE_ALPHA_THRESHOLD)
|
static void Dilate(int w, int h, const uint8_t *pSrc, uint8_t *pDest)
|
||||||
{
|
{
|
||||||
const int BPP = 4; // RGBA assumed
|
|
||||||
int ix, iy;
|
|
||||||
const int aDirX[] = {0, -1, 1, 0};
|
const int aDirX[] = {0, -1, 1, 0};
|
||||||
const int aDirY[] = {-1, 0, 0, 1};
|
const int aDirY[] = {-1, 0, 0, 1};
|
||||||
|
|
||||||
int AlphaCompIndex = BPP - 1;
|
|
||||||
|
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for(int y = 0; y < h; y++)
|
for(int y = 0; y < h; y++)
|
||||||
{
|
{
|
||||||
for(int x = 0; x < w; x++, m += BPP)
|
for(int x = 0; x < w; x++, m += DILATE_BPP)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < BPP; ++i)
|
for(int i = 0; i < DILATE_BPP; ++i)
|
||||||
pDest[m + i] = pSrc[m + i];
|
pDest[m + i] = pSrc[m + i];
|
||||||
if(pSrc[m + AlphaCompIndex] > AlphaThreshold)
|
if(pSrc[m + DILATE_BPP - 1] > DILATE_ALPHA_THRESHOLD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int aSumOfOpaque[] = {0, 0, 0};
|
int aSumOfOpaque[] = {0, 0, 0};
|
||||||
int Counter = 0;
|
int Counter = 0;
|
||||||
for(int c = 0; c < 4; c++)
|
for(int c = 0; c < 4; c++)
|
||||||
{
|
{
|
||||||
ix = clamp(x + aDirX[c], 0, w - 1);
|
const int ClampedX = clamp(x + aDirX[c], 0, w - 1);
|
||||||
iy = clamp(y + aDirY[c], 0, h - 1);
|
const int ClampedY = clamp(y + aDirY[c], 0, h - 1);
|
||||||
int k = iy * w * BPP + ix * BPP;
|
const int SrcIndex = ClampedY * w * DILATE_BPP + ClampedX * DILATE_BPP;
|
||||||
if(pSrc[k + AlphaCompIndex] > AlphaThreshold)
|
if(pSrc[SrcIndex + DILATE_BPP - 1] > DILATE_ALPHA_THRESHOLD)
|
||||||
{
|
{
|
||||||
for(int p = 0; p < BPP - 1; ++p)
|
for(int p = 0; p < DILATE_BPP - 1; ++p)
|
||||||
aSumOfOpaque[p] += pSrc[k + p];
|
aSumOfOpaque[p] += pSrc[SrcIndex + p];
|
||||||
++Counter;
|
++Counter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -41,29 +38,28 @@ static void Dilate(int w, int h, const uint8_t *pSrc, uint8_t *pDest, uint8_t Al
|
||||||
|
|
||||||
if(Counter > 0)
|
if(Counter > 0)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < BPP - 1; ++i)
|
for(int i = 0; i < DILATE_BPP - 1; ++i)
|
||||||
{
|
{
|
||||||
aSumOfOpaque[i] /= Counter;
|
aSumOfOpaque[i] /= Counter;
|
||||||
pDest[m + i] = (uint8_t)aSumOfOpaque[i];
|
pDest[m + i] = (uint8_t)aSumOfOpaque[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
pDest[m + AlphaCompIndex] = 255;
|
pDest[m + DILATE_BPP - 1] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyColorValues(int w, int h, int BPP, const uint8_t *pSrc, uint8_t *pDest)
|
static void CopyColorValues(int w, int h, const uint8_t *pSrc, uint8_t *pDest)
|
||||||
{
|
{
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for(int y = 0; y < h; y++)
|
for(int y = 0; y < h; y++)
|
||||||
{
|
{
|
||||||
for(int x = 0; x < w; x++, m += BPP)
|
for(int x = 0; x < w; x++, m += DILATE_BPP)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < BPP - 1; ++i)
|
if(pDest[m + DILATE_BPP - 1] == 0)
|
||||||
{
|
{
|
||||||
if(pDest[m + 3] == 0)
|
mem_copy(&pDest[m], &pSrc[m], DILATE_BPP - 1);
|
||||||
pDest[m + i] = pSrc[m + i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,18 +72,18 @@ void DilateImage(uint8_t *pImageBuff, int w, int h)
|
||||||
|
|
||||||
void DilateImageSub(uint8_t *pImageBuff, int w, int h, int x, int y, int sw, int sh)
|
void DilateImageSub(uint8_t *pImageBuff, int w, int h, int x, int y, int sw, int sh)
|
||||||
{
|
{
|
||||||
const int BPP = 4; // RGBA assumed
|
uint8_t *apBuffer[2] = {nullptr, nullptr};
|
||||||
uint8_t *apBuffer[2] = {NULL, NULL};
|
|
||||||
|
|
||||||
apBuffer[0] = (uint8_t *)malloc((size_t)sw * sh * sizeof(uint8_t) * BPP);
|
const size_t ImageSize = (size_t)sw * sh * sizeof(uint8_t) * DILATE_BPP;
|
||||||
apBuffer[1] = (uint8_t *)malloc((size_t)sw * sh * sizeof(uint8_t) * BPP);
|
apBuffer[0] = (uint8_t *)malloc(ImageSize);
|
||||||
uint8_t *pBufferOriginal = (uint8_t *)malloc((size_t)sw * sh * sizeof(uint8_t) * BPP);
|
apBuffer[1] = (uint8_t *)malloc(ImageSize);
|
||||||
|
uint8_t *pBufferOriginal = (uint8_t *)malloc(ImageSize);
|
||||||
|
|
||||||
for(int Y = 0; Y < sh; ++Y)
|
for(int Y = 0; Y < sh; ++Y)
|
||||||
{
|
{
|
||||||
int SrcImgOffset = ((y + Y) * w * BPP) + (x * BPP);
|
int SrcImgOffset = ((y + Y) * w * DILATE_BPP) + (x * DILATE_BPP);
|
||||||
int DstImgOffset = (Y * sw * BPP);
|
int DstImgOffset = (Y * sw * DILATE_BPP);
|
||||||
int CopySize = sw * BPP;
|
int CopySize = sw * DILATE_BPP;
|
||||||
mem_copy(&pBufferOriginal[DstImgOffset], &pImageBuff[SrcImgOffset], CopySize);
|
mem_copy(&pBufferOriginal[DstImgOffset], &pImageBuff[SrcImgOffset], CopySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,16 +95,16 @@ void DilateImageSub(uint8_t *pImageBuff, int w, int h, int x, int y, int sw, int
|
||||||
Dilate(sw, sh, apBuffer[1], apBuffer[0]);
|
Dilate(sw, sh, apBuffer[1], apBuffer[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyColorValues(sw, sh, BPP, apBuffer[0], pBufferOriginal);
|
CopyColorValues(sw, sh, apBuffer[0], pBufferOriginal);
|
||||||
|
|
||||||
free(apBuffer[0]);
|
free(apBuffer[0]);
|
||||||
free(apBuffer[1]);
|
free(apBuffer[1]);
|
||||||
|
|
||||||
for(int Y = 0; Y < sh; ++Y)
|
for(int Y = 0; Y < sh; ++Y)
|
||||||
{
|
{
|
||||||
int SrcImgOffset = ((y + Y) * w * BPP) + (x * BPP);
|
int SrcImgOffset = ((y + Y) * w * DILATE_BPP) + (x * DILATE_BPP);
|
||||||
int DstImgOffset = (Y * sw * BPP);
|
int DstImgOffset = (Y * sw * DILATE_BPP);
|
||||||
int CopySize = sw * BPP;
|
int CopySize = sw * DILATE_BPP;
|
||||||
mem_copy(&pImageBuff[SrcImgOffset], &pBufferOriginal[DstImgOffset], CopySize);
|
mem_copy(&pImageBuff[SrcImgOffset], &pBufferOriginal[DstImgOffset], CopySize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,18 +121,15 @@ static float CubicHermite(float A, float B, float C, float D, float t)
|
||||||
return (a * t * t * t) + (b * t * t) + (c * t) + d;
|
return (a * t * t * t) + (b * t * t) + (c * t) + d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetPixelClamped(const uint8_t *pSourceImage, int x, int y, uint32_t W, uint32_t H, size_t BPP, uint8_t aTmp[])
|
static void GetPixelClamped(const uint8_t *pSourceImage, int x, int y, uint32_t W, uint32_t H, size_t BPP, uint8_t aSample[4])
|
||||||
{
|
{
|
||||||
x = clamp<int>(x, 0, (int)W - 1);
|
x = clamp<int>(x, 0, (int)W - 1);
|
||||||
y = clamp<int>(y, 0, (int)H - 1);
|
y = clamp<int>(y, 0, (int)H - 1);
|
||||||
|
|
||||||
for(size_t i = 0; i < BPP; i++)
|
mem_copy(aSample, &pSourceImage[x * BPP + (W * BPP * y)], BPP);
|
||||||
{
|
|
||||||
aTmp[i] = pSourceImage[x * BPP + (W * BPP * y) + i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SampleBicubic(const uint8_t *pSourceImage, float u, float v, uint32_t W, uint32_t H, size_t BPP, uint8_t aSample[])
|
static void SampleBicubic(const uint8_t *pSourceImage, float u, float v, uint32_t W, uint32_t H, size_t BPP, uint8_t aSample[4])
|
||||||
{
|
{
|
||||||
float X = (u * W) - 0.5f;
|
float X = (u * W) - 0.5f;
|
||||||
int xInt = (int)X;
|
int xInt = (int)X;
|
||||||
|
@ -146,79 +139,37 @@ static void SampleBicubic(const uint8_t *pSourceImage, float u, float v, uint32_
|
||||||
int yInt = (int)Y;
|
int yInt = (int)Y;
|
||||||
float yFract = Y - std::floor(Y);
|
float yFract = Y - std::floor(Y);
|
||||||
|
|
||||||
uint8_t aPX00[4];
|
uint8_t aaaSamples[4][4][4];
|
||||||
uint8_t aPX10[4];
|
for(int y = 0; y < 4; ++y)
|
||||||
uint8_t aPX20[4];
|
{
|
||||||
uint8_t aPX30[4];
|
for(int x = 0; x < 4; ++x)
|
||||||
|
{
|
||||||
uint8_t aPX01[4];
|
GetPixelClamped(pSourceImage, xInt + x - 1, yInt + y - 1, W, H, BPP, aaaSamples[x][y]);
|
||||||
uint8_t aPX11[4];
|
}
|
||||||
uint8_t aPX21[4];
|
}
|
||||||
uint8_t aPX31[4];
|
|
||||||
|
|
||||||
uint8_t aPX02[4];
|
|
||||||
uint8_t aPX12[4];
|
|
||||||
uint8_t aPX22[4];
|
|
||||||
uint8_t aPX32[4];
|
|
||||||
|
|
||||||
uint8_t aPX03[4];
|
|
||||||
uint8_t aPX13[4];
|
|
||||||
uint8_t aPX23[4];
|
|
||||||
uint8_t aPX33[4];
|
|
||||||
|
|
||||||
GetPixelClamped(pSourceImage, xInt - 1, yInt - 1, W, H, BPP, aPX00);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 0, yInt - 1, W, H, BPP, aPX10);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 1, yInt - 1, W, H, BPP, aPX20);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 2, yInt - 1, W, H, BPP, aPX30);
|
|
||||||
|
|
||||||
GetPixelClamped(pSourceImage, xInt - 1, yInt + 0, W, H, BPP, aPX01);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 0, yInt + 0, W, H, BPP, aPX11);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 1, yInt + 0, W, H, BPP, aPX21);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 2, yInt + 0, W, H, BPP, aPX31);
|
|
||||||
|
|
||||||
GetPixelClamped(pSourceImage, xInt - 1, yInt + 1, W, H, BPP, aPX02);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 0, yInt + 1, W, H, BPP, aPX12);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 1, yInt + 1, W, H, BPP, aPX22);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 2, yInt + 1, W, H, BPP, aPX32);
|
|
||||||
|
|
||||||
GetPixelClamped(pSourceImage, xInt - 1, yInt + 2, W, H, BPP, aPX03);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 0, yInt + 2, W, H, BPP, aPX13);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 1, yInt + 2, W, H, BPP, aPX23);
|
|
||||||
GetPixelClamped(pSourceImage, xInt + 2, yInt + 2, W, H, BPP, aPX33);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < BPP; i++)
|
for(size_t i = 0; i < BPP; i++)
|
||||||
{
|
{
|
||||||
float Clmn0 = CubicHermite(aPX00[i], aPX10[i], aPX20[i], aPX30[i], xFract);
|
float aRows[4];
|
||||||
float Clmn1 = CubicHermite(aPX01[i], aPX11[i], aPX21[i], aPX31[i], xFract);
|
for(int y = 0; y < 4; ++y)
|
||||||
float Clmn2 = CubicHermite(aPX02[i], aPX12[i], aPX22[i], aPX32[i], xFract);
|
{
|
||||||
float Clmn3 = CubicHermite(aPX03[i], aPX13[i], aPX23[i], aPX33[i], xFract);
|
aRows[y] = CubicHermite(aaaSamples[0][y][i], aaaSamples[1][y][i], aaaSamples[2][y][i], aaaSamples[3][y][i], xFract);
|
||||||
|
}
|
||||||
float Valuef = CubicHermite(Clmn0, Clmn1, Clmn2, Clmn3, yFract);
|
aSample[i] = (uint8_t)clamp<float>(CubicHermite(aRows[0], aRows[1], aRows[2], aRows[3], yFract), 0.0f, 255.0f);
|
||||||
|
|
||||||
Valuef = clamp<float>(Valuef, 0.0f, 255.0f);
|
|
||||||
|
|
||||||
aSample[i] = (uint8_t)Valuef;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ResizeImage(const uint8_t *pSourceImage, uint32_t SW, uint32_t SH, uint8_t *pDestinationImage, uint32_t W, uint32_t H, size_t BPP)
|
static void ResizeImage(const uint8_t *pSourceImage, uint32_t SW, uint32_t SH, uint8_t *pDestinationImage, uint32_t W, uint32_t H, size_t BPP)
|
||||||
{
|
{
|
||||||
uint8_t aSample[4];
|
for(int y = 0; y < (int)H; ++y)
|
||||||
int y, x;
|
|
||||||
|
|
||||||
for(y = 0; y < (int)H; ++y)
|
|
||||||
{
|
{
|
||||||
float v = (float)y / (float)(H - 1);
|
float v = (float)y / (float)(H - 1);
|
||||||
|
for(int x = 0; x < (int)W; ++x)
|
||||||
for(x = 0; x < (int)W; ++x)
|
|
||||||
{
|
{
|
||||||
float u = (float)x / (float)(W - 1);
|
float u = (float)x / (float)(W - 1);
|
||||||
|
uint8_t aSample[4];
|
||||||
SampleBicubic(pSourceImage, u, v, SW, SH, BPP, aSample);
|
SampleBicubic(pSourceImage, u, v, SW, SH, BPP, aSample);
|
||||||
|
mem_copy(&pDestinationImage[x * BPP + ((W * BPP) * y)], aSample, BPP);
|
||||||
for(size_t i = 0; i < BPP; ++i)
|
|
||||||
{
|
|
||||||
pDestinationImage[x * BPP + ((W * BPP) * y) + i] = aSample[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue