[DEV] better distance field display

This commit is contained in:
Edouard DUPIN 2014-01-08 22:15:01 +01:00
parent d144c0a65f
commit fbca6c4491
5 changed files with 508 additions and 656 deletions

View File

@ -12,37 +12,44 @@ uniform int EW_SoftEdge;
varying vec2 f_texcoord; varying vec2 f_texcoord;
varying vec4 f_color; varying vec4 f_color;
void main(void) { vec3 glyph_color = vec3(1.0,1.0,1.0);
vec4 tmpcolor = texture2D(EW_texID, f_texcoord); const float glyph_center = 0.50;
vec4 outColor = vec4(0,0,0,0); vec3 outline_color = vec3(0.0,0.0,0.0);
// compare distance with 0.5 that represent the middle ... const float outline_center = 0.55;
/* vec3 glow_color = vec3(1.0,1.0,1.0);
if (tmpcolor[0]>0.5) { const float glow_center = 1.25;
outColor = f_color;
outColor[3] = 1.0;
} else if (tmpcolor[0]>0.49) {
// antialiasing :
outColor = f_color;
outColor[3] = 0.0;//(tmpcolor[3]-0.49)*1.0/0.02;
}
*/
outColor = f_color;
outColor[3] = smoothstep(0.35, 0.65, tmpcolor[0]);
/*
outColor = f_color;// * tmpcolor[3];
if (1==EW_SoftEdge) {
outColor[3] = smoothstep(EW_SoftEdgeMin, EW_SoftEdgeMax, tmpcolor[3]);
} else {
if (tmpcolor[3]>0.5) {
outColor[3] = 1.0;
} else {
outColor[3] = 0.0;
}
}
*/
//outColor = vec4(0,0,0,0);
//outColor[3] = tmpcolor[3];
gl_FragColor = outColor;
//gl_FragColor = tmpcolor;
}
void main(void) {
//vec4 color = texture2D(EW_texID, vec2(int(f_texcoord[0]*256.0)/256.0,int(f_texcoord[1]*256.0)/256.0) );
vec4 color = texture2D(EW_texID, f_texcoord );
float dist = color.r;
float width = fwidth(dist);
float alpha = smoothstep(glyph_center-width, glyph_center+width, dist);
// Smooth
gl_FragColor = vec4(glyph_color, alpha);
// Outline
/*
float mu = smoothstep(outline_center-width, outline_center+width, dist);
vec3 rgb = mix(outline_color, glyph_color, mu);
gl_FragColor = vec4(rgb, max(alpha,mu));
*/
// Glow
/*
vec3 rgb = mix(glow_color, glyph_color, alpha);
float mu = smoothstep(glyph_center, glow_center, sqrt(dist));
gl_FragColor = vec4(rgb, max(alpha,mu));
*/
// Glow + outline
/*
vec3 rgb = mix(glow_color, glyph_color, alpha);
float mu = smoothstep(glyph_center, glow_center, sqrt(dist));
color = vec4(rgb, max(alpha,mu));
float beta = smoothstep(outline_center-width, outline_center+width, dist);
rgb = mix(outline_color, color.rgb, beta);
gl_FragColor = vec4(rgb, max(color.a,beta));
*/
}

View File

@ -21,6 +21,7 @@ void main(void) {
f_color = EW_color; f_color = EW_color;
} }
/* /*
// Distance map contour texturing according to Green (2007), // Distance map contour texturing according to Green (2007),
// implementation by Stefan Gustavson 2009. // implementation by Stefan Gustavson 2009.

View File

@ -97,10 +97,8 @@ void computegradient(double *img, int w, int h, double *gx, double *gy)
* accuracy at and near edges, and reduces the error even at distant pixels * accuracy at and near edges, and reduces the error even at distant pixels
* provided that the gradient direction is accurately estimated. * provided that the gradient direction is accurately estimated.
*/ */
double edgedf(double gx, double gy, double a) double edgedf(double gx, double gy, double a) {
{
double df, glength, temp, a1; double df, glength, temp, a1;
if ((gx == 0) || (gy == 0)) { // Either A) gu or gv are zero, or B) both if ((gx == 0) || (gy == 0)) { // Either A) gu or gv are zero, or B) both
df = 0.5-a; // Linear approximation is A) correct or B) a fair guess df = 0.5-a; // Linear approximation is A) correct or B) a fair guess
} else { } else {
@ -132,8 +130,7 @@ double edgedf(double gx, double gy, double a)
return df; return df;
} }
double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc, int yc, int xi, int yi) double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc, int yc, int xi, int yi) {
{
double di, df, dx, dy, gx, gy, a; double di, df, dx, dy, gx, gy, a;
int closest; int closest;
@ -142,9 +139,15 @@ double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc,
gx = gximg[closest]; // X gradient component at the edge pixel gx = gximg[closest]; // X gradient component at the edge pixel
gy = gyimg[closest]; // Y gradient component at the edge pixel gy = gyimg[closest]; // Y gradient component at the edge pixel
if(a > 1.0) a = 1.0; if(a > 1.0) {
if(a < 0.0) a = 0.0; // Clip grayscale values outside the range [0,1] a = 1.0;
if(a == 0.0) return 1000000.0; // Not an object pixel, return "very far" ("don't know yet") }
if(a < 0.0) {
a = 0.0; // Clip grayscale values outside the range [0,1]
}
if(a == 0.0) {
return 1000000.0; // Not an object pixel, return "very far" ("don't know yet")
}
dx = (double)xi; dx = (double)xi;
dy = (double)yi; dy = (double)yi;
@ -186,59 +189,47 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
for(i=0; i<w*h; i++) { for(i=0; i<w*h; i++) {
distx[i] = 0; // At first, all pixels point to distx[i] = 0; // At first, all pixels point to
disty[i] = 0; // themselves as the closest known. disty[i] = 0; // themselves as the closest known.
if(img[i] <= 0.0) if(img[i] <= 0.0){
{
dist[i]= 1000000.0; // Big value, means "not set yet" dist[i]= 1000000.0; // Big value, means "not set yet"
} } else if (img[i]<1.0) {
else if (img[i]<1.0) {
dist[i] = edgedf(gx[i], gy[i], img[i]); // Gradient-assisted estimate dist[i] = edgedf(gx[i], gy[i], img[i]); // Gradient-assisted estimate
} } else {
else {
dist[i]= 0.0; // Inside the object dist[i]= 0.0; // Inside the object
} }
} }
/* Perform the transformation */ /* Perform the transformation */
do do {
{
changed = 0; changed = 0;
/* Scan rows, except first row */ /* Scan rows, except first row */
for(y=1; y<h; y++) for(y=1; y<h; y++) {
{
/* move index to leftmost pixel of current row */ /* move index to leftmost pixel of current row */
i = y*w; i = y*w;
/* scan right, propagate distances from above & left */ /* scan right, propagate distances from above & left */
/* Leftmost pixel is special, has no left neighbors */ /* Leftmost pixel is special, has no left neighbors */
olddist = dist[i]; olddist = dist[i];
if(olddist > 0) // If non-zero distance or not set yet if(olddist > 0) { // If non-zero distance or not set yet
{
c = i + offset_u; // Index of candidate for testing c = i + offset_u; // Index of candidate for testing
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx; newdistx = cdistx;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_ur; c = i+offset_ur;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
@ -246,140 +237,122 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
} }
} }
i++; i++;
/* Middle pixels have all neighbors */ /* Middle pixels have all neighbors */
for(x=1; x<w-1; x++, i++) for(x=1; x<w-1; x++, i++) {
{
olddist = dist[i]; olddist = dist[i];
if(olddist <= 0) continue; // No need to update further if(olddist <= 0) {
continue; // No need to update further
}
c = i+offset_l; c = i+offset_l;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty; newdisty = cdisty;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_lu; c = i+offset_lu;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_u; c = i+offset_u;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx; newdistx = cdistx;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_ur; c = i+offset_ur;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
changed = 1; changed = 1;
} }
} }
/* Rightmost pixel of row is special, has no right neighbors */ /* Rightmost pixel of row is special, has no right neighbors */
olddist = dist[i]; olddist = dist[i];
if(olddist > 0) // If not already zero distance if(olddist > 0) {// If not already zero distance
{
c = i+offset_l; c = i+offset_l;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty; newdisty = cdisty;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_lu; c = i+offset_lu;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_u; c = i+offset_u;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx; newdistx = cdistx;
newdisty = cdisty+1; newdisty = cdisty+1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
changed = 1; changed = 1;
} }
} }
/* Move index to second rightmost pixel of current row. */ /* Move index to second rightmost pixel of current row. */
/* Rightmost pixel is skipped, it has no right neighbor. */ /* Rightmost pixel is skipped, it has no right neighbor. */
i = y*w + w-2; i = y*w + w-2;
/* scan left, propagate distance from right */ /* scan left, propagate distance from right */
for(x=w-2; x>=0; x--, i--) for(x=w-2; x>=0; x--, i--) {
{
olddist = dist[i]; olddist = dist[i];
if(olddist <= 0) continue; // Already zero distance if(olddist <= 0) {
continue; // Already zero distance
}
c = i+offset_r; c = i+offset_r;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty; newdisty = cdisty;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
@ -387,27 +360,21 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
} }
} }
} }
/* Scan rows in reverse order, except last row */ /* Scan rows in reverse order, except last row */
for(y=h-2; y>=0; y--) for(y=h-2; y>=0; y--) {
{
/* move index to rightmost pixel of current row */ /* move index to rightmost pixel of current row */
i = y*w + w-1; i = y*w + w-1;
/* Scan left, propagate distances from below & right */ /* Scan left, propagate distances from below & right */
/* Rightmost pixel is special, has no right neighbors */ /* Rightmost pixel is special, has no right neighbors */
olddist = dist[i]; olddist = dist[i];
if(olddist > 0) // If not already zero distance if(olddist > 0) { // If not already zero distance
{
c = i+offset_d; c = i+offset_d;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx; newdistx = cdistx;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
@ -421,8 +388,7 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
@ -430,66 +396,58 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
} }
} }
i--; i--;
/* Middle pixels have all neighbors */ /* Middle pixels have all neighbors */
for(x=w-2; x>0; x--, i--) for(x=w-2; x>0; x--, i--) {
{
olddist = dist[i]; olddist = dist[i];
if(olddist <= 0) continue; // Already zero distance if(olddist <= 0) {
continue; // Already zero distance
}
c = i+offset_r; c = i+offset_r;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty; newdisty = cdisty;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_rd; c = i+offset_rd;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_d; c = i+offset_d;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx; newdistx = cdistx;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_dl; c = i+offset_dl;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
@ -498,70 +456,62 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
} }
/* Leftmost pixel is special, has no left neighbors */ /* Leftmost pixel is special, has no left neighbors */
olddist = dist[i]; olddist = dist[i];
if(olddist > 0) // If not already zero distance if(olddist > 0) { // If not already zero distance
{
c = i+offset_r; c = i+offset_r;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty; newdisty = cdisty;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_rd; c = i+offset_rd;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx-1; newdistx = cdistx-1;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
olddist=newdist; olddist=newdist;
changed = 1; changed = 1;
} }
c = i+offset_d; c = i+offset_d;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx; newdistx = cdistx;
newdisty = cdisty-1; newdisty = cdisty-1;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
changed = 1; changed = 1;
} }
} }
/* Move index to second leftmost pixel of current row. */ /* Move index to second leftmost pixel of current row. */
/* Leftmost pixel is skipped, it has no left neighbor. */ /* Leftmost pixel is skipped, it has no left neighbor. */
i = y*w + 1; i = y*w + 1;
for(x=1; x<w; x++, i++) for(x=1; x<w; x++, i++) {
{
/* scan right, propagate distance from left */ /* scan right, propagate distance from left */
olddist = dist[i]; olddist = dist[i];
if(olddist <= 0) continue; // Already zero distance if(olddist <= 0) {
continue; // Already zero distance
}
c = i+offset_l; c = i+offset_l;
cdistx = distx[c]; cdistx = distx[c];
cdisty = disty[c]; cdisty = disty[c];
newdistx = cdistx+1; newdistx = cdistx+1;
newdisty = cdisty; newdisty = cdisty;
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
if(newdist < olddist-epsilon) if(newdist < olddist-epsilon) {
{
distx[i]=newdistx; distx[i]=newdistx;
disty[i]=newdisty; disty[i]=newdisty;
dist[i]=newdist; dist[i]=newdist;
@ -569,9 +519,6 @@ void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, sho
} }
} }
} }
} } while(changed); // Sweep until no more updates are made
while(changed); // Sweep until no more updates are made
/* The transformation is completed. */ /* The transformation is completed. */
} }

2
external/etk vendored

@ -1 +1 @@
Subproject commit a61639ef292b617a86a07fe30770d8533c17159b Subproject commit b0e3b31664cab066ea3f5e9c42ba6729f40e95e1

View File

@ -17,6 +17,7 @@
#include <ewol/resource/FontFreeType.h> #include <ewol/resource/FontFreeType.h>
#include <ewol/context/Context.h> #include <ewol/context/Context.h>
#include <ewol/resource/DistanceFieldFont.h> #include <ewol/resource/DistanceFieldFont.h>
#include <edtaa3/edtaa3func.h>
#undef __class__ #undef __class__
#define __class__ "resource::DistanceFieldFont" #define __class__ "resource::DistanceFieldFont"
@ -27,7 +28,7 @@ ewol::resource::DistanceFieldFont::DistanceFieldFont(const std::string& _fontNam
m_font = NULL; m_font = NULL;
m_lastGlyphPos.setValue(1,1); m_lastGlyphPos.setValue(1,1);
m_lastRawHeigh = 0; m_lastRawHeigh = 0;
m_size = 36; m_size = 70;
std::string localName = _fontName; std::string localName = _fontName;
std::vector<std::string> folderList; std::vector<std::string> folderList;
if (true == ewol::getContext().getFontDefault().getUseExternal()) { if (true == ewol::getContext().getFontDefault().getUseExternal()) {
@ -112,29 +113,21 @@ ewol::resource::DistanceFieldFont::~DistanceFieldFont(void) {
ewol::resource::FontFreeType::release(m_font); ewol::resource::FontFreeType::release(m_font);
} }
void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::ImageMono& _input, egami::Image& _output) { void ewol::resource::DistanceFieldFont::GenerateDistanceField(const egami::ImageMono& _input, egami::Image& _output) {
unsigned char *img = &_input[0]; int32_t size = _input.getSize().x() * _input.getSize().y();
unsigned int width = _input.getSize().x(); std::vector<short> xdist(size);
unsigned int height = _input.getSize().y(); std::vector<short> ydist(size);
std::vector<short> xdist; std::vector<double> gx(size);
std::vector<short> ydist; std::vector<double> gy(size);
std::vector<double> gx; std::vector<double> data(size);
std::vector<double> gy; std::vector<double> outside(size);
std::vector<double> data; std::vector<double> inside(size);
std::vector<double> outside;
std::vector<double> inside;
xdist.resize(width*height, 0);
ydist.resize(width*height, 0);
gx.resize(width*height, 0.0);
gy.resize(width*height, 0.0);
data.resize(width*height, 0.0);
outside.resize(width*height, 0.0);
inside.resize(width*height, 0.0);
// Convert img into double (data) // Convert img into double (data)
double img_min = 255, img_max = -255; double img_min = 255, img_max = -255;
for(size_t iii = 0; iii < data.size(); ++iii) { for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
double v = img[iii]; for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
int32_t iii = yyy * _input.getSize().x() + xxx;
double v = _input.get(ivec2(xxx, yyy));
data[iii] = v; data[iii] = v;
if (v > img_max) { if (v > img_max) {
img_max = v; img_max = v;
@ -143,14 +136,18 @@ void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::I
img_min = v; img_min = v;
} }
} }
}
// Rescale image levels between 0 and 1 // Rescale image levels between 0 and 1
for(size_t iii = 0; iii < data.size(); ++iii) { for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
data[iii] = (img[iii]-img_min)/img_max; for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
int32_t iii = yyy * _input.getSize().x() + xxx;
data[iii] = (_input.get(ivec2(xxx, yyy))-img_min)/img_max;
}
} }
// Compute outside = edtaa3(bitmap); % Transform background (0's) // Compute outside = edtaa3(bitmap); % Transform background (0's)
computegradient(&data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]); computegradient(&data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().y(), _input.getSize().x(), &xdist[0], &ydist[0], &outside[0]); edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &outside[0]);
for(size_t iii = 0; iii < outside.size(); ++iii) { for(size_t iii = 0; iii < outside.size(); ++iii) {
if( outside[iii] < 0 ) { if( outside[iii] < 0 ) {
outside[iii] = 0.0; outside[iii] = 0.0;
@ -168,7 +165,7 @@ void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::I
data[iii] = 1 - data[iii]; data[iii] = 1 - data[iii];
} }
computegradient( &data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]); computegradient( &data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]);
edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().y(), _input.getSize().x(), &xdist[0], &ydist[0], &inside[0]); edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &inside[0]);
for(size_t iii = 0; iii < inside.size(); ++iii) { for(size_t iii = 0; iii < inside.size(); ++iii) {
if( inside[iii] < 0 ) { if( inside[iii] < 0 ) {
inside[iii] = 0.0; inside[iii] = 0.0;
@ -195,106 +192,6 @@ void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::I
} }
} }
class GirdDF {
private:
std::vector<ivec2> m_data;
ivec2 m_size;
ivec2 m_error;
public:
GirdDF(const ivec2& _size, const ivec2& _base = ivec2(0,0), const ivec2& _error = ivec2(0,0)) {
m_size = _size;
m_data.resize(m_size.x()*m_size.y(), _base);
m_error = _error;
}
const ivec2& get(const ivec2& _pos) const {
if( _pos.x()>0 && _pos.x()<m_size.x()
&& _pos.y()>0 && _pos.y()<m_size.y()) {
return m_data[_pos.x()+_pos.y()*m_size.x()];
}
return m_error;
}
void set(const ivec2& _pos, const ivec2& _data) {
if( _pos.x()>0 && _pos.x()<m_size.x()
&& _pos.y()>0 && _pos.y()<m_size.y()) {
m_data[_pos.x()+_pos.y()*m_size.x()] = _data;
}
}
void compare(ivec2& _data, ivec2 _pos, ivec2 _offset) {
ivec2 other = get(_pos + _offset) + _offset;
if (other.length2() < _data.length2()) {
_data = other;
}
}
void GenerateSoftDistanceField(void) {
// First pass :
for (int32_t yyy = 0; yyy < m_size.y(); ++yyy) {
for (int32_t xxx = 0; xxx < m_size.x(); ++xxx) {
ivec2 data = get(ivec2(xxx, yyy));
compare(data, ivec2(xxx, yyy), ivec2(-1, 0));
compare(data, ivec2(xxx, yyy), ivec2( 0, -1));
compare(data, ivec2(xxx, yyy), ivec2(-1, -1));
compare(data, ivec2(xxx, yyy), ivec2( 1, -1));
set(ivec2(xxx, yyy), data);
}
for (int32_t xxx = m_size.y()-1; xxx >= 0;--xxx) {
ivec2 data = get(ivec2(xxx, yyy));
compare(data, ivec2(xxx, yyy), ivec2(1, 0));
set(ivec2(xxx, yyy), data );
}
}
// Second pass
for (int32_t yyy = m_size.y()-1; yyy >= 0; --yyy) {
for (int32_t xxx = m_size.x()-1; xxx >= 0; --xxx) {
ivec2 data = get(ivec2(xxx, yyy));
compare(data, ivec2(xxx, yyy), ivec2( 1, 0));
compare(data, ivec2(xxx, yyy), ivec2( 0, 1));
compare(data, ivec2(xxx, yyy), ivec2(-1, 1));
compare(data, ivec2(xxx, yyy), ivec2( 1, 1));
set(ivec2(xxx, yyy), data );
}
for (int32_t xxx = 0; xxx < m_size.x(); ++xxx) {
ivec2 data = get(ivec2(xxx, yyy));
compare(data, ivec2(xxx, yyy), ivec2(-1, 0));
set(ivec2(xxx, yyy), data);
}
}
}
};
void ewol::resource::DistanceFieldFont::GenerateDistanceField(const egami::ImageMono& _input, egami::Image& _output) {
GirdDF myGird1(_input.getSize(), ivec2(0,0), ivec2(0, 0));
GirdDF myGird2(_input.getSize(), ivec2(0,0), ivec2(9999, 9999));
// Reformat gird :
for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) {
for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) {
if ( _input.get(ivec2(xxx, yyy)) < 128 ) {
myGird1.set(ivec2(xxx, yyy), ivec2(0, 0));
myGird2.set(ivec2(xxx, yyy), ivec2(9999, 9999));
} else {
myGird1.set(ivec2(xxx, yyy), ivec2(9999, 9999));
myGird2.set(ivec2(xxx, yyy), ivec2(0, 0));
}
}
}
// Create internal distance of the 2 layer mode :
myGird1.GenerateSoftDistanceField();
myGird2.GenerateSoftDistanceField();
// Generate output :
_output.resize(_input.getSize(), etk::Color<>(0));
_output.clear(etk::Color<>(0));
for (int32_t xxx = 0; xxx < _output.getSize().x(); ++xxx) {
for (int32_t yyy = 0; yyy < _output.getSize().y(); ++yyy) {
float dist1 = myGird1.get(ivec2(xxx, yyy)).length();
float dist2 = myGird2.get(ivec2(xxx, yyy)).length();
float dist = dist1 - dist2;
float value = etk_avg(0.0f, dist*15.0f + 128.0f, 256.0f);
_output.set(ivec2(xxx, yyy), etk::Color<>((int32_t)value,(int32_t)value,(int32_t)value,256));
}
}
}
bool ewol::resource::DistanceFieldFont::addGlyph(const char32_t& _val) { bool ewol::resource::DistanceFieldFont::addGlyph(const char32_t& _val) {
bool hasChange = false; bool hasChange = false;
if (m_font == NULL) { if (m_font == NULL) {