summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRodger Combs <rodger.combs@gmail.com>2016-07-15 03:00:59 -0500
committerRodger Combs <rodger.combs@gmail.com>2016-07-15 06:01:50 -0500
commit748d479107b1e19a4f52f0f6acb47f78b2260430 (patch)
treeac0cd072a7cd8bf2894821bb476451c63d4770aa
parent669d06d814da42f7046689c97f578756d6cb6aa7 (diff)
downloadlibass-748d479107b1e19a4f52f0f6acb47f78b2260430.tar.bz2
libass-748d479107b1e19a4f52f0f6acb47f78b2260430.tar.xz
WIP: RGBA API
-rw-r--r--libass/ass.h10
-rw-r--r--libass/ass_bitmap.c32
-rw-r--r--libass/ass_bitmap.h8
-rw-r--r--libass/ass_func_template.h7
-rw-r--r--libass/ass_render.c83
-rw-r--r--test/test.c84
6 files changed, 149 insertions, 75 deletions
diff --git a/libass/ass.h b/libass/ass.h
index bd8bb1a..873f2c2 100644
--- a/libass/ass.h
+++ b/libass/ass.h
@@ -56,6 +56,11 @@ typedef struct ass_image {
IMAGE_TYPE_SHADOW
} type;
+ enum {
+ ASS_BITMAP_TYPE_ALPHA,
+ ASS_BITMAP_TYPE_RGBA
+ } bitmapType;
+
} ASS_Image;
/*
@@ -493,6 +498,9 @@ void ass_set_cache_limits(ASS_Renderer *priv, int glyph_max,
ASS_Image *ass_render_frame(ASS_Renderer *priv, ASS_Track *track,
long long now, int *detect_change);
+ASS_Image *ass_render_rgba_frame(ASS_Renderer *priv, ASS_Track *track,
+ long long now, int *detect_change,
+ int force_max_size);
/*
* The following functions operate on track objects and do not need
@@ -542,6 +550,8 @@ void ass_free_style(ASS_Track *track, int sid);
*/
void ass_free_event(ASS_Track *track, int eid);
+void ass_free_image(ASS_Image *img);
+
/**
* \brief Parse a chunk of subtitle stream data.
* \param track track
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c
index 2c354b3..78894c9 100644
--- a/libass/ass_bitmap.c
+++ b/libass/ass_bitmap.c
@@ -624,3 +624,35 @@ void ass_mul_bitmaps_c(uint8_t *dst, intptr_t dst_stride,
src2 += src2_stride;
}
}
+
+void ass_rgba_blend_c(uint8_t *dst, intptr_t dst_stride,
+ uint8_t *src, intptr_t src_stride,
+ intptr_t src_w, intptr_t src_h,
+ 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);
+
+ 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);
+ }
+ }
+}
diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h
index 36df816..71a3f5e 100644
--- a/libass/ass_bitmap.h
+++ b/libass/ass_bitmap.h
@@ -42,6 +42,11 @@ typedef void (*BitmapMulFunc)(uint8_t *dst, intptr_t dst_stride,
uint8_t *src2, intptr_t src2_stride,
intptr_t width, intptr_t height);
+typedef void (*RGBABlendFunc)(uint8_t *dst, intptr_t dst_stride,
+ uint8_t *src, intptr_t src_stride,
+ intptr_t src_w, intptr_t src_h,
+ uint32_t color);
+
typedef void (*BeBlurFunc)(uint8_t *buf, intptr_t w, intptr_t h,
intptr_t stride, uint16_t *tmp);
@@ -73,6 +78,9 @@ typedef struct {
BitmapBlendFunc add_bitmaps, sub_bitmaps;
BitmapMulFunc mul_bitmaps;
+ // rgba blend functions
+ RGBABlendFunc rgba_blend;
+
// be blur function
BeBlurFunc be_blur;
diff --git a/libass/ass_func_template.h b/libass/ass_func_template.h
index 3fea779..6c72021 100644
--- a/libass/ass_func_template.h
+++ b/libass/ass_func_template.h
@@ -42,6 +42,11 @@ void DECORATE(mul_bitmaps)(uint8_t *dst, intptr_t dst_stride,
uint8_t *src2, intptr_t src2_stride,
intptr_t width, intptr_t height);
+void DECORATE(rgba_blend)(uint8_t *dst, intptr_t dst_stride,
+ uint8_t *src, intptr_t src_stride,
+ intptr_t src_w, intptr_t src_h,
+ uint32_t color);
+
void DECORATE(be_blur)(uint8_t *buf, intptr_t w, intptr_t h,
intptr_t stride, uint16_t *tmp);
@@ -115,6 +120,8 @@ const BitmapEngine DECORATE(bitmap_engine) = {
.mul_bitmaps = ass_mul_bitmaps_c,
#endif
+ .rgba_blend = ass_rgba_blend_c,
+
#ifdef __x86_64__
.be_blur = DECORATE(be_blur),
#else
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 9bbaaa3..f124114 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -174,6 +174,7 @@ static ASS_Image *my_draw_bitmap(unsigned char *bitmap, int bitmap_w,
img->result.color = color;
img->result.dst_x = dst_x;
img->result.dst_y = dst_y;
+ img->result.bitmapType = ASS_BITMAP_TYPE_ALPHA;
img->source = source;
ass_cache_inc_ref(source);
@@ -3047,3 +3048,85 @@ void ass_frame_unref(ASS_Image *img)
free(priv);
} while (img);
}
+
+/**
+ * \brief render an RGBA frame
+ * \param priv library handle
+ * \param track track
+ * \param now current video timestamp (ms)
+ * \param detect_change a value describing how the new images differ from the previous ones will be written here:
+ * 0 if identical, >0 if different.
+ * Can be NULL, in that case no detection is performed.
+ */
+ASS_Image *ass_render_rgba_frame(ASS_Renderer *priv, ASS_Track *track,
+ long long now, int *detect_change,
+ int force_max_size)
+{
+ ASS_Image *list = ass_render_frame(priv, track, now, detect_change);
+
+ unsigned min_x = INT_MAX, min_y = INT_MAX;
+ unsigned max_x = 0, max_y = 0;
+ unsigned char *bitmap = NULL;
+ ASS_ImagePriv *out = NULL;
+ if (force_max_size) {
+ min_x = 0; min_y = 0;
+ max_x = priv->width;
+ max_y = priv->height;
+ } else {
+ for (ASS_Image *current = list; current; current = current->next) {
+ if (!current->w || !current->h)
+ continue;
+ min_x = FFMIN(current->dst_x, min_x);
+ min_y = FFMIN(current->dst_y, min_y);
+ max_x = FFMAX(current->dst_x + current->w, max_x);
+ max_x = FFMAX(current->dst_y + current->h, max_y);
+ }
+
+ if (max_x <= min_x || max_y <= min_y)
+ goto fail;
+ }
+
+ unsigned width = max_x - min_x;
+ unsigned height = max_y - min_y;
+ unsigned stride = ass_align(32, width * 4);
+ bitmap = ass_aligned_alloc(32, height * stride);
+ if (!bitmap)
+ goto fail;
+
+ memset(bitmap, 0, stride * height);
+
+ out = malloc(sizeof(ASS_ImagePriv));
+ if (!out)
+ goto fail;
+
+ out->result.w = width;
+ out->result.h = height;
+ out->result.stride = stride;
+ out->result.bitmap = bitmap;
+ out->result.color = 0x0; // N/A
+ out->result.dst_x = min_x;
+ out->result.dst_y = min_y;
+ out->result.bitmapType = ASS_BITMAP_TYPE_RGBA;
+ out->result.next = NULL;
+ out->ref_count = 1;
+ out->source = NULL;
+
+ for (ASS_Image *current = list; current; current = current->next) {
+ if (!current->w || !current->h)
+ continue;
+
+ unsigned char *dst = bitmap + (current->dst_y - min_y) * stride +
+ (current->dst_x - min_x) * 4;
+ priv->engine->rgba_blend(dst, stride, current->bitmap, current->stride,
+ current->w, current->h, current->color);
+ }
+
+ return &out->result;
+
+ fail:
+ if (bitmap)
+ free(bitmap);
+ if (out)
+ free(out);
+ return NULL;
+}
diff --git a/test/test.c b/test/test.c
index 4884b28..125c9ad 100644
--- a/test/test.c
+++ b/test/test.c
@@ -24,11 +24,6 @@
#include "../libass/ass.h"
#include <png.h>
-typedef struct image_s {
- int width, height, stride;
- unsigned char *buffer; // RGB24
-} image_t;
-
ASS_Library *ass_library;
ASS_Renderer *ass_renderer;
@@ -41,7 +36,7 @@ void msg_callback(int level, const char *fmt, va_list va, void *data)
printf("\n");
}
-static void write_png(char *fname, image_t *img)
+static void write_png(char *fname, ASS_Image *img)
{
FILE *fp;
png_structp png_ptr;
@@ -69,17 +64,15 @@ static void write_png(char *fname, image_t *img)
png_init_io(png_ptr, fp);
png_set_compression_level(png_ptr, 0);
- png_set_IHDR(png_ptr, info_ptr, img->width, img->height,
- 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ png_set_IHDR(png_ptr, info_ptr, img->w, img->h,
+ 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
- png_set_bgr(png_ptr);
-
- row_pointers = (png_byte **) malloc(img->height * sizeof(png_byte *));
- for (k = 0; k < img->height; k++)
- row_pointers[k] = img->buffer + img->stride * k;
+ row_pointers = (png_byte **) malloc(img->h * sizeof(png_byte *));
+ for (k = 0; k < img->h; k++)
+ row_pointers[k] = img->bitmap + img->stride * k;
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, info_ptr);
@@ -111,61 +104,6 @@ static void init(int frame_w, int frame_h)
ASS_FONTPROVIDER_AUTODETECT, NULL, 1);
}
-static image_t *gen_image(int width, int height)
-{
- image_t *img = malloc(sizeof(image_t));
- img->width = width;
- img->height = height;
- img->stride = width * 3;
- img->buffer = (unsigned char *) calloc(1, height * width * 3);
- memset(img->buffer, 63, img->stride * img->height);
- //for (int i = 0; i < height * width * 3; ++i)
- // img->buffer[i] = (i/3/50) % 100;
- return img;
-}
-
-#define _r(c) ((c)>>24)
-#define _g(c) (((c)>>16)&0xFF)
-#define _b(c) (((c)>>8)&0xFF)
-#define _a(c) ((c)&0xFF)
-
-static void blend_single(image_t * frame, ASS_Image *img)
-{
- int x, y;
- unsigned char opacity = 255 - _a(img->color);
- unsigned char r = _r(img->color);
- unsigned char g = _g(img->color);
- unsigned char b = _b(img->color);
-
- unsigned char *src;
- unsigned char *dst;
-
- src = img->bitmap;
- dst = frame->buffer + img->dst_y * frame->stride + img->dst_x * 3;
- for (y = 0; y < img->h; ++y) {
- for (x = 0; x < img->w; ++x) {
- unsigned k = ((unsigned) src[x]) * opacity / 255;
- // possible endianness problems
- dst[x * 3] = (k * b + (255 - k) * dst[x * 3]) / 255;
- dst[x * 3 + 1] = (k * g + (255 - k) * dst[x * 3 + 1]) / 255;
- dst[x * 3 + 2] = (k * r + (255 - k) * dst[x * 3 + 2]) / 255;
- }
- src += img->stride;
- dst += frame->stride;
- }
-}
-
-static void blend(image_t * frame, ASS_Image *img)
-{
- int cnt = 0;
- while (img) {
- blend_single(frame, img);
- ++cnt;
- img = img->next;
- }
- printf("%d images blended\n", cnt);
-}
-
char *font_provider_labels[] = {
[ASS_FONTPROVIDER_NONE] = "None",
[ASS_FONTPROVIDER_AUTODETECT] = "Autodetect",
@@ -210,18 +148,14 @@ int main(int argc, char *argv[])
return 1;
}
- ASS_Image *img =
- ass_render_frame(ass_renderer, track, (int) (tm * 1000), NULL);
- image_t *frame = gen_image(frame_w, frame_h);
- blend(frame, img);
+ ASS_Image *img = ass_render_rgba_frame(ass_renderer, track, (int) (tm * 1000), NULL, 1);
ass_free_track(track);
ass_renderer_done(ass_renderer);
ass_library_done(ass_library);
- write_png(imgfile, frame);
- free(frame->buffer);
- free(frame);
+ write_png(imgfile, img);
+ ass_frame_unref(img);
return 0;
}