diff options
author | Dr.Smile <vabnick@gmail.com> | 2022-02-27 00:01:13 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2022-11-16 16:05:43 +0200 |
commit | b4deb8937aa1485106b402422791bd87fa98099e (patch) | |
tree | 7336eb693d2d910ba80c0f45277377e8e97ffffb /libass | |
parent | 194f0d298f3c9f3d1167aac694de7adc812a18a3 (diff) | |
download | libass-b4deb8937aa1485106b402422791bd87fa98099e.tar.bz2 libass-b4deb8937aa1485106b402422791bd87fa98099e.tar.xz |
Support different Gaussian blur radii along the two axes
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass_bitmap.c | 6 | ||||
-rw-r--r-- | libass/ass_bitmap.h | 4 | ||||
-rw-r--r-- | libass/ass_blur.c | 43 | ||||
-rw-r--r-- | libass/ass_cache_template.h | 3 | ||||
-rw-r--r-- | libass/ass_render.c | 17 |
5 files changed, 41 insertions, 32 deletions
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 527916f..3f62f82 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -88,14 +88,14 @@ static void be_blur_post(uint8_t *buf, intptr_t stride, intptr_t width, intptr_t } void ass_synth_blur(const BitmapEngine *engine, Bitmap *bm, - int be, double blur_r2) + int be, double blur_r2x, double blur_r2y) { if (!bm->buffer) return; // Apply gaussian blur - if (blur_r2 > 0.001) - ass_gaussian_blur(engine, bm, blur_r2); + if (blur_r2x > 0.001 || blur_r2y > 0.001) + ass_gaussian_blur(engine, bm, blur_r2x, blur_r2y); if (!be) return; diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index 90973e0..9f425cc 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -108,9 +108,9 @@ bool ass_outline_to_bitmap(struct render_context *state, Bitmap *bm, ASS_Outline *outline1, ASS_Outline *outline2); void ass_synth_blur(const BitmapEngine *engine, Bitmap *bm, - int be, double blur_r2); + int be, double blur_r2x, double blur_r2y); -bool ass_gaussian_blur(const BitmapEngine *engine, Bitmap *bm, double r2); +bool ass_gaussian_blur(const BitmapEngine *engine, Bitmap *bm, double r2x, double r2y); void ass_shift_bitmap(Bitmap *bm, int shift_x, int shift_y); void ass_fix_outline(Bitmap *bm_g, Bitmap *bm_o); diff --git a/libass/ass_blur.c b/libass/ass_blur.c index efea0df..61c838e 100644 --- a/libass/ass_blur.c +++ b/libass/ass_blur.c @@ -529,17 +529,22 @@ static void find_best_method(BlurMethod *blur, double r2) /** * \brief Perform approximate gaussian blur - * \param r2 in: desired standard deviation squared + * \param r2x in: desired standard deviation along X axis squared + * \param r2y in: desired standard deviation along Y axis squared */ -bool ass_gaussian_blur(const BitmapEngine *engine, Bitmap *bm, double r2) +bool ass_gaussian_blur(const BitmapEngine *engine, Bitmap *bm, double r2x, double r2y) { - BlurMethod blur; - find_best_method(&blur, r2); + BlurMethod blur_x, blur_y; + find_best_method(&blur_x, r2x); + if (r2y == r2x) + memcpy(&blur_y, &blur_x, sizeof(blur_y)); + else find_best_method(&blur_y, r2y); uint32_t w = bm->w, h = bm->h; - int offset = ((2 * blur.radius + 9) << blur.level) - 5; - uint32_t end_w = ((w + offset) & ~((1 << blur.level) - 1)) - 4; - uint32_t end_h = ((h + offset) & ~((1 << blur.level) - 1)) - 4; + int offset_x = ((2 * blur_x.radius + 9) << blur_x.level) - 5; + int offset_y = ((2 * blur_y.radius + 9) << blur_y.level) - 5; + uint32_t end_w = ((w + offset_x) & ~((1 << blur_x.level) - 1)) - 4; + uint32_t end_h = ((h + offset_y) & ~((1 << blur_y.level) - 1)) - 4; const int stripe_width = 1 << (engine->align_order - 1); uint64_t size = (((uint64_t) end_w + stripe_width - 1) & ~(stripe_width - 1)) * end_h; @@ -554,29 +559,30 @@ bool ass_gaussian_blur(const BitmapEngine *engine, Bitmap *bm, double r2) int16_t *buf[2] = {tmp, tmp + size}; int index = 0; - for (int i = 0; i < blur.level; i++) { + for (int i = 0; i < blur_y.level; i++) { engine->shrink_vert(buf[index ^ 1], buf[index], w, h); h = (h + 5) >> 1; index ^= 1; } - for (int i = 0; i < blur.level; i++) { + for (int i = 0; i < blur_x.level; i++) { engine->shrink_horz(buf[index ^ 1], buf[index], w, h); w = (w + 5) >> 1; index ^= 1; } - assert(blur.radius >= 4 && blur.radius <= 8); - engine->blur_horz[blur.radius - 4](buf[index ^ 1], buf[index], w, h, blur.coeff); - w += 2 * blur.radius; + assert(blur_x.radius >= 4 && blur_x.radius <= 8); + engine->blur_horz[blur_x.radius - 4](buf[index ^ 1], buf[index], w, h, blur_x.coeff); + w += 2 * blur_x.radius; index ^= 1; - engine->blur_vert[blur.radius - 4](buf[index ^ 1], buf[index], w, h, blur.coeff); - h += 2 * blur.radius; + assert(blur_y.radius >= 4 && blur_y.radius <= 8); + engine->blur_vert[blur_y.radius - 4](buf[index ^ 1], buf[index], w, h, blur_y.coeff); + h += 2 * blur_y.radius; index ^= 1; - for (int i = 0; i < blur.level; i++) { + for (int i = 0; i < blur_x.level; i++) { engine->expand_horz(buf[index ^ 1], buf[index], w, h); w = 2 * w + 4; index ^= 1; } - for (int i = 0; i < blur.level; i++) { + for (int i = 0; i < blur_y.level; i++) { engine->expand_vert(buf[index ^ 1], buf[index], w, h); h = 2 * h + 4; index ^= 1; @@ -587,9 +593,8 @@ bool ass_gaussian_blur(const BitmapEngine *engine, Bitmap *bm, double r2) ass_aligned_free(tmp); return false; } - offset = ((blur.radius + 4) << blur.level) - 4; - bm->left -= offset; - bm->top -= offset; + bm->left -= ((blur_x.radius + 4) << blur_x.level) - 4; + bm->top -= ((blur_y.radius + 4) << blur_y.level) - 4; engine->stripe_pack(bm->buffer, bm->stride, buf[index], w, h); ass_aligned_free(tmp); diff --git a/libass/ass_cache_template.h b/libass/ass_cache_template.h index fd4cdb6..8b07faa 100644 --- a/libass/ass_cache_template.h +++ b/libass/ass_cache_template.h @@ -104,7 +104,8 @@ END(BorderHashKey) START(filter, filter_desc) GENERIC(int, flags) GENERIC(int, be) - GENERIC(int, blur) + GENERIC(int, blur_x) + GENERIC(int, blur_y) VECTOR(shadow) END(FilterDesc) diff --git a/libass/ass_render.c b/libass/ass_render.c index 1022989..f14a737 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -2538,14 +2538,16 @@ static void render_and_combine_glyphs(RenderContext *state, filter->flags = flags; filter->be = info->be; - int32_t shadow_mask; + int32_t shadow_mask_x, shadow_mask_y; double blur_scale = state->blur_scale * (2 / sqrt(log(256))); - filter->blur = quantize_blur(info->blur * blur_scale, &shadow_mask); + // XXX: correct anamorphic blur radii + filter->blur_x = quantize_blur(info->blur * blur_scale, &shadow_mask_x); + filter->blur_y = quantize_blur(info->blur * blur_scale, &shadow_mask_y); if (flags & FILTER_NONZERO_SHADOW) { int32_t x = double_to_d6(info->shadow_x * state->border_scale_x); int32_t y = double_to_d6(info->shadow_y * state->border_scale_y); - filter->shadow.x = (x + (shadow_mask >> 1)) & ~shadow_mask; - filter->shadow.y = (y + (shadow_mask >> 1)) & ~shadow_mask; + filter->shadow.x = (x + (shadow_mask_x >> 1)) & ~shadow_mask_x; + filter->shadow.y = (y + (shadow_mask_y >> 1)) & ~shadow_mask_y; } else filter->shadow.x = filter->shadow.y = 0; @@ -2752,10 +2754,11 @@ size_t ass_composite_construct(void *key, void *value, void *priv) } int flags = k->filter.flags; - double r2 = restore_blur(k->filter.blur); + double r2x = restore_blur(k->filter.blur_x); + double r2y = restore_blur(k->filter.blur_y); if (!(flags & FILTER_NONZERO_BORDER) || (flags & FILTER_BORDER_STYLE_3)) - ass_synth_blur(render_priv->engine, &v->bm, k->filter.be, r2); - ass_synth_blur(render_priv->engine, &v->bm_o, k->filter.be, r2); + ass_synth_blur(render_priv->engine, &v->bm, k->filter.be, r2x, r2y); + ass_synth_blur(render_priv->engine, &v->bm_o, k->filter.be, r2x, r2y); if (!(flags & FILTER_FILL_IN_BORDER) && !(flags & FILTER_FILL_IN_SHADOW)) ass_fix_outline(&v->bm, &v->bm_o); |