summaryrefslogtreecommitdiffstats
path: root/sub/draw_bmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sub/draw_bmp.c')
-rw-r--r--sub/draw_bmp.c172
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,