summaryrefslogtreecommitdiffstats
path: root/sub/img_convert.c
diff options
context:
space:
mode:
Diffstat (limited to 'sub/img_convert.c')
-rw-r--r--sub/img_convert.c87
1 files changed, 75 insertions, 12 deletions
diff --git a/sub/img_convert.c b/sub/img_convert.c
index 9a5d1bf42b..3196340c7a 100644
--- a/sub/img_convert.c
+++ b/sub/img_convert.c
@@ -56,13 +56,14 @@ static void rgba_to_premultiplied_rgba(uint32_t *colors, size_t count)
}
}
-bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+static bool conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
+ bool straight_alpha)
{
struct sub_bitmaps src = *imgs;
if (src.format != SUBBITMAP_INDEXED)
return false;
- imgs->format = SUBBITMAP_RGBA;
+ imgs->format = straight_alpha ? SUBBITMAP_RGBA_STR : SUBBITMAP_RGBA;
talloc_free(c->parts);
imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
@@ -71,7 +72,8 @@ bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
struct sub_bitmap *s = &src.parts[n];
struct osd_bmp_indexed sb = *(struct osd_bmp_indexed *)s->bitmap;
- rgba_to_premultiplied_rgba(sb.palette, 256);
+ if (imgs->format == SUBBITMAP_RGBA)
+ rgba_to_premultiplied_rgba(sb.palette, 256);
*d = *s;
struct mp_image *image = mp_image_alloc(IMGFMT_BGRA, s->w, s->h);
@@ -89,11 +91,21 @@ bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
return true;
}
+bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+{
+ return conv_idx_to_rgba(c, imgs, false);
+}
+
+bool osd_conv_idx_to_rgba_str(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+{
+ return conv_idx_to_rgba(c, imgs, true);
+}
+
bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
double gblur)
{
struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_RGBA)
+ if (src.format != SUBBITMAP_RGBA && src.format != SUBBITMAP_RGBA_STR)
return false;
talloc_free(c->parts);
@@ -165,8 +177,8 @@ bool osd_conv_idx_to_gray(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
return true;
}
-static void draw_ass_rgba(unsigned char *src, int src_w, int src_h,
- int src_stride, unsigned char *dst, size_t dst_stride,
+static void draw_ass_rgba(uint8_t *src, int src_w, int src_h,
+ int src_stride, uint8_t *dst, size_t dst_stride,
int dst_x, int dst_y, uint32_t color)
{
const unsigned int r = (color >> 24) & 0xff;
@@ -198,7 +210,41 @@ static void draw_ass_rgba(unsigned char *src, int src_w, int src_h,
}
}
-bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+static void draw_ass_rgba_str(uint8_t *src, int src_w, int src_h,
+ int src_stride, uint8_t *dst, size_t dst_stride,
+ int dst_x, int dst_y, uint32_t color)
+{
+ const unsigned int r = (color >> 24) & 0xff;
+ const unsigned int g = (color >> 16) & 0xff;
+ const unsigned int b = (color >> 8) & 0xff;
+ const unsigned int a = 0xff - (color & 0xff);
+
+ dst += dst_y * dst_stride + dst_x * 4;
+
+ for (int y = 0; y < src_h; y++, dst += dst_stride, src += src_stride) {
+ uint32_t *dstrow = (uint32_t *) dst;
+ for (int x = 0; x < src_w; x++) {
+ const unsigned int v = src[x];
+ int rr = (r * v);
+ int gg = (g * v);
+ int bb = (b * v);
+ int aa = (a * v);
+ uint32_t dstpix = dstrow[x];
+ unsigned int dstb = dstpix & 0xFF;
+ unsigned int dstg = (dstpix >> 8) & 0xFF;
+ unsigned int dstr = (dstpix >> 16) & 0xFF;
+ unsigned int dsta = (dstpix >> 24) & 0xFF;
+ dstb = (bb + dstb * (255 - aa)) / 255;
+ dstg = (gg + dstg * (255 - aa)) / 255;
+ dstr = (rr + dstr * (255 - aa)) / 255;
+ dsta = (aa + dsta * (255 - aa)) / 255;
+ dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24);
+ }
+ }
+}
+
+static bool conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
+ bool straight_alpha)
{
struct sub_bitmaps src = *imgs;
if (src.format != SUBBITMAP_LIBASS)
@@ -208,7 +254,7 @@ bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
struct mp_rect bb_list[MP_SUB_BB_LIST_MAX];
int num_bb = mp_get_sub_bb_list(&src, bb_list, MP_SUB_BB_LIST_MAX);
- imgs->format = SUBBITMAP_RGBA;
+ imgs->format = straight_alpha ? SUBBITMAP_RGBA_STR : SUBBITMAP_RGBA;
imgs->parts = c->part;
imgs->num_parts = num_bb;
@@ -251,16 +297,33 @@ bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
s->y > bb.y1 || s->y + s->h < bb.y0)
continue;
- draw_ass_rgba(s->bitmap, s->w, s->h, s->stride,
- bmp->bitmap, bmp->stride,
- s->x - bb.x0, s->y - bb.y0,
- s->libass.color);
+ if (imgs->format == SUBBITMAP_RGBA_STR) {
+ draw_ass_rgba(s->bitmap, s->w, s->h, s->stride,
+ bmp->bitmap, bmp->stride,
+ s->x - bb.x0, s->y - bb.y0,
+ s->libass.color);
+ } else {
+ draw_ass_rgba_str(s->bitmap, s->w, s->h, s->stride,
+ bmp->bitmap, bmp->stride,
+ s->x - bb.x0, s->y - bb.y0,
+ s->libass.color);
+ }
}
}
return true;
}
+bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+{
+ return conv_ass_to_rgba(c, imgs, false);
+}
+
+bool osd_conv_ass_to_rgba_str(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+{
+ return conv_ass_to_rgba(c, imgs, true);
+}
+
bool mp_sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb)
{
struct mp_rect bb = {INT_MAX, INT_MAX, INT_MIN, INT_MIN};