summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-12-11 16:24:24 +0100
committerRudolf Polzer <divverent@xonotic.org>2012-12-28 08:30:15 +0100
commit844bba6645864ad2ccd9cc40bab2c4553b50d35b (patch)
tree2d50f94b37b807ec5606d408398c360b32a8fedb /sub
parentf3374eecada2cde520d76931055f0509296fc9d6 (diff)
downloadmpv-844bba6645864ad2ccd9cc40bab2c4553b50d35b.tar.bz2
mpv-844bba6645864ad2ccd9cc40bab2c4553b50d35b.tar.xz
sub: add ASS to RGBA conversion
This makes implementing new VOs easier, because they don't have to support the ASS format.
Diffstat (limited to 'sub')
-rw-r--r--sub/img_convert.c76
-rw-r--r--sub/img_convert.h1
-rw-r--r--sub/sub.c4
-rw-r--r--sub/sub.h4
4 files changed, 83 insertions, 2 deletions
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;
+}
diff --git a/sub/img_convert.h b/sub/img_convert.h
index 2ea17ef889..0a46916f60 100644
--- a/sub/img_convert.h
+++ b/sub/img_convert.h
@@ -11,6 +11,7 @@ struct osd_conv_cache *osd_conv_cache_new(void);
// These functions convert from one OSD format to another. On success, they copy
// the converted image data into c, and change imgs to point to the data.
bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
+bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
// Sub postprocessing
bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
double gblur);
diff --git a/sub/sub.c b/sub/sub.c
index 56d85141a7..1365d3c844 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -229,6 +229,10 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
if (out_imgs->format == SUBBITMAP_RGBA && opts->sub_gauss != 0.0f)
cached |= osd_conv_blur_rgba(obj->cache[2], out_imgs, opts->sub_gauss);
+ // Do this conversion last to not trigger gauss blurring for ASS
+ if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_LIBASS)
+ cached |= osd_conv_ass_to_rgba(obj->cache[3], out_imgs);
+
if (cached)
obj->cached = *out_imgs;
}
diff --git a/sub/sub.h b/sub/sub.h
index 0de36fedb5..ed4401cacf 100644
--- a/sub/sub.h
+++ b/sub/sub.h
@@ -25,7 +25,7 @@
#include "core/m_option.h"
-// NOTE: VOs must support at least SUBBITMAP_LIBASS and SUBBITMAP_RGBA.
+// NOTE: VOs must support at least SUBBITMAP_RGBA.
enum sub_bitmap_format {
SUBBITMAP_EMPTY = 0,// no bitmaps; always has num_parts==0
SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color)
@@ -94,7 +94,7 @@ enum mp_osdtype {
MAX_OSD_PARTS
};
-#define OSD_CONV_CACHE_MAX 3
+#define OSD_CONV_CACHE_MAX 4
struct osd_object {
int type; // OSDTYPE_*