From 844bba6645864ad2ccd9cc40bab2c4553b50d35b Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 11 Dec 2012 16:24:24 +0100 Subject: sub: add ASS to RGBA conversion This makes implementing new VOs easier, because they don't have to support the ASS format. --- sub/img_convert.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'sub/img_convert.c') diff --git a/sub/img_convert.c b/sub/img_convert.c index 578a20b646..0560b66aab 100644 --- a/sub/img_convert.c +++ b/sub/img_convert.c @@ -163,3 +163,79 @@ 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, + 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 * a * v); + int gg = (g * a * v); + int bb = (b * a * 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 * 255 - aa)) / (255 * 255); + dstg = (gg + dstg * (255 * 255 - aa)) / (255 * 255); + dstr = (rr + dstr * (255 * 255 - aa)) / (255 * 255); + dsta = (aa * 255 + dsta * (255 * 255 - aa)) / (255 * 255); + dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24); + } + } +} + +bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs) +{ + struct sub_bitmaps src = *imgs; + if (src.format != SUBBITMAP_LIBASS) + return false; + assert(!src.scaled); // ASS is always unscaled + + struct sub_bitmap *bmp = &c->part; + + imgs->format = SUBBITMAP_RGBA; + imgs->parts = bmp; + imgs->num_parts = 0; + + struct mp_rect bb; + if (!sub_bitmaps_bb(&src, &bb)) + return true; + + bmp->x = bb.x0; + bmp->y = bb.y0; + bmp->w = bmp->dw = bb.x1 - bb.x0; + bmp->h = bmp->dh = bb.y1 - bb.y0; + bmp->stride = bmp->w * 4; + size_t newsize = bmp->h * bmp->stride; + if (talloc_get_size(bmp->bitmap) < newsize) { + talloc_free(bmp->bitmap); + bmp->bitmap = talloc_array(c, char, newsize); + } + + memset_pic(bmp->bitmap, 0, bmp->w * 4, bmp->h, bmp->stride); + + for (int n = 0; n < src.num_parts; n++) { + struct sub_bitmap *s = &src.parts[n]; + + 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); + } + + imgs->num_parts = 1; + return true; +} -- cgit v1.2.3