sub/ass_mp: add missing padding for ass packer
This ensures it is safe to sample packed image with bilinear filtering.
This commit is contained in:
1 parent
55043cb5c8
commit
e2fc75434e
3 files changed
+76
-19
No files matched your search
+70
-16
@@ -206,6 +206,7 @@ struct mp_ass_packer *mp_ass_packer_alloc(void *ta_parent)
|
||||
{
|
||||
struct mp_ass_packer *p = talloc_zero(ta_parent, struct mp_ass_packer);
|
||||
p->packer = talloc_zero(p, struct bitmap_packer);
|
||||
p->packer->padding = 1; // assume bilinear sampling
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -256,18 +257,68 @@ static bool pack(struct mp_ass_packer *p, struct sub_bitmaps *res, int imgfmt)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fill_padding_1(uint8_t *base, int w, int h, int stride, int padding)
|
||||
{
|
||||
for (int row = 0; row < h; ++row) {
|
||||
uint8_t *row_ptr = base + row * stride;
|
||||
uint8_t left_pixel = row_ptr[0];
|
||||
uint8_t right_pixel = row_ptr[w - 1];
|
||||
|
||||
for (int i = 1; i <= padding; ++i)
|
||||
row_ptr[-i] = left_pixel;
|
||||
|
||||
for (int i = 0; i < padding; ++i)
|
||||
row_ptr[w + i] = right_pixel;
|
||||
}
|
||||
|
||||
int row_bytes = (w + 2 * padding);
|
||||
uint8_t *top_row = base - padding;
|
||||
for (int i = 1; i <= padding; ++i)
|
||||
memcpy(base - i * stride - padding, top_row, row_bytes);
|
||||
|
||||
uint8_t *last_row = base + (h - 1) * stride - padding;
|
||||
for (int i = 0; i < padding; ++i)
|
||||
memcpy(base + (h + i) * stride - padding, last_row, row_bytes);
|
||||
}
|
||||
|
||||
static void fill_padding_4(uint8_t *base, int w, int h, int stride, int padding)
|
||||
{
|
||||
for (int row = 0; row < h; ++row) {
|
||||
uint32_t *row_ptr = (uint32_t *)(base + row * stride);
|
||||
uint32_t left_pixel = row_ptr[0];
|
||||
uint32_t right_pixel = row_ptr[w - 1];
|
||||
|
||||
for (int i = 1; i <= padding; ++i)
|
||||
row_ptr[-i] = left_pixel;
|
||||
|
||||
for (int i = 0; i < padding; ++i)
|
||||
row_ptr[w + i] = right_pixel;
|
||||
}
|
||||
|
||||
int row_bytes = (w + 2 * padding) * 4;
|
||||
uint8_t *top_row = base - padding * 4;
|
||||
for (int i = 1; i <= padding; ++i)
|
||||
memcpy(base - i * stride - padding * 4, top_row, row_bytes);
|
||||
|
||||
uint8_t *last_row = base + (h - 1) * stride - padding * 4;
|
||||
for (int i = 0; i < padding; ++i)
|
||||
memcpy(base + (h + i) * stride - padding * 4, last_row, row_bytes);
|
||||
}
|
||||
|
||||
static bool pack_libass(struct mp_ass_packer *p, struct sub_bitmaps *res)
|
||||
{
|
||||
if (!pack(p, res, IMGFMT_Y8))
|
||||
return false;
|
||||
|
||||
int padding = p->packer->padding;
|
||||
uint8_t *base = res->packed->planes[0];
|
||||
int stride = res->packed->stride[0];
|
||||
|
||||
for (int n = 0; n < res->num_parts; n++) {
|
||||
struct sub_bitmap *b = &res->parts[n];
|
||||
|
||||
int stride = res->packed->stride[0];
|
||||
void *pdata =
|
||||
(uint8_t *)res->packed->planes[0] + b->src_y * stride + b->src_x;
|
||||
void *pdata = base + b->src_y * stride + b->src_x;
|
||||
memcpy_pic(pdata, b->bitmap, b->w, b->h, stride, b->stride);
|
||||
fill_padding_1(pdata, b->w, b->h, stride, padding);
|
||||
|
||||
b->bitmap = pdata;
|
||||
b->stride = stride;
|
||||
@@ -278,8 +329,9 @@ static bool pack_libass(struct mp_ass_packer *p, struct sub_bitmaps *res)
|
||||
|
||||
static bool pack_rgba(struct mp_ass_packer *p, struct sub_bitmaps *res)
|
||||
{
|
||||
int padding = p->packer->padding;
|
||||
struct mp_rect bb_list[MP_SUB_BB_LIST_MAX];
|
||||
int num_bb = mp_get_sub_bb_list(res, bb_list, MP_SUB_BB_LIST_MAX);
|
||||
int num_bb = mp_get_sub_bb_list(res, bb_list, MP_SUB_BB_LIST_MAX, padding);
|
||||
|
||||
struct sub_bitmaps imgs = {
|
||||
.change_id = res->change_id,
|
||||
@@ -296,18 +348,19 @@ static bool pack_rgba(struct mp_ass_packer *p, struct sub_bitmaps *res)
|
||||
if (!pack(p, &imgs, IMGFMT_BGRA))
|
||||
return false;
|
||||
|
||||
uint8_t *base = imgs.packed->planes[0];
|
||||
int stride = imgs.packed->stride[0];
|
||||
|
||||
for (int n = 0; n < num_bb; n++) {
|
||||
struct mp_rect bb = bb_list[n];
|
||||
struct sub_bitmap *b = &imgs.parts[n];
|
||||
|
||||
b->x = bb.x0;
|
||||
b->y = bb.y0;
|
||||
b->w = b->dw = bb.x1 - bb.x0;
|
||||
b->h = b->dh = bb.y1 - bb.y0;
|
||||
b->stride = imgs.packed->stride[0];
|
||||
b->bitmap = (uint8_t *)imgs.packed->planes[0] +
|
||||
b->stride * b->src_y + b->src_x * 4;
|
||||
|
||||
b->x = bb.x0 + padding;
|
||||
b->y = bb.y0 + padding;
|
||||
b->w = b->dw = mp_rect_w(bb) - padding * 2;
|
||||
b->h = b->dh = mp_rect_h(bb) - padding * 2;
|
||||
b->stride = stride;
|
||||
b->bitmap = base + b->stride * b->src_y + b->src_x * 4;
|
||||
memset_pic(b->bitmap, 0, b->w * 4, b->h, b->stride);
|
||||
|
||||
for (int i = 0; i < res->num_parts; i++) {
|
||||
@@ -315,14 +368,15 @@ static bool pack_rgba(struct mp_ass_packer *p, struct sub_bitmaps *res)
|
||||
|
||||
// Assume mp_get_sub_bb_list() never splits sub bitmaps
|
||||
// So we don't clip/adjust the size of the sub bitmap
|
||||
if (s->x > bb.x1 || s->x + s->w < bb.x0 ||
|
||||
s->y > bb.y1 || s->y + s->h < bb.y0)
|
||||
if (s->x >= b->x + b->w || s->x + s->w <= b->x ||
|
||||
s->y >= b->y + b->h || s->y + s->h <= b->y)
|
||||
continue;
|
||||
|
||||
draw_ass_rgba(s->bitmap, s->w, s->h, s->stride,
|
||||
b->bitmap, b->stride,
|
||||
s->x - bb.x0, s->y - bb.y0,
|
||||
s->x - b->x, s->y - b->y,
|
||||
s->libass.color);
|
||||
fill_padding_4(b->bitmap, b->w, b->h, b->stride, padding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -100,13 +100,16 @@ static void remove_intersecting_rcs(struct mp_rect *list, int *count)
|
||||
// NOTE: some callers assume that sub bitmaps are never split or partially
|
||||
// covered by returned rectangles.
|
||||
int mp_get_sub_bb_list(struct sub_bitmaps *sbs, struct mp_rect *out_rc_list,
|
||||
int rc_list_count)
|
||||
int rc_list_count, int padding)
|
||||
{
|
||||
int M = MERGE_RC_PIXELS;
|
||||
int num_rc = 0;
|
||||
for (int n = 0; n < sbs->num_parts; n++) {
|
||||
struct sub_bitmap *sb = &sbs->parts[n];
|
||||
struct mp_rect bb = {sb->x, sb->y, sb->x + sb->dw, sb->y + sb->dh};
|
||||
struct mp_rect bb = {sb->x - padding,
|
||||
sb->y - padding,
|
||||
sb->x + sb->dw + padding,
|
||||
sb->y + sb->dh + padding};
|
||||
bool intersects = false;
|
||||
for (int r = 0; r < num_rc; r++) {
|
||||
struct mp_rect *rc = &out_rc_list[r];
|
||||
|
||||
+1
-1
@@ -18,6 +18,6 @@ bool mp_sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb);
|
||||
#define MP_SUB_BB_LIST_MAX 15
|
||||
|
||||
int mp_get_sub_bb_list(struct sub_bitmaps *sbs, struct mp_rect *out_rc_list,
|
||||
int rc_list_count);
|
||||
int rc_list_count, int padding);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user