mirror of
https://github.com/mpv-player/mpv
synced 2025-01-03 13:32:16 +00:00
img_convert: add sub_bitmap bounding box functions
mp_sub_bitmaps_bb is just sub_bitmaps_bb renamed/moved.
This commit is contained in:
parent
23f731839a
commit
03730e73dc
@ -27,6 +27,7 @@
|
||||
#include "core/mp_common.h"
|
||||
#include "sub/draw_bmp.h"
|
||||
#include "sub/sub.h"
|
||||
#include "sub/img_convert.h"
|
||||
#include "video/mp_image.h"
|
||||
#include "video/sws_utils.h"
|
||||
#include "video/img_format.h"
|
||||
@ -543,7 +544,7 @@ void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst,
|
||||
get_closest_y444_format(dst->imgfmt, &format, &bits);
|
||||
|
||||
struct mp_rect bb;
|
||||
if (!sub_bitmaps_bb(sbs, &bb))
|
||||
if (!mp_sub_bitmaps_bb(sbs, &bb))
|
||||
return;
|
||||
|
||||
if (!align_bbox_for_swscale(dst, &bb))
|
||||
|
@ -211,7 +211,7 @@ bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
|
||||
imgs->num_parts = 0;
|
||||
|
||||
struct mp_rect bb;
|
||||
if (!sub_bitmaps_bb(&src, &bb))
|
||||
if (!mp_sub_bitmaps_bb(&src, &bb))
|
||||
return true;
|
||||
|
||||
bmp->x = bb.x0;
|
||||
@ -239,3 +239,85 @@ bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
|
||||
imgs->num_parts = 1;
|
||||
return 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};
|
||||
for (int n = 0; n < imgs->num_parts; n++) {
|
||||
struct sub_bitmap *p = &imgs->parts[n];
|
||||
bb.x0 = FFMIN(bb.x0, p->x);
|
||||
bb.y0 = FFMIN(bb.y0, p->y);
|
||||
bb.x1 = FFMAX(bb.x1, p->x + p->dw);
|
||||
bb.y1 = FFMAX(bb.y1, p->y + p->dh);
|
||||
}
|
||||
|
||||
// avoid degenerate bounding box if empty
|
||||
bb.x0 = FFMIN(bb.x0, bb.x1);
|
||||
bb.y0 = FFMIN(bb.y0, bb.y1);
|
||||
|
||||
*out_bb = bb;
|
||||
|
||||
return bb.x0 < bb.x1 && bb.y0 < bb.y1;
|
||||
}
|
||||
|
||||
// Merge bounding rectangles if they're closer than the given amount of pixels.
|
||||
// Avoids having too many rectangles due to spacing between letter.
|
||||
#define MERGE_RC_PIXELS 50
|
||||
|
||||
static void remove_intersecting_rcs(struct mp_rect *list, int *count)
|
||||
{
|
||||
int M = MERGE_RC_PIXELS;
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (int a = 0; a < *count; a++) {
|
||||
struct mp_rect *rc_a = &list[a];
|
||||
for (int b = *count - 1; b > a; b--) {
|
||||
struct mp_rect *rc_b = &list[b];
|
||||
if (rc_a->x0 - M <= rc_b->x1 && rc_a->x1 + M >= rc_b->x0 &&
|
||||
rc_a->y0 - M <= rc_b->y1 && rc_a->y1 + M >= rc_b->y0)
|
||||
{
|
||||
mp_rect_union(rc_a, rc_b);
|
||||
MP_TARRAY_REMOVE_AT(list, *count, b);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cluster the given subrectangles into a small numbers of bounding rectangles,
|
||||
// and store them into list. E.g. when subtitles and toptitles are visible at
|
||||
// the same time, there should be two bounding boxes, so that the video between
|
||||
// the text is left untouched (need to resample less pixels -> faster).
|
||||
// Returns number of rectangles added to out_rc_list (<= rc_list_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 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};
|
||||
bool intersects = false;
|
||||
for (int r = 0; r < num_rc; r++) {
|
||||
struct mp_rect *rc = &out_rc_list[r];
|
||||
if ((bb.x0 - M <= rc->x1 && bb.x1 + M >= rc->x0 &&
|
||||
bb.y0 - M <= rc->y1 && bb.y1 + M >= rc->y0) ||
|
||||
num_rc == rc_list_count)
|
||||
{
|
||||
mp_rect_union(rc, &bb);
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!intersects) {
|
||||
out_rc_list[num_rc++] = bb;
|
||||
remove_intersecting_rcs(out_rc_list, &num_rc);
|
||||
}
|
||||
}
|
||||
remove_intersecting_rcs(out_rc_list, &num_rc);
|
||||
return num_rc;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
struct osd_conv_cache;
|
||||
struct sub_bitmaps;
|
||||
struct mp_rect;
|
||||
|
||||
struct osd_conv_cache *osd_conv_cache_new(void);
|
||||
|
||||
@ -17,4 +18,15 @@ bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
|
||||
double gblur);
|
||||
bool osd_conv_idx_to_gray(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
|
||||
|
||||
|
||||
bool mp_sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb);
|
||||
|
||||
// Intentionally limit the maximum number of bounding rects to something low.
|
||||
// This prevents the algorithm from degrading to O(N^2).
|
||||
// Most subtitles yield a very low number of bounding rects (<5).
|
||||
#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);
|
||||
|
||||
#endif
|
||||
|
20
sub/sub.c
20
sub/sub.c
@ -333,23 +333,3 @@ void osd_subs_changed(struct osd_state *osd)
|
||||
vo_osd_changed(n);
|
||||
}
|
||||
}
|
||||
|
||||
bool sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb)
|
||||
{
|
||||
struct mp_rect bb = {INT_MAX, INT_MAX, INT_MIN, INT_MIN};
|
||||
for (int n = 0; n < imgs->num_parts; n++) {
|
||||
struct sub_bitmap *p = &imgs->parts[n];
|
||||
bb.x0 = FFMIN(bb.x0, p->x);
|
||||
bb.y0 = FFMIN(bb.y0, p->y);
|
||||
bb.x1 = FFMAX(bb.x1, p->x + p->dw);
|
||||
bb.y1 = FFMAX(bb.y1, p->y + p->dh);
|
||||
}
|
||||
|
||||
// avoid degenerate bounding box if empty
|
||||
bb.x0 = FFMIN(bb.x0, bb.x1);
|
||||
bb.y0 = FFMIN(bb.y0, bb.y1);
|
||||
|
||||
*out_bb = bb;
|
||||
|
||||
return bb.x0 < bb.x1 && bb.y0 < bb.y1;
|
||||
}
|
||||
|
@ -227,9 +227,6 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res,
|
||||
double video_pts, int draw_flags,
|
||||
struct mp_image_pool *pool, struct mp_image *dest);
|
||||
|
||||
struct mp_rect;
|
||||
bool sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb);
|
||||
|
||||
// defined in osd_libass.c and osd_dummy.c
|
||||
|
||||
void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
|
||||
|
Loading…
Reference in New Issue
Block a user