diff options
Diffstat (limited to 'sub/draw_bmp.c')
-rw-r--r-- | sub/draw_bmp.c | 172 |
1 files changed, 69 insertions, 103 deletions
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index da4760e105..ce62a549c9 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -64,124 +64,83 @@ static bool get_sub_area(struct mp_rect bb, struct mp_image *temp, struct sub_bitmap *sb, struct mp_image *out_area, int *out_src_x, int *out_src_y); -#define ACCURATE -#define CONDITIONAL - -static void blend_const16_alpha(void *dst, int dst_stride, uint16_t srcp, - uint8_t *srca, int srca_stride, uint8_t srcamul, - int w, int h) -{ - if (!srcamul) - return; - for (int y = 0; y < h; y++) { - uint16_t *dst_r = (uint16_t *)((uint8_t *)dst + dst_stride * y); - uint8_t *srca_r = srca + srca_stride * y; - for (int x = 0; x < w; x++) { - uint32_t srcap = srca_r[x]; -#ifdef CONDITIONAL - if (!srcap) - continue; -#endif - srcap *= srcamul; // now 0..65025 - dst_r[x] = (srcp * srcap + dst_r[x] * (65025 - srcap) + 32512) / 65025; - } +#define CONDITIONAL 1 + +#define BLEND_CONST_ALPHA(TYPE) \ + TYPE *dst_r = dst_rp; \ + for (int x = 0; x < w; x++) { \ + uint32_t srcap = srca_r[x]; \ + if (CONDITIONAL && !srcap) continue; \ + srcap *= srcamul; /* now 0..65025 */ \ + dst_r[x] = (srcp * srcap + dst_r[x] * (65025 - srcap) + 32512) / 65025; \ } -} -static void blend_const8_alpha(void *dst, int dst_stride, uint16_t srcp, - uint8_t *srca, int srca_stride, uint8_t srcamul, - int w, int h) +// dst = srcp * (srca * srcamul) + dst * (1 - (srca * srcamul)) +static void blend_const_alpha(void *dst, int dst_stride, int srcp, + uint8_t *srca, int srca_stride, uint8_t srcamul, + int w, int h, int bytes) { if (!srcamul) return; for (int y = 0; y < h; y++) { - uint8_t *dst_r = (uint8_t *)dst + dst_stride * y; + void *dst_rp = (uint8_t *)dst + dst_stride * y; uint8_t *srca_r = srca + srca_stride * y; - for (int x = 0; x < w; x++) { - uint32_t srcap = srca_r[x]; -#ifdef CONDITIONAL - if (!srcap) - continue; -#endif -#ifdef ACCURATE - srcap *= srcamul; // now 0..65025 - dst_r[x] = (srcp * srcap + dst_r[x] * (65025 - srcap) + 32512) / 65025; -#else - srcap = (srcap * srcamul + 255) >> 8; - dst_r[x] = (srcp * srcap + dst_r[x] * (255 - srcap) + 255) >> 8; -#endif + if (bytes == 2) { + BLEND_CONST_ALPHA(uint16_t) + } else if (bytes == 1) { + BLEND_CONST_ALPHA(uint8_t) } } } -static void blend_const_alpha(void *dst, int dst_stride, int srcp, - uint8_t *srca, int srca_stride, uint8_t srcamul, - int w, int h, int bytes) -{ - if (bytes == 2) { - blend_const16_alpha(dst, dst_stride, srcp, srca, srca_stride, srcamul, - w, h); - } else if (bytes == 1) { - blend_const8_alpha(dst, dst_stride, srcp, srca, srca_stride, srcamul, - w, h); +#define BLEND_SRC_ALPHA(TYPE) \ + TYPE *dst_r = dst_rp, *src_r = src_rp; \ + for (int x = 0; x < w; x++) { \ + uint32_t srcap = srca_r[x]; \ + if (CONDITIONAL && !srcap) continue; \ + dst_r[x] = (src_r[x] * srcap + dst_r[x] * (255 - srcap) + 127) / 255; \ } -} -static void blend_src16_alpha(void *dst, int dst_stride, void *src, - int src_stride, uint8_t *srca, int srca_stride, - int w, int h) +// dst = src * srca + dst * (1 - srca) +static void blend_src_alpha(void *dst, int dst_stride, void *src, + int src_stride, uint8_t *srca, int srca_stride, + int w, int h, int bytes) { for (int y = 0; y < h; y++) { - uint16_t *dst_r = (uint16_t *)((uint8_t *)dst + dst_stride * y); - uint16_t *src_r = (uint16_t *)((uint8_t *)src + src_stride * y); + void *dst_rp = (uint8_t *)dst + dst_stride * y; + void *src_rp = (uint8_t *)src + src_stride * y; uint8_t *srca_r = srca + srca_stride * y; - for (int x = 0; x < w; x++) { - uint32_t srcap = srca_r[x]; -#ifdef CONDITIONAL - if (!srcap) - continue; -#endif - dst_r[x] = (src_r[x] * srcap + dst_r[x] * (255 - srcap) + 127) / 255; + if (bytes == 2) { + BLEND_SRC_ALPHA(uint16_t) + } else if (bytes == 1) { + BLEND_SRC_ALPHA(uint8_t) } } } -static void blend_src8_alpha(void *dst, int dst_stride, void *src, - int src_stride, uint8_t *srca, int srca_stride, - int w, int h) +#define BLEND_SRC_DST_MUL(TYPE, MAX) \ + TYPE *dst_r = dst_rp; \ + for (int x = 0; x < w; x++) { \ + uint16_t srcp = src_r[x] * srcmul; /* now 0..65025 */ \ + dst_r[x] = (srcp * (MAX) + dst_r[x] * (65025 - srcp) + 32512) / 65025; \ + } + +// dst = src * srcmul + dst * (1 - src * srcmul) +static void blend_src_dst_mul(void *dst, int dst_stride, + uint8_t *src, int src_stride, uint8_t srcmul, + int w, int h, int dst_bytes) { for (int y = 0; y < h; y++) { - uint8_t *dst_r = (uint8_t *)dst + dst_stride * y; + void *dst_rp = (uint8_t *)dst + dst_stride * y; uint8_t *src_r = (uint8_t *)src + src_stride * y; - uint8_t *srca_r = srca + srca_stride * y; - for (int x = 0; x < w; x++) { - uint16_t srcap = srca_r[x]; -#ifdef CONDITIONAL - if (!srcap) - continue; -#endif -#ifdef ACCURATE - dst_r[x] = (src_r[x] * srcap + dst_r[x] * (255 - srcap) + 127) / 255; -#else - dst_r[x] = (src_r[x] * srcap + dst_r[x] * (255 - srcap) + 255) >> 8; -#endif + if (dst_bytes == 2) { + BLEND_SRC_DST_MUL(uint16_t, 65025) + } else if (dst_bytes == 1) { + BLEND_SRC_DST_MUL(uint8_t, 255) } } } -static void blend_src_alpha(void *dst, int dst_stride, void *src, - int src_stride, uint8_t *srca, int srca_stride, - int w, int h, int bytes) -{ - if (bytes == 2) { - blend_src16_alpha(dst, dst_stride, src, src_stride, srca, srca_stride, - w, h); - } else if (bytes == 1) { - blend_src8_alpha(dst, dst_stride, src, src_stride, srca, srca_stride, - w, h); - } -} - static void unpremultiply_and_split_BGR32(struct mp_image *img, struct mp_image *alpha) { @@ -278,6 +237,10 @@ static void draw_rgba(struct mp_draw_sub_cache *cache, struct mp_rect bb, blend_src_alpha(dst.planes[p], dst.stride[p], src, sbi->stride[p], alpha_p, sba->stride[0], dst.w, dst.h, bytes); } + if (temp->num_planes >= 4) { + blend_src_dst_mul(dst.planes[3], dst.stride[3], alpha_p, + sba->stride[0], 255, dst.w, dst.h, bytes); + } part->imgs[i].i = talloc_steal(part, sbi); part->imgs[i].a = talloc_steal(part, sba); @@ -328,6 +291,10 @@ static void draw_ass(struct mp_draw_sub_cache *cache, struct mp_rect bb, blend_const_alpha(dst.planes[p], dst.stride[p], color_yuv[p], alpha_p, sb->stride, a, dst.w, dst.h, bytes); } + if (temp->num_planes >= 4) { + blend_src_dst_mul(dst.planes[3], dst.stride[3], alpha_p, + sb->stride, a, dst.w, dst.h, bytes); + } } } @@ -373,21 +340,20 @@ static bool align_bbox_for_swscale(struct mp_image *img, struct mp_rect *rc) static void get_closest_y444_format(int imgfmt, int *out_format, int *out_bits) { struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt); + int planes = desc.flags & MP_IMGFLAG_ALPHA ? 4 : 3; + int bits = desc.component_bits > 8 ? 16 : 8; if (desc.flags & MP_IMGFLAG_RGB) { - *out_format = IMGFMT_GBRP; - *out_bits = 8; - return; + *out_format = mp_imgfmt_find(0, 0, planes, bits, MP_IMGFLAG_RGB_P); + if (!mp_sws_supported_format(*out_format)) + *out_format = mp_imgfmt_find(0, 0, planes, 8, MP_IMGFLAG_RGB_P); } else if (desc.flags & MP_IMGFLAG_YUV_P) { - *out_format = mp_imgfmt_find_yuv_planar(0, 0, desc.num_planes, - desc.plane_bits); - if (*out_format && mp_sws_supported_format(*out_format)) { - *out_bits = mp_imgfmt_get_desc(*out_format).plane_bits; - return; - } + *out_format = mp_imgfmt_find(0, 0, planes, bits, MP_IMGFLAG_YUV_P); + } else { + *out_format = 0; } - // fallback - *out_format = IMGFMT_444P; - *out_bits = 8; + if (!mp_sws_supported_format(*out_format)) + *out_format = IMGFMT_444P; // generic fallback + *out_bits = mp_imgfmt_get_desc(*out_format).component_bits; } static struct part *get_cache(struct mp_draw_sub_cache *cache, |