From 77ce541e10c2b553d6d5974b1db40159b49e486f Mon Sep 17 00:00:00 2001 From: Anuj Verma Date: Sat, 1 Aug 2020 09:26:22 +0530 Subject: [PATCH] [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. --- [GSoC]ChangeLog | 27 +++++++++++ src/sdf/ftbsdf.c | 117 +++++++++++++++++++++++------------------------ 2 files changed, 83 insertions(+), 61 deletions(-) diff --git a/[GSoC]ChangeLog b/[GSoC]ChangeLog index 4570ca395..464e146a0 100644 --- a/[GSoC]ChangeLog +++ b/[GSoC]ChangeLog @@ -1,3 +1,30 @@ +2020-08-1 Anuj Verma + + [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 * src/sdf/ftbsdf.c (compute_edge_distance): Grammer fix. diff --git a/src/sdf/ftbsdf.c b/src/sdf/ftbsdf.c index 696d54999..858d538d8 100644 --- a/src/sdf/ftbsdf.c +++ b/src/sdf/ftbsdf.c @@ -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; } }