forked from minhngoc25a/freetype2
[sdf -> bsdf] Added function to approximate edge distance.
* src/sdf/ftbsdf.c (bsdf_approximate_edge): The function uses the Gustavson's algorithm to approximate the edge from pixel values. * src/sdf/ftbsdf.c (compute_gradient): The function uses Sobel's operator to compute the gradient at a pixel. The is used to detect edge direction.
This commit is contained in:
parent
ffb6890089
commit
fbbec7c64d
|
@ -1,3 +1,15 @@
|
|||
2020-07-29 Anuj Verma <anujv@iitbhilai.ac.in>
|
||||
|
||||
[sdf -> bsdf] Added function to approximate edge distance.
|
||||
|
||||
* src/sdf/ftbsdf.c (bsdf_approximate_edge): The function
|
||||
uses the Gustavson's algorithm to approximate the edge
|
||||
from pixel values.
|
||||
|
||||
* src/sdf/ftbsdf.c (compute_gradient): The function uses
|
||||
Sobel's operator to compute the gradient at a pixel.
|
||||
The is used to detect edge direction.
|
||||
|
||||
2020-07-28 Anuj Verma <anujv@iitbhilai.ac.in>
|
||||
|
||||
* src/sdf/ftbsdf.c (_pass): Use function for repetitive task.
|
||||
|
|
157
src/sdf/ftbsdf.c
157
src/sdf/ftbsdf.c
|
@ -47,7 +47,8 @@
|
|||
|
||||
} BSDF_TRaster;
|
||||
|
||||
/* euclidean distance used for euclidean distance transform */
|
||||
/* Euclidean distance used for euclidean distance transform */
|
||||
/* can also be interpreted as edge distance. */
|
||||
typedef struct ED_
|
||||
{
|
||||
FT_16D16 dist; /* distance at `near' */
|
||||
|
@ -126,12 +127,15 @@
|
|||
FT_Int num_neighbour = 0;
|
||||
|
||||
|
||||
if ( y == 7 && x == 20 )
|
||||
to_check = NULL;
|
||||
|
||||
if ( *s == 0 )
|
||||
goto Done;
|
||||
|
||||
if ( *s > 0 && *s < 255 )
|
||||
{
|
||||
is_edge = 1;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* up */
|
||||
CHECK_NEIGHBOR( 0, -1 );
|
||||
|
||||
|
@ -166,6 +170,122 @@
|
|||
|
||||
#undef CHECK_NEIGHBOR
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
* compute_gradient
|
||||
*
|
||||
* @Description:
|
||||
* [TODO]
|
||||
*
|
||||
* @Input:
|
||||
* [TODO]
|
||||
*
|
||||
* @Return:
|
||||
* [TODO]
|
||||
*/
|
||||
static FT_16D16_Vec
|
||||
compute_gradient( ED* current,
|
||||
FT_Int x,
|
||||
FT_Int y,
|
||||
FT_Int w,
|
||||
FT_Int r )
|
||||
{
|
||||
/* [TODO]: Write proper explanation. */
|
||||
FT_16D16_Vec g = { 0, 0 };
|
||||
|
||||
|
||||
if ( x <= 0 || x >= w - 1 ||
|
||||
y <= 0 || y >= r - 1 )
|
||||
return g;
|
||||
|
||||
|
||||
g.x = - current[-w - 1].dist -
|
||||
2 * current[ -1 ].dist -
|
||||
current[ w - 1].dist +
|
||||
current[-w + 1].dist +
|
||||
2 * current[ 1 ].dist +
|
||||
current[ w + 1].dist;
|
||||
|
||||
g.y = - current[-w - 1].dist -
|
||||
2 * current[ -w ].dist -
|
||||
current[-w + 1].dist +
|
||||
current[ w - 1].dist +
|
||||
2 * current[ w ].dist +
|
||||
current[ w + 1].dist;
|
||||
|
||||
FT_Vector_NormLen( &g );
|
||||
g.x = FT_MulFix( g.x, ONE / 2 - current->dist );
|
||||
g.y = FT_MulFix( g.y, ONE / 2 - current->dist );
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
* bsdf_approximate_edge
|
||||
*
|
||||
* @Description:
|
||||
* [TODO]
|
||||
*
|
||||
* @Input:
|
||||
* [TODO]
|
||||
*
|
||||
* @Return:
|
||||
* [TODO]
|
||||
*/
|
||||
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;
|
||||
ED* ed;
|
||||
|
||||
|
||||
if ( !worker || !worker->distance_map )
|
||||
{
|
||||
error = FT_THROW( Invalid_Argument );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ed = worker->distance_map;
|
||||
|
||||
for ( j = 0; j < worker->rows; j++ )
|
||||
{
|
||||
for ( i = 0; i < worker->width; i++ )
|
||||
{
|
||||
index = j * worker->width + i;
|
||||
|
||||
if ( ed[index].dist != 0 )
|
||||
ed[index].near = compute_gradient( ed + index, i, j,
|
||||
worker->width, worker->rows );
|
||||
}
|
||||
}
|
||||
|
||||
for ( j = 0; j < worker->rows; j++ )
|
||||
{
|
||||
for ( i = 0; i < worker->width; i++ )
|
||||
{
|
||||
index = j * worker->width + i;
|
||||
|
||||
if ( ed[index].dist == 0 )
|
||||
{
|
||||
ed[index].dist = 200 * ONE;
|
||||
ed[index].near.x = 100 * ONE;
|
||||
ed[index].near.y = 100 * ONE;
|
||||
}
|
||||
else
|
||||
ed[index].dist = FT_Vector_Length( &ed[index].near );
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
|
@ -277,7 +397,7 @@
|
|||
{
|
||||
FT_Int t_index = t_j * t_width + t_i;
|
||||
FT_Int s_index;
|
||||
FT_Byte pixel_value;
|
||||
FT_Int pixel_value;
|
||||
|
||||
|
||||
t[t_index] = zero_ed;
|
||||
|
@ -290,10 +410,7 @@
|
|||
if ( s_i < 0 || s_i >= s_width ||
|
||||
s_j < 0 || s_j >= s_rows )
|
||||
{
|
||||
t[t_index].near.x = FT_INT_MAX;
|
||||
t[t_index].near.y = FT_INT_MAX;
|
||||
t[t_index].dist = 128 * ONE;
|
||||
t[t_index].sign = -1;
|
||||
t[t_index].sign = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -302,20 +419,19 @@
|
|||
else
|
||||
s_index = s_j * s_width + s_i;
|
||||
|
||||
pixel_value = s[s_index];
|
||||
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 ( bsdf_is_edge( s + s_index , s_i, s_j, s_width, s_rows ) )
|
||||
{
|
||||
t[t_index].dist = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
t[t_index].near.x = FT_INT_MAX;
|
||||
t[t_index].near.y = FT_INT_MAX;
|
||||
t[t_index].dist = 128 * ONE;
|
||||
}
|
||||
t[t_index].dist = 256 * pixel_value;
|
||||
|
||||
if ( 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;
|
||||
|
@ -765,6 +881,7 @@
|
|||
worker.params = *sdf_params;
|
||||
|
||||
FT_CALL( bsdf_init_distance_map( source, &worker ) );
|
||||
FT_CALL( bsdf_approximate_edge( &worker ) );
|
||||
FT_CALL( edt8( &worker ) );
|
||||
FT_CALL( finalize_sdf( &worker, target ) );
|
||||
|
||||
|
|
Loading…
Reference in New Issue