>From edce1412b4bdb6561432b23260f6c2694007d410 Mon Sep 17 00:00:00 2001 From: greg Date: Wed, 18 Feb 2009 03:14:02 +0100 Subject: [PATCH 09/12] Add simple blur with [1,2,1] for \be. This is the same blur vsfilter uses. It's also faster than gaussian blur. --- libass/ass_bitmap.c | 63 ++++++++++++++++++++++++++++++++++++++++++++------ libass/ass_bitmap.h | 9 ++++++- libass/ass_render.c | 10 ++++---- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 463bb7d..3869185 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -254,11 +254,61 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o) return bm_s; } -int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, +/** + * \brief Blur with [1,2,1] kernel + * This simple blur is exactly the same as the one employed by vsfilter. + * In addition, it's slightly faster than gaussian blur. + */ +static void be_blur(unsigned char *buf, ass_be_priv_t* priv, int w, int h) { + unsigned int x, y; + unsigned int p; + unsigned char *tmp_buf = priv->buf; + const int wh = w*h; + + if (priv->size < wh) { + priv->buf = realloc(priv->buf, wh); + priv->size = wh; + tmp_buf = priv->buf; + } + memset(tmp_buf, 0, wh); + + for (y=0; y> 2; + tmp_buf[y*w+x] = p; + } + + for (x=0; x> 2; + buf[y*w+x] = p; + } +} + +ass_be_priv_t* ass_be_init(void) { + ass_be_priv_t* priv; + priv = calloc(1, sizeof(ass_be_priv_t)); + + return priv; +} + +void ass_be_done(ass_be_priv_t* priv) { + if (priv->buf) + free(priv->buf); + free(priv); +} + +int glyph_to_bitmap(ass_be_priv_t* priv_be, ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius) { - int bord = be ? (be+1) : 0; + int bord = be ? (be/4+1) : 0; blur_radius *= 2; bord = (blur_radius > 0.0) ? blur_radius : bord; @@ -278,19 +328,16 @@ int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, return 1; } } - if (*bm_o) { - resize_tmp(priv, (*bm_o)->w, (*bm_o)->h); + if (*bm_o) resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h); - } - resize_tmp(priv, (*bm_g)->w, (*bm_g)->h); resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h); if (be) { while (be--) { if (*bm_o) - blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w); + be_blur((*bm_o)->buffer, priv_be, (*bm_o)->w, (*bm_o)->h); else - blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w); + be_blur((*bm_o)->buffer, priv_be, (*bm_o)->w, (*bm_o)->h); } } else { if (blur_radius > 0.0) { diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index 5f45aae..56ed2a5 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -28,6 +28,13 @@ typedef struct ass_synth_priv_s ass_synth_priv_t; +typedef struct ass_be_priv_s { + int size; + unsigned char *buf; +} ass_be_priv_t; + +ass_be_priv_t* ass_be_init(void); +void ass_be_done(ass_be_priv_t* priv); ass_synth_priv_t* ass_synth_init(double); void ass_synth_done(ass_synth_priv_t* priv); @@ -46,7 +53,7 @@ typedef struct bitmap_s { * \param bm_g out: pointer to the bitmap of glyph shadow is returned here * \param be 1 = produces blurred bitmaps, 0 = normal bitmaps */ -int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius); +int glyph_to_bitmap(ass_be_priv_t* priv_be, ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius); void ass_free_bitmap(bitmap_t* bm); diff --git a/libass/ass_render.c b/libass/ass_render.c index 060341d..7700fdf 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -43,7 +43,6 @@ #define MAX_GLYPHS 3000 #define MAX_LINES 300 -#define BE_RADIUS 1.5 #define BLUR_MAX_RADIUS 50.0 #define ROUND(x) ((int) ((x) + .5)) @@ -82,7 +81,7 @@ struct ass_renderer_s { fc_instance_t* fontconfig_priv; ass_settings_t settings; int render_id; - ass_synth_priv_t* synth_priv; + ass_be_priv_t* be_priv; ass_synth_priv_t* synth_priv_blur; ass_image_t* images_root; // rendering result is stored here @@ -270,7 +269,7 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library) goto ass_init_exit; } - priv->synth_priv = ass_synth_init(BE_RADIUS); + priv->be_priv = ass_be_init(); priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS); priv->library = library; @@ -301,7 +300,8 @@ void ass_renderer_done(ass_renderer_t* priv) } if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary); if (priv && priv->fontconfig_priv) fontconfig_done(priv->fontconfig_priv); - if (priv && priv->synth_priv) ass_synth_done(priv->synth_priv); + if (priv && priv->synth_priv_blur) ass_synth_done(priv->synth_priv_blur); + if (priv && priv->be_priv) ass_be_done(priv->be_priv); if (priv && priv->eimg) free(priv->eimg); if (priv) free(priv); if (text_info.glyphs) free(text_info.glyphs); @@ -1389,7 +1389,7 @@ static void get_bitmap_glyph(glyph_info_t* info) transform_3d(shift, &info->glyph, &info->outline_glyph, info->frx, info->fry, info->frz); // render glyph - error = glyph_to_bitmap(ass_renderer->synth_priv, + error = glyph_to_bitmap(ass_renderer->be_priv, ass_renderer->synth_priv_blur, info->glyph, info->outline_glyph, &info->bm, &info->bm_o, -- 1.5.4.3