summaryrefslogtreecommitdiff
path: root/src/internal/subtitle/renderers/kitsubimage.c
blob: 2bc9cf0bd362fa47f3890653d9f335f67062e79c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <assert.h>
#include <stdlib.h>

#include <SDL2/SDL_Surface.h>

#include "kitchensink/kiterror.h"
#include "kitchensink/internal/utils/kitlog.h"
#include "kitchensink/internal/subtitle/kitsubtitlepacket.h"
#include "kitchensink/internal/subtitle/renderers/kitsubimage.h"


static void _ProcessSubImage(SDL_Surface *surface, const AVSubtitleRect *rect, int min_x, int min_y) {
    SDL_Surface *src = SDL_CreateRGBSurfaceWithFormatFrom(
        rect->data[0], rect->w, rect->h, 8, rect->linesize[0], SDL_PIXELFORMAT_INDEX8);
    SDL_SetPaletteColors(src->format->palette, (SDL_Color*)rect->data[1], 0, 256);

    SDL_Rect dst_rect;
    dst_rect.x = rect->x - min_x;
    dst_rect.y = rect->y - min_y;

    SDL_BlitSurface(src, NULL, surface, &dst_rect);
}

static Kit_SubtitlePacket* ren_render_image_cb(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts) {
    assert(ren != NULL);
    assert(src != NULL);

    AVSubtitle *sub = src;
    SDL_Surface *surface = NULL;
    int x0 = INT_MAX, y0 = INT_MAX;
    int x1 = 0, y1 = 0;
    int w, h;
    int has_content = 0;

    // Find sizes of incoming subtitle bitmaps
    for(int n = 0; n < sub->num_rects; n++) {
        AVSubtitleRect *r = sub->rects[n];
        if(r->type != SUBTITLE_BITMAP)
            continue;
        has_content = 1;
        if(r->x < x0)
            x0 = r->x;
        if(r->y < y0)
            y0 = r->y;
        if(r->x + r->w > x1)
            x1 = r->x + r->w;
        if(r->y + r->h > y1)
            y1 = r->y + r->h;
    }

    if(has_content == 0) {
        return NULL;
    }

    w = x1 - x0;
    h = y1 - y0;
    LOG("x, y = %d, %d  w, h = %d, %d\n", x0, y0, w, h);

    // Surface to render on
    surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGBA32);
    SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
    SDL_FillRect(surface, NULL, 0);

    // Render subimages to the target surface.
    for(int n = 0; n < sub->num_rects; n++) {
        AVSubtitleRect *r = sub->rects[n];
        if(r->type != SUBTITLE_BITMAP)
            continue;
        _ProcessSubImage(surface, r, x0, y0);
    }

    LOG("Setting %f, %f\n", start_pts, end_pts);
    return Kit_CreateSubtitlePacket(start_pts, end_pts, x0, y0, surface);
}


Kit_SubtitleRenderer* Kit_CreateImageSubtitleRenderer(const Kit_Decoder *dec, int w, int h) {
    assert(dec != NULL);
    assert(w >= 0);
    assert(h >= 0);

    // Allocate a new renderer
    Kit_SubtitleRenderer *ren = Kit_CreateSubtitleRenderer();
    if(ren == NULL) {
        return NULL;
    }

    // Only renderer required, no other data.
    ren->ren_render = ren_render_image_cb;
    ren->ren_close = NULL;
    ren->userdata = NULL;
    return ren;
}