From 2792757cc3a1c92c4d20042ac926481d946d7771 Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Fri, 8 Nov 2013 19:25:20 +0000 Subject: Improve blur quality: use volume 65536 and initialize left column --- libass/ass_bitmap.c | 70 ++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 0ad1647..4c6bd14 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -30,7 +30,7 @@ struct ass_synth_priv { int tmp_w, tmp_h; - unsigned short *tmp; + unsigned *tmp; int g_r; int g_w; @@ -41,7 +41,6 @@ struct ass_synth_priv { double radius; }; -static const unsigned int maxcolor = 255; static const unsigned base = 256; static int generate_tables(ASS_SynthPriv *priv, double radius) @@ -68,7 +67,7 @@ static int generate_tables(ASS_SynthPriv *priv, double radius) } if (priv->g_r) { - // gaussian curve with volume = 256 + // gaussian curve with volume = 65536 for (volume_diff = 10000000; volume_diff > 0.0000001; volume_diff *= 0.5) { volume_factor += volume_diff; @@ -79,7 +78,7 @@ static int generate_tables(ASS_SynthPriv *priv, double radius) volume_factor + .5); volume += priv->g[i]; } - if (volume > 256) + if (volume > 65536) volume_factor -= volume_diff; } volume = 0; @@ -114,7 +113,7 @@ static void resize_tmp(ASS_SynthPriv *priv, int w, int h) while (priv->tmp_h < h) priv->tmp_h *= 2; free(priv->tmp); - priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short)); + priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(unsigned)); } ASS_SynthPriv *ass_synth_init(double radius) @@ -302,24 +301,25 @@ static void shift_bitmap(Bitmap *bm, int shift_x, int shift_y) /* * Gaussian blur. An fast pure C implementation from MPlayer. */ -static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, - int width, int height, int stride, int *m2, - int r, int mwidth) +static void ass_gauss_blur(unsigned char *buffer, unsigned *tmp2, + int width, int height, int stride, + unsigned *m2, int r, int mwidth) { int x, y; unsigned char *s = buffer; - unsigned short *t = tmp2 + 1; + unsigned *t = tmp2 + 1; for (y = 0; y < height; y++) { - memset(t - 1, 0, (width + 1) * sizeof(short)); + memset(t - 1, 0, (width + 1) * sizeof(unsigned)); + t[-1] = 32768; for (x = 0; x < r; x++) { const int src = s[x]; if (src) { - register unsigned short *dstp = t + x - r; + register unsigned *dstp = t + x - r; int mx; - unsigned *m3 = (unsigned *) (m2 + src * mwidth); + unsigned *m3 = m2 + src * mwidth; for (mx = r - x; mx < mwidth; mx++) { dstp[mx] += m3[mx]; } @@ -329,9 +329,9 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, for (; x < width - r; x++) { const int src = s[x]; if (src) { - register unsigned short *dstp = t + x - r; + register unsigned *dstp = t + x - r; int mx; - unsigned *m3 = (unsigned *) (m2 + src * mwidth); + unsigned *m3 = m2 + src * mwidth; for (mx = 0; mx < mwidth; mx++) { dstp[mx] += m3[mx]; } @@ -341,10 +341,10 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, for (; x < width; x++) { const int src = s[x]; if (src) { - register unsigned short *dstp = t + x - r; + register unsigned *dstp = t + x - r; int mx; const int x2 = r + width - x; - unsigned *m3 = (unsigned *) (m2 + src * mwidth); + unsigned *m3 = m2 + src * mwidth; for (mx = 0; mx < x2; mx++) { dstp[mx] += m3[mx]; } @@ -358,15 +358,15 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, t = tmp2; for (x = 0; x < width; x++) { for (y = 0; y < r; y++) { - unsigned short *srcp = t + y * (width + 1) + 1; + unsigned *srcp = t + y * (width + 1) + 1; int src = *srcp; if (src) { - register unsigned short *dstp = srcp - 1 + width + 1; - const int src2 = (src + 128) >> 8; - unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); + register unsigned *dstp = srcp - 1 + width + 1; + const int src2 = (src + 32768) >> 16; + unsigned *m3 = m2 + src2 * mwidth; int mx; - *srcp = 128; + *srcp = 32768; for (mx = r - 1; mx < mwidth; mx++) { *dstp += m3[mx]; dstp += width + 1; @@ -374,15 +374,15 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, } } for (; y < height - r; y++) { - unsigned short *srcp = t + y * (width + 1) + 1; + unsigned *srcp = t + y * (width + 1) + 1; int src = *srcp; if (src) { - register unsigned short *dstp = srcp - 1 - r * (width + 1); - const int src2 = (src + 128) >> 8; - unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); + register unsigned *dstp = srcp - 1 - r * (width + 1); + const int src2 = (src + 32768) >> 16; + unsigned *m3 = m2 + src2 * mwidth; int mx; - *srcp = 128; + *srcp = 32768; for (mx = 0; mx < mwidth; mx++) { *dstp += m3[mx]; dstp += width + 1; @@ -390,16 +390,16 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, } } for (; y < height; y++) { - unsigned short *srcp = t + y * (width + 1) + 1; + unsigned *srcp = t + y * (width + 1) + 1; int src = *srcp; if (src) { const int y2 = r + height - y; - register unsigned short *dstp = srcp - 1 - r * (width + 1); - const int src2 = (src + 128) >> 8; - unsigned *m3 = (unsigned *) (m2 + src2 * mwidth); + register unsigned *dstp = srcp - 1 - r * (width + 1); + const int src2 = (src + 32768) >> 16; + unsigned *m3 = m2 + src2 * mwidth; int mx; - *srcp = 128; + *srcp = 32768; for (mx = 0; mx < y2; mx++) { *dstp += m3[mx]; dstp += width + 1; @@ -413,7 +413,7 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2, s = buffer; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - s[x] = t[x] >> 8; + s[x] = t[x] >> 16; } s += stride; t += width + 1; @@ -499,13 +499,11 @@ int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur, if (*bm_o) ass_gauss_blur((*bm_o)->buffer, priv_blur->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->stride, - (int *) priv_blur->gt2, priv_blur->g_r, - priv_blur->g_w); + priv_blur->gt2, priv_blur->g_r, priv_blur->g_w); if (!*bm_o || border_style == 3) ass_gauss_blur((*bm_g)->buffer, priv_blur->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->stride, - (int *) priv_blur->gt2, priv_blur->g_r, - priv_blur->g_w); + priv_blur->gt2, priv_blur->g_r, priv_blur->g_w); } // Create shadow and fix outline as needed -- cgit v1.2.3 From f226ef125da564ead8e6188c897b8ba328b47652 Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Sun, 10 Nov 2013 22:11:18 +0000 Subject: Speed up \blur table generation Based on xy-VSFilter commit 54391d3a. --- libass/ass_bitmap.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 4c6bd14..6dbc30c 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -35,6 +35,7 @@ struct ass_synth_priv { int g_r; int g_w; + double *g0; unsigned *g; unsigned *gt2; @@ -59,6 +60,7 @@ static int generate_tables(ASS_SynthPriv *priv, double radius) priv->g_w = 2 * priv->g_r + 1; if (priv->g_r) { + priv->g0 = realloc(priv->g0, priv->g_w * sizeof(double)); priv->g = realloc(priv->g, priv->g_w * sizeof(unsigned)); priv->gt2 = realloc(priv->gt2, 256 * priv->g_w * sizeof(unsigned)); if (priv->g == NULL || priv->gt2 == NULL) { @@ -67,15 +69,18 @@ static int generate_tables(ASS_SynthPriv *priv, double radius) } if (priv->g_r) { - // gaussian curve with volume = 65536 + // exact gaussian curve + for (i = 0; i < priv->g_w; ++i) { + priv->g0[i] = exp(A * (i - priv->g_r) * (i - priv->g_r)); + } + + // integer gaussian curve with volume = 65536 for (volume_diff = 10000000; volume_diff > 0.0000001; volume_diff *= 0.5) { volume_factor += volume_diff; volume = 0; for (i = 0; i < priv->g_w; ++i) { - priv->g[i] = - (unsigned) (exp(A * (i - priv->g_r) * (i - priv->g_r)) * - volume_factor + .5); + priv->g[i] = (unsigned) (priv->g0[i] * volume_factor + .5); volume += priv->g[i]; } if (volume > 65536) @@ -83,9 +88,7 @@ static int generate_tables(ASS_SynthPriv *priv, double radius) } volume = 0; for (i = 0; i < priv->g_w; ++i) { - priv->g[i] = - (unsigned) (exp(A * (i - priv->g_r) * (i - priv->g_r)) * - volume_factor + .5); + priv->g[i] = (unsigned) (priv->g0[i] * volume_factor + .5); volume += priv->g[i]; } @@ -126,6 +129,7 @@ ASS_SynthPriv *ass_synth_init(double radius) void ass_synth_done(ASS_SynthPriv *priv) { free(priv->tmp); + free(priv->g0); free(priv->g); free(priv->gt2); free(priv); -- cgit v1.2.3 From 02487cc506e9f59eb7d824e30c4b8a577fd71b15 Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Tue, 17 Dec 2013 21:39:23 +0200 Subject: Fix mismatched/out-of-bounds accesses in vertical \blur --- libass/ass_bitmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 6dbc30c..5310481 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -365,13 +365,13 @@ static void ass_gauss_blur(unsigned char *buffer, unsigned *tmp2, unsigned *srcp = t + y * (width + 1) + 1; int src = *srcp; if (src) { - register unsigned *dstp = srcp - 1 + width + 1; + register unsigned *dstp = srcp - 1 - y * (width + 1); const int src2 = (src + 32768) >> 16; unsigned *m3 = m2 + src2 * mwidth; int mx; *srcp = 32768; - for (mx = r - 1; mx < mwidth; mx++) { + for (mx = r - y; mx < mwidth; mx++) { *dstp += m3[mx]; dstp += width + 1; } -- cgit v1.2.3 From 817d88f10fe6ce635894c9879f861cebf49b7fff Mon Sep 17 00:00:00 2001 From: Oleg Oshmyan Date: Tue, 17 Dec 2013 21:44:06 +0200 Subject: Don't forget to apply \be to the last row/column --- libass/ass_bitmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 5310481..dcc2f2b 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -444,6 +444,8 @@ static void be_blur(Bitmap *bm) buf[y * s + x] = (old_sum + new_sum) >> 2; old_sum = new_sum; } + new_sum = 2 * buf[y * s + w - 1]; + buf[y * s + w - 1] = (old_sum + new_sum) >> 2; } for (x = 0; x < w; x++) { @@ -453,6 +455,8 @@ static void be_blur(Bitmap *bm) buf[y * s + x] = (old_sum + new_sum) >> 2; old_sum = new_sum; } + new_sum = 2 * buf[(h - 1) * s + x]; + buf[(h - 1) * s + x] = (old_sum + new_sum) >> 2; } } -- cgit v1.2.3