This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
nekohook/modules/gl_draw/libglez/ftgl/distance-field.c
2020-08-04 13:13:01 -04:00

95 lines
3.0 KiB
C

/* Freetype GL - A C OpenGL Freetype engine
*
* Distributed under the OSI-approved BSD 2-Clause License. See accompanying
* file `LICENSE` for more details.
*/
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "edtaa3func.h"
double *make_distance_mapd(double *data, unsigned int width,
unsigned int height) {
short *xdist = (short *)malloc(width * height * sizeof(short));
short *ydist = (short *)malloc(width * height * sizeof(short));
double *gx = (double *)calloc(width * height, sizeof(double));
double *gy = (double *)calloc(width * height, sizeof(double));
double *outside = (double *)calloc(width * height, sizeof(double));
double *inside = (double *)calloc(width * height, sizeof(double));
double vmin = DBL_MAX;
unsigned int i;
// Compute outside = edtaa3(bitmap); % Transform background (0's)
computegradient(data, width, height, gx, gy);
edtaa3(data, gx, gy, width, height, xdist, ydist, outside);
for (i = 0; i < width * height; ++i)
if (outside[i] < 0.0) outside[i] = 0.0;
// Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
memset(gx, 0, sizeof(double) * width * height);
memset(gy, 0, sizeof(double) * width * height);
for (i = 0; i < width * height; ++i) data[i] = 1 - data[i];
computegradient(data, width, height, gx, gy);
edtaa3(data, gx, gy, width, height, xdist, ydist, inside);
for (i = 0; i < width * height; ++i)
if (inside[i] < 0) inside[i] = 0.0;
// distmap = outside - inside; % Bipolar distance field
for (i = 0; i < width * height; ++i) {
outside[i] -= inside[i];
if (outside[i] < vmin) vmin = outside[i];
}
vmin = fabs(vmin);
for (i = 0; i < width * height; ++i) {
double v = outside[i];
if (v < -vmin)
outside[i] = -vmin;
else if (v > +vmin)
outside[i] = +vmin;
data[i] = (outside[i] + vmin) / (2 * vmin);
}
free(xdist);
free(ydist);
free(gx);
free(gy);
free(outside);
free(inside);
return data;
}
unsigned char *make_distance_mapb(unsigned char *img, unsigned int width,
unsigned int height) {
double *data = (double *)calloc(width * height, sizeof(double));
unsigned char *out =
(unsigned char *)malloc(width * height * sizeof(unsigned char));
unsigned int i;
// find minimimum and maximum values
double img_min = DBL_MAX;
double img_max = DBL_MIN;
for (i = 0; i < width * height; ++i) {
double v = img[i];
data[i] = v;
if (v > img_max) img_max = v;
if (v < img_min) img_min = v;
}
// Map values from 0 - 255 to 0.0 - 1.0
for (i = 0; i < width * height; ++i) data[i] = (img[i] - img_min) / img_max;
data = make_distance_mapd(data, width, height);
// map values from 0.0 - 1.0 to 0 - 255
for (i = 0; i < width * height; ++i)
out[i] = (unsigned char)(255 * (1 - data[i]));
free(data);
return out;
}