47 const unsigned char* img,
int width,
int height,
int stride);
52 const unsigned char* img,
int width,
int height,
int stride,
67 const unsigned char* img,
int width,
int height,
int stride);
72#ifdef SDF_IMPLEMENTATION
77#define SDF_MAX_PASSES 10
78#define SDF_SLACK 0.001f
79#define SDF_SQRT2 1.4142136f
82static float sdf__clamp01(
float x)
84 return x < 0.0f ? 0.0f : (
x > 1.0f ? 1.0f :
x);
88 const unsigned char* img,
int width,
int height,
int stride)
93 for (
x = 0;
x < width;
x++)
95 for (
y = 1;
y < height;
y++) {
97 out[width-1+
y*outstride] = 0;
99 for (
x = 0;
x < width;
x++)
100 out[
x+(height-1)*outstride] = 0;
102 for (
y = 1;
y < height-1;
y++) {
103 for (
x = 1;
x < width-1;
x++) {
104 int k =
x +
y * stride;
105 float d, gx, gy, glen,
a, a1;
109 out[
x+
y*outstride] = 255;
115 int he = img[
k-1] == 255 || img[
k+1] == 255;
116 int ve = img[
k-stride] == 255 || img[
k+stride] == 255;
118 out[
x+
y*outstride] = 0;
123 gx = -(float)img[k-stride-1] - SDF_SQRT2*(
float)img[
k-1] - (float)img[k+stride-1] + (
float)img[
k-stride+1] + SDF_SQRT2*(float)img[k+1] + (
float)img[
k+stride+1];
124 gy = -(float)img[k-stride-1] - SDF_SQRT2*(
float)img[
k-stride] - (float)img[k-stride+1] + (
float)img[
k+stride-1] + SDF_SQRT2*(float)img[k+stride] + (
float)img[
k+stride+1];
125 a = (float)img[k]/255.0f;
128 if (gx < 0.0001f || gy < 0.000f) {
129 d = (0.5f -
a) * SDF_SQRT2;
131 glen = gx*gx + gy*gy;
132 glen = 1.0f / sqrtf(glen);
142 d = 0.5f*(gx + gy) - sqrtf(2.0f*gx*gy*
a);
143 }
else if (
a < (1.0-a1)) {
146 d = -0.5f*(gx + gy) + sqrt(2.0f*gx*gy*(1.0f-
a));
149 d *= 1.0f / SDF_SQRT2;
150 out[
x+
y*outstride] = (
unsigned char)(sdf__clamp01(0.5f - d) * 255.0f);
155static float sdf__edgedf(
float gx,
float gy,
float a)
158 if ((gx == 0) || (gy == 0)) {
175 df = 0.5f*(gx + gy) - sqrtf(2.0f*gx*gy*
a);
176 }
else if (
a < (1.0-a1)) {
179 df = -0.5f*(gx + gy) + sqrt(2.0f*gx*gy*(1.0f-
a));
189static float sdf__distsqr(
struct SDFpoint*
a,
struct SDFpoint*
b)
191 float dx =
b->x -
a->x, dy =
b->y -
a->y;
192 return dx*dx + dy*dy;
196 const unsigned char* img,
int width,
int height,
int stride,
201 float* tdist = (
float*)&temp[0];
202 struct SDFpoint* tpt = (
struct SDFpoint*)&temp[width * height *
sizeof(
float)];
205 for (i = 0;
i < width*height;
i++) {
212 for (
y = 1;
y < height-1;
y++) {
213 for (
x = 1;
x < width-1;
x++) {
214 int tk,
k =
x +
y * stride;
215 struct SDFpoint
c = { (float)
x, (
float)
y };
216 float d, gx, gy, glen;
219 if (img[k] == 255)
continue;
223 int he = img[
k-1] == 255 || img[
k+1] == 255;
224 int ve = img[
k-stride] == 255 || img[
k+stride] == 255;
225 if (!he && !ve)
continue;
229 gx = -(float)img[k-stride-1] - SDF_SQRT2*(
float)img[
k-1] - (float)img[k+stride-1] + (
float)img[
k-stride+1] + SDF_SQRT2*(float)img[k+1] + (
float)img[
k+stride+1];
230 gy = -(float)img[k-stride-1] - SDF_SQRT2*(
float)img[
k-stride] - (float)img[k-stride+1] + (
float)img[
k+stride-1] + SDF_SQRT2*(float)img[k+stride] + (
float)img[
k+stride+1];
231 if (fabsf(gx) < 0.001f && fabsf(gy) < 0.001f)
continue;
232 glen = gx*gx + gy*gy;
233 if (glen > 0.0001f) {
234 glen = 1.0f / sqrtf(glen);
241 d = sdf__edgedf(gx, gy, (
float)img[k]/255.0f);
242 tpt[tk].x =
x + gx*
d;
243 tpt[tk].y =
y + gy*
d;
244 tdist[tk] = sdf__distsqr(&c, &tpt[tk]);
249 for (pass = 0; pass < SDF_MAX_PASSES; pass++){
253 for (
y = 1;
y < height-1;
y++) {
254 for (
x = 1;
x < width-1;
x++) {
255 int k =
x+
y*width, kn, ch = 0;
256 struct SDFpoint
c = { (float)
x, (
float)
y }, pt;
257 float pd = tdist[
k],
d;
260 if (tdist[kn] < pd) {
261 d = sdf__distsqr(&c, &tpt[kn]);
262 if (d + SDF_SLACK < pd) {
270 if (tdist[kn] < pd) {
271 d = sdf__distsqr(&c, &tpt[kn]);
272 if (d + SDF_SLACK < pd) {
280 if (tdist[kn] < pd) {
281 d = sdf__distsqr(&c, &tpt[kn]);
282 if (d + SDF_SLACK < pd) {
290 if (tdist[kn] < pd) {
291 d = sdf__distsqr(&c, &tpt[kn]);
292 if (d + SDF_SLACK < pd) {
307 for (
y = height-2;
y > 0 ;
y--) {
308 for (
x = width-2;
x > 0;
x--) {
309 int k =
x+
y*width, kn, ch = 0;
310 struct SDFpoint
c = { (float)
x, (
float)
y }, pt;
311 float pd = tdist[
k],
d;
314 if (tdist[kn] < pd) {
315 d = sdf__distsqr(&c, &tpt[kn]);
316 if (d + SDF_SLACK < pd) {
324 if (tdist[kn] < pd) {
325 d = sdf__distsqr(&c, &tpt[kn]);
326 if (d + SDF_SLACK < pd) {
334 if (tdist[kn] < pd) {
335 d = sdf__distsqr(&c, &tpt[kn]);
336 if (d + SDF_SLACK < pd) {
344 if (tdist[kn] < pd) {
345 d = sdf__distsqr(&c, &tpt[kn]);
346 if (d + SDF_SLACK < pd) {
360 if (changed == 0)
break;
364 scale = 1.0f / radius;
365 for (
y = 0;
y < height;
y++) {
366 for (
x = 0;
x < width;
x++) {
367 float d = sqrtf(tdist[
x+
y*width]) *
scale;
368 if (img[
x+
y*stride] > 127)
d = -
d;
369 out[
x+
y*outstride] = (
unsigned char)(sdf__clamp01(0.5f - d*0.5f) * 255.0f);
376 const unsigned char* img,
int width,
int height,
int stride)
378 unsigned char* temp = (
unsigned char*)malloc(width*height*
sizeof(
float)*3);
379 if (temp == NULL)
return 0;
void sdfCoverageToDistanceField(unsigned char *out, int outstride, const unsigned char *img, int width, int height, int stride)
void sdfBuildDistanceFieldNoAlloc(unsigned char *out, int outstride, float radius, const unsigned char *img, int width, int height, int stride, unsigned char *temp)
int sdfBuildDistanceField(unsigned char *out, int outstride, float radius, const unsigned char *img, int width, int height, int stride)