forked from minhngoc25a/freetype2
[sdf -> bsdf] Optimized a bit.
* src/sdf/ftbsdf.c (ED: sign => alpha): Renamed sign to alphs. This is used to store the alpha of the current pixel mapped to the source image. This let's us store additional information without increasing memory usage. * src/sdf/ftbsdf.c (bsdf_init_distance_map): Removed any/all kind of edge approximation and edge check from the function. The function simply copy the source bitmap to the distance map now, preserving alpha values. * src/sdf/ftbsdf.c (compute_edge_distance): Use the new `alpha' parameter to compute gradient and approximate distance. Previously we were using the `dist' variable to store alpha values, which restricts modifying the `dist' variable because we need alpha values of neighbor to compute the gradient. * src/sdf/ftbsdf.c (bsdf_approximate_edge): Now that we can modify the `dist' variable of the distance map, we can combine the two nested loops. * src/sdf/ftbsdf.c (finalize_sdf): Move the `sign' determination and assignment to this function.
This commit is contained in:
parent
185c88905e
commit
77ce541e10
|
@ -1,3 +1,30 @@
|
||||||
|
2020-08-1 Anuj Verma <anujv@iitbhilai.ac.in>
|
||||||
|
|
||||||
|
[sdf -> bsdf] Optimized a bit.
|
||||||
|
|
||||||
|
* src/sdf/ftbsdf.c (ED: sign => alpha): Renamed sign
|
||||||
|
to alphs. This is used to store the alpha of the current
|
||||||
|
pixel mapped to the source image. This let's us store
|
||||||
|
additional information without increasing memory usage.
|
||||||
|
|
||||||
|
* src/sdf/ftbsdf.c (bsdf_init_distance_map): Removed any/all
|
||||||
|
kind of edge approximation and edge check from the function.
|
||||||
|
The function simply copy the source bitmap to the distance
|
||||||
|
map now, preserving alpha values.
|
||||||
|
|
||||||
|
* src/sdf/ftbsdf.c (compute_edge_distance): Use the new `alpha'
|
||||||
|
parameter to compute gradient and approximate distance.
|
||||||
|
Previously we were using the `dist' variable to store alpha
|
||||||
|
values, which restricts modifying the `dist' variable because
|
||||||
|
we need alpha values of neighbor to compute the gradient.
|
||||||
|
|
||||||
|
* src/sdf/ftbsdf.c (bsdf_approximate_edge): Now that we can
|
||||||
|
modify the `dist' variable of the distance map, we can
|
||||||
|
combine the two nested loops.
|
||||||
|
|
||||||
|
* src/sdf/ftbsdf.c (finalize_sdf): Move the `sign' determination
|
||||||
|
and assignment to this function.
|
||||||
|
|
||||||
2020-07-31 Anuj Verma <anujv@iitbhilai.ac.in>
|
2020-07-31 Anuj Verma <anujv@iitbhilai.ac.in>
|
||||||
|
|
||||||
* src/sdf/ftbsdf.c (compute_edge_distance): Grammer fix.
|
* src/sdf/ftbsdf.c (compute_edge_distance): Grammer fix.
|
||||||
|
|
117
src/sdf/ftbsdf.c
117
src/sdf/ftbsdf.c
|
@ -32,9 +32,9 @@
|
||||||
/* can also be interpreted as edge distance. */
|
/* can also be interpreted as edge distance. */
|
||||||
typedef struct ED_
|
typedef struct ED_
|
||||||
{
|
{
|
||||||
FT_16D16 dist; /* distance at `near' */
|
FT_16D16 dist; /* distance at `near' */
|
||||||
FT_16D16_Vec near; /* nearest point */
|
FT_16D16_Vec near; /* nearest point */
|
||||||
FT_Char sign; /* outside or inside */
|
FT_Byte alpha; /* alpha of the source */
|
||||||
|
|
||||||
} ED;
|
} ED;
|
||||||
|
|
||||||
|
@ -208,15 +208,33 @@
|
||||||
/* https://en.wikipedia.org/wiki/Sobel_operator */
|
/* https://en.wikipedia.org/wiki/Sobel_operator */
|
||||||
/* */
|
/* */
|
||||||
FT_16D16_Vec g = { 0, 0 };
|
FT_16D16_Vec g = { 0, 0 };
|
||||||
FT_16D16 dist;
|
FT_16D16 dist, current_alpha;
|
||||||
FT_16D16 a1, temp;
|
FT_16D16 a1, temp;
|
||||||
FT_16D16 gx, gy;
|
FT_16D16 gx, gy;
|
||||||
|
FT_16D16 alphas[9];
|
||||||
|
|
||||||
|
|
||||||
|
if ( x == 41 && y == 72 )
|
||||||
|
gx = 0;
|
||||||
|
|
||||||
|
/* Since our spread cannot be 0, this condition */
|
||||||
|
/* can never be true. */
|
||||||
if ( x <= 0 || x >= w - 1 ||
|
if ( x <= 0 || x >= w - 1 ||
|
||||||
y <= 0 || y >= r - 1 )
|
y <= 0 || y >= r - 1 )
|
||||||
return g;
|
return g;
|
||||||
|
|
||||||
|
/* initialize the alphas */
|
||||||
|
alphas[0] = 256 * (FT_16D16)current[-w - 1].alpha;
|
||||||
|
alphas[1] = 256 * (FT_16D16)current[ -w ].alpha;
|
||||||
|
alphas[2] = 256 * (FT_16D16)current[-w + 1].alpha;
|
||||||
|
alphas[3] = 256 * (FT_16D16)current[ -1 ].alpha;
|
||||||
|
alphas[4] = 256 * (FT_16D16)current[ 0 ].alpha;
|
||||||
|
alphas[5] = 256 * (FT_16D16)current[ 1 ].alpha;
|
||||||
|
alphas[6] = 256 * (FT_16D16)current[ w - 1].alpha;
|
||||||
|
alphas[7] = 256 * (FT_16D16)current[ w ].alpha;
|
||||||
|
alphas[8] = 256 * (FT_16D16)current[ w + 1].alpha;
|
||||||
|
|
||||||
|
current_alpha = alphas[4];
|
||||||
|
|
||||||
/* Compute the gradient using the Sobel operator. */
|
/* Compute the gradient using the Sobel operator. */
|
||||||
/* In this case we use the following 3x3 filters: */
|
/* In this case we use the following 3x3 filters: */
|
||||||
|
@ -230,19 +248,19 @@
|
||||||
/* | 1 root(2) 1 | */
|
/* | 1 root(2) 1 | */
|
||||||
/* */
|
/* */
|
||||||
/* [Note]: 92681 is nothing but root(2) in 16.16 */
|
/* [Note]: 92681 is nothing but root(2) in 16.16 */
|
||||||
g.x = - current[-w - 1].dist -
|
g.x = -alphas[0] -
|
||||||
FT_MulFix( current[-1].dist, 92681 ) -
|
FT_MulFix( alphas[3], 92681 ) -
|
||||||
current[ w - 1].dist +
|
alphas[6] +
|
||||||
current[-w + 1].dist +
|
alphas[2] +
|
||||||
FT_MulFix( current[1].dist, 92681 ) +
|
FT_MulFix( alphas[5], 92681 ) +
|
||||||
current[ w + 1].dist;
|
alphas[8];
|
||||||
|
|
||||||
g.y = - current[-w - 1].dist -
|
g.y = -alphas[0] -
|
||||||
FT_MulFix( current[-w].dist, 92681 ) -
|
FT_MulFix( alphas[1], 92681 ) -
|
||||||
current[-w + 1].dist +
|
alphas[2] +
|
||||||
current[ w - 1].dist +
|
alphas[6] +
|
||||||
FT_MulFix( current[w].dist, 92681 ) +
|
FT_MulFix( alphas[7], 92681 ) +
|
||||||
current[ w + 1].dist;
|
alphas[8];
|
||||||
|
|
||||||
FT_Vector_NormLen( &g );
|
FT_Vector_NormLen( &g );
|
||||||
|
|
||||||
|
@ -253,7 +271,7 @@
|
||||||
|
|
||||||
/* [TODO]: Add squared distance support. */
|
/* [TODO]: Add squared distance support. */
|
||||||
if ( g.x == 0 || g.y == 0 )
|
if ( g.x == 0 || g.y == 0 )
|
||||||
dist = ONE / 2 - current->dist;
|
dist = ONE / 2 - alphas[4];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gx = g.x;
|
gx = g.x;
|
||||||
|
@ -270,16 +288,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
a1 = FT_DivFix( gy, gx ) / 2;
|
a1 = FT_DivFix( gy, gx ) / 2;
|
||||||
if ( current->dist < a1 )
|
if ( current_alpha < a1 )
|
||||||
dist = (( gx + gy ) / 2) -
|
dist = (( gx + gy ) / 2) -
|
||||||
square_root( 2 * FT_MulFix( gx,
|
square_root( 2 * FT_MulFix( gx,
|
||||||
FT_MulFix( gy, current->dist ) ) );
|
FT_MulFix( gy, current_alpha ) ) );
|
||||||
else if ( current->dist < ( ONE - a1 ) )
|
else if ( current_alpha < ( ONE - a1 ) )
|
||||||
dist = FT_MulFix( ONE / 2 - current->dist, gx );
|
dist = FT_MulFix( ONE / 2 - current_alpha, gx );
|
||||||
else
|
else
|
||||||
dist = -(( gx + gy ) / 2) +
|
dist = -(( gx + gy ) / 2) +
|
||||||
square_root( 2 * FT_MulFix( gx,
|
square_root( 2 * FT_MulFix( gx,
|
||||||
FT_MulFix( gy, ONE - current->dist ) ) );
|
FT_MulFix( gy, ONE - current_alpha ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
g.x = FT_MulFix( g.x, dist );
|
g.x = FT_MulFix( g.x, dist );
|
||||||
|
@ -325,30 +343,20 @@
|
||||||
{
|
{
|
||||||
index = j * worker->width + i;
|
index = j * worker->width + i;
|
||||||
|
|
||||||
if ( ed[index].dist != 0 )
|
/* [TODO]: Check if the current pixel is edge. */
|
||||||
|
if ( ed[index].alpha != 0 )
|
||||||
|
{
|
||||||
/* approximate the edge distance */
|
/* approximate the edge distance */
|
||||||
ed[index].near = compute_edge_distance( ed + index, i, j,
|
ed[index].near = compute_edge_distance( ed + index, i, j,
|
||||||
worker->width, worker->rows );
|
worker->width, worker->rows );
|
||||||
}
|
ed[index].dist = FT_Vector_Length( &ed[index].near );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* [TODO]: Try to combine the above and below loops. */
|
{
|
||||||
for ( j = 0; j < worker->rows; j++ )
|
|
||||||
{
|
|
||||||
for ( i = 0; i < worker->width; i++ )
|
|
||||||
{
|
|
||||||
index = j * worker->width + i;
|
|
||||||
|
|
||||||
/* Assign the values, for bacground pixel assign */
|
|
||||||
/* values vert far away. */
|
|
||||||
if ( ed[index].dist == 0 )
|
|
||||||
{
|
|
||||||
ed[index].dist = 200 * ONE;
|
ed[index].dist = 200 * ONE;
|
||||||
ed[index].near.x = 100 * ONE;
|
ed[index].near.x = 100 * ONE;
|
||||||
ed[index].near.y = 100 * ONE;
|
ed[index].near.y = 100 * ONE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ed[index].dist = FT_Vector_Length( &ed[index].near );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +475,6 @@
|
||||||
{
|
{
|
||||||
FT_Int t_index = t_j * t_width + t_i;
|
FT_Int t_index = t_j * t_width + t_i;
|
||||||
FT_Int s_index;
|
FT_Int s_index;
|
||||||
FT_Int pixel_value;
|
|
||||||
|
|
||||||
|
|
||||||
t[t_index] = zero_ed;
|
t[t_index] = zero_ed;
|
||||||
|
@ -479,32 +486,15 @@
|
||||||
/* the source bitmap. */
|
/* the source bitmap. */
|
||||||
if ( s_i < 0 || s_i >= s_width ||
|
if ( s_i < 0 || s_i >= s_width ||
|
||||||
s_j < 0 || s_j >= s_rows )
|
s_j < 0 || s_j >= s_rows )
|
||||||
{
|
|
||||||
t[t_index].sign = -1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if ( worker->params.flip_y )
|
if ( worker->params.flip_y )
|
||||||
s_index = ( s_rows - s_j - 1 ) * s_width + s_i;
|
s_index = ( s_rows - s_j - 1 ) * s_width + s_i;
|
||||||
else
|
else
|
||||||
s_index = s_j * s_width + s_i;
|
s_index = s_j * s_width + s_i;
|
||||||
|
|
||||||
pixel_value = (FT_Int)s[s_index];
|
/* simply copy the alpha values */
|
||||||
|
t[t_index].alpha = s[s_index];
|
||||||
/* clamp the pixel value to [0, 256] */
|
|
||||||
if ( pixel_value == 255 )
|
|
||||||
pixel_value = 256;
|
|
||||||
|
|
||||||
/* only assign values to the edge pixels */
|
|
||||||
if ( pixel_value )
|
|
||||||
t[t_index].dist = 256 * pixel_value;
|
|
||||||
|
|
||||||
/* We assume that if the pixel is inside a contour */
|
|
||||||
/* then it's coverage value must be > 127. */
|
|
||||||
if ( pixel_value > 127 )
|
|
||||||
t[t_index].sign = 1;
|
|
||||||
else
|
|
||||||
t[t_index].sign = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,6 +795,7 @@
|
||||||
FT_Int index;
|
FT_Int index;
|
||||||
FT_16D16 dist;
|
FT_16D16 dist;
|
||||||
FT_6D10 final_dist;
|
FT_6D10 final_dist;
|
||||||
|
FT_Char sign;
|
||||||
|
|
||||||
|
|
||||||
index = j * w + i;
|
index = j * w + i;
|
||||||
|
@ -818,7 +809,11 @@
|
||||||
if ( final_dist > worker->params.spread * 1024 )
|
if ( final_dist > worker->params.spread * 1024 )
|
||||||
final_dist = worker->params.spread * 1024;
|
final_dist = worker->params.spread * 1024;
|
||||||
|
|
||||||
t_buffer[index] = final_dist * worker->distance_map[index].sign;
|
/* We assume that if the pixel is inside a contour */
|
||||||
|
/* then it's coverage value must be > 127. */
|
||||||
|
sign = worker->distance_map[index].alpha < 127 ? -1 : 1;
|
||||||
|
|
||||||
|
t_buffer[index] = final_dist * sign;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue