summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuj Verma <anujv@iitbhilai.ac.in>2020-07-31 17:43:33 +0530
committeranujverma <anujv@iitbhilai.ac.in>2020-08-02 16:33:21 +0530
commit62b38d2b8541b46d02ac64c3b98448ceb6b77733 (patch)
tree29a8b888df95ff6dae289c8cb56127184aecc49f
parentdcdcc6520125ac74b63a49bc0c556f06b684f706 (diff)
downloadfreetype2-62b38d2b8541b46d02ac64c3b98448ceb6b77733.tar.gz
[sdf -> bsdf] Add explanation of the approximation.
* src/sdf/ftbsdf.c (compute_gradient => compute_edge_distance): Renamed to make sense of what the function does. Also, added the explanation of the algorithm used and a high level view of how it works. * src/sdf/ftbsdf.c (compare_neighbor): Fix a bug related to value approximation before calling `FT_Vector_Length'.
-rw-r--r--[GSoC]ChangeLog12
-rw-r--r--src/sdf/ftbsdf.c73
2 files changed, 72 insertions, 13 deletions
diff --git a/[GSoC]ChangeLog b/[GSoC]ChangeLog
index 0d8f4cf5b..ddb4a9178 100644
--- a/[GSoC]ChangeLog
+++ b/[GSoC]ChangeLog
@@ -1,3 +1,15 @@
+2020-07-31 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf -> bsdf] Add explanation of the approximation.
+
+ * src/sdf/ftbsdf.c (compute_gradient => compute_edge_distance):
+ Renamed to make sense of what the function does.
+ Also, added the explanation of the algorithm used
+ and a high level view of how it works.
+
+ * src/sdf/ftbsdf.c (compare_neighbor): Fix a bug related
+ to value approximation before calling `FT_Vector_Length'.
+
2020-07-30 Anuj Verma <anujv@iitbhilai.ac.in>
* src/sdf/ftsdfcommon.h (*): Fix line endings.
diff --git a/src/sdf/ftbsdf.c b/src/sdf/ftbsdf.c
index 101d7aa2a..e26f18cb7 100644
--- a/src/sdf/ftbsdf.c
+++ b/src/sdf/ftbsdf.c
@@ -154,7 +154,7 @@
/**************************************************************************
*
* @Function:
- * compute_gradient
+ * compute_edge_distance
*
* @Description:
* [TODO]
@@ -166,13 +166,46 @@
* [TODO]
*/
static FT_16D16_Vec
- compute_gradient( ED* current,
- FT_Int x,
- FT_Int y,
- FT_Int w,
- FT_Int r )
+ compute_edge_distance( ED* current,
+ FT_Int x,
+ FT_Int y,
+ FT_Int w,
+ FT_Int r )
{
- /* [TODO]: Write proper explanation. */
+ /* This is the function which is based on the paper presented */
+ /* by Stefan Gustavson and Robin Strand which is used to app- */
+ /* roximate edge distance from anti-aliased bitmaps. */
+ /* */
+ /* The algorithm is as follows: */
+ /* */
+ /* * In anti-aliased images, the pixel's alpha value is the */
+ /* coverage of the pixel by the outline. For example if the */
+ /* alpha value is 0.5f then we can assume the the outline */
+ /* passes through the center of the pixel. */
+ /* */
+ /* * So, we can use that alpha value to approximate the real */
+ /* distance of the pixel to edge pretty accurately. A real */
+ /* simple approximation is ( 0.5f - alpha ), assuming that */
+ /* the outline is parallel to the x or y axis. But in this */
+ /* algorithm that is pretty accurate the edge distance. */
+ /* */
+ /* * The only remaining piece of information that we cannot */
+ /* approximate directly from the alpha is the direction of */
+ /* the edge. That is where we use the Sobel's operator to */
+ /* compute the gradient of the pixel. The gradient give us */
+ /* a pretty good approximation of the edge direction. */
+ /* We use a 3x3 kernel filter to compute the gradient. */
+ /* */
+ /* * After the above two steps we have both the direction and */
+ /* the distance to the edge which is used to generate the */
+ /* Signed Distance Field. */
+ /* */
+ /* References: */
+ /* * Anti-Aliased Euclidean Distance Transform: */
+ /* http://weber.itn.liu.se/~stegu/aadist/edtaa_preprint.pdf */
+ /* * Sobel Operator: */
+ /* https://en.wikipedia.org/wiki/Sobel_operator */
+ /* */
FT_16D16_Vec g = { 0, 0 };
FT_16D16 dist;
FT_16D16 a1, temp;
@@ -184,7 +217,18 @@
return g;
- /* compute the gradient */
+ /* Compute the gradient using the Sobel operator. */
+ /* In this case we use the following 3x3 filters: */
+ /* */
+ /* For x: | -1 0 -1 | */
+ /* | -root(2) 0 root(2) | */
+ /* | -1 0 1 | */
+ /* */
+ /* For y: | -1 -root(2) -1 | */
+ /* | 0 0 0 | */
+ /* | 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 +
@@ -260,7 +304,6 @@
static FT_Error
bsdf_approximate_edge( BSDF_Worker* worker )
{
- /* [TODO]: Write proper explanation. */
FT_Error error = FT_Err_Ok;
FT_Int i, j;
FT_Int index;
@@ -282,7 +325,8 @@
index = j * worker->width + i;
if ( ed[index].dist != 0 )
- ed[index].near = compute_gradient( ed + index, i, j,
+ /* approximate the edge distance */
+ ed[index].near = compute_edge_distance( ed + index, i, j,
worker->width, worker->rows );
}
}
@@ -294,6 +338,8 @@
{
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;
@@ -449,7 +495,7 @@
pixel_value = 256;
/* only assign values to the edge pixels */
- if ( bsdf_is_edge( s + s_index , s_i, s_j, s_width, s_rows ) )
+ if ( pixel_value )
t[t_index].dist = 256 * pixel_value;
/* We assume that if the pixel is inside a contour */
@@ -510,8 +556,9 @@
/* Of course this will be eliminated while using */
/* squared distances. */
- /* approximate the distance */
- dist = to_check->dist + ( FT_ABS( x_offset ) + FT_ABS( y_offset ) ) * ONE;
+ /* Approximate the distance, use 1 to avoid */
+ /* precision errors. */
+ dist = to_check->dist + ONE;
if ( dist < current->dist )
{