[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:
Anuj Verma 2020-08-01 09:26:22 +05:30 committed by anujverma
parent 185c88905e
commit 77ce541e10
2 changed files with 83 additions and 61 deletions

View File

@ -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>
* src/sdf/ftbsdf.c (compute_edge_distance): Grammer fix.

View File

@ -32,9 +32,9 @@
/* can also be interpreted as edge distance. */
typedef struct ED_
{
FT_16D16 dist; /* distance at `near' */
FT_16D16_Vec near; /* nearest point */
FT_Char sign; /* outside or inside */
FT_16D16 dist; /* distance at `near' */
FT_16D16_Vec near; /* nearest point */
FT_Byte alpha; /* alpha of the source */
} ED;
@ -208,15 +208,33 @@
/* https://en.wikipedia.org/wiki/Sobel_operator */
/* */
FT_16D16_Vec g = { 0, 0 };
FT_16D16 dist;
FT_16D16 dist, current_alpha;
FT_16D16 a1, temp;
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 ||
y <= 0 || y >= r - 1 )
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. */
/* In this case we use the following 3x3 filters: */
@ -230,19 +248,19 @@
/* | 1 root(2) 1 | */
/* */
/* [Note]: 92681 is nothing but root(2) in 16.16 */
g.x = - current[-w - 1].dist -
FT_MulFix( current[-1].dist, 92681 ) -
current[ w - 1].dist +
current[-w + 1].dist +
FT_MulFix( current[1].dist, 92681 ) +
current[ w + 1].dist;
g.x = -alphas[0] -
FT_MulFix( alphas[3], 92681 ) -
alphas[6] +
alphas[2] +
FT_MulFix( alphas[5], 92681 ) +
alphas[8];
g.y = - current[-w - 1].dist -
FT_MulFix( current[-w].dist, 92681 ) -
current[-w + 1].dist +
current[ w - 1].dist +
FT_MulFix( current[w].dist, 92681 ) +
current[ w + 1].dist;
g.y = -alphas[0] -
FT_MulFix( alphas[1], 92681 ) -
alphas[2] +
alphas[6] +
FT_MulFix( alphas[7], 92681 ) +
alphas[8];
FT_Vector_NormLen( &g );
@ -253,7 +271,7 @@
/* [TODO]: Add squared distance support. */
if ( g.x == 0 || g.y == 0 )
dist = ONE / 2 - current->dist;
dist = ONE / 2 - alphas[4];
else
{
gx = g.x;
@ -270,16 +288,16 @@
}
a1 = FT_DivFix( gy, gx ) / 2;
if ( current->dist < a1 )
if ( current_alpha < a1 )
dist = (( gx + gy ) / 2) -
square_root( 2 * FT_MulFix( gx,
FT_MulFix( gy, current->dist ) ) );
else if ( current->dist < ( ONE - a1 ) )
dist = FT_MulFix( ONE / 2 - current->dist, gx );
FT_MulFix( gy, current_alpha ) ) );
else if ( current_alpha < ( ONE - a1 ) )
dist = FT_MulFix( ONE / 2 - current_alpha, gx );
else
dist = -(( gx + gy ) / 2) +
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 );
@ -325,30 +343,20 @@
{
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 */
ed[index].near = compute_edge_distance( ed + index, i, j,
worker->width, worker->rows );
}
}
/* [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 = FT_Vector_Length( &ed[index].near );
}
else
{
ed[index].dist = 200 * 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 s_index;
FT_Int pixel_value;
t[t_index] = zero_ed;
@ -479,32 +486,15 @@
/* the source bitmap. */
if ( s_i < 0 || s_i >= s_width ||
s_j < 0 || s_j >= s_rows )
{
t[t_index].sign = -1;
continue;
}
if ( worker->params.flip_y )
s_index = ( s_rows - s_j - 1 ) * s_width + s_i;
else
s_index = s_j * s_width + s_i;
pixel_value = (FT_Int)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;
/* simply copy the alpha values */
t[t_index].alpha = s[s_index];
}
}
@ -805,6 +795,7 @@
FT_Int index;
FT_16D16 dist;
FT_6D10 final_dist;
FT_Char sign;
index = j * w + i;
@ -818,7 +809,11 @@
if ( 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;
}
}