]> git.sesse.net Git - mlt/blob - src/modules/videostab/stab/utils.c
6f06eaf11192466522b74a9cf5538ee2363c292e
[mlt] / src / modules / videostab / stab / utils.c
1 /*
2  * Video stabilizer
3  *
4  * Copyright (c) 2008 Lenny <leonardo.masoni@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21
22 #include "utils.h"
23
24 int *lanc_kernels = NULL;
25
26 float lanc(float x, float r) {
27
28     float t = x * M_PI;
29
30     if (x == 0.0)
31         return 1.0;
32
33     if (x <= -r || x >= r)
34         return 0.0;
35         
36     return r * sin(t) * sin(t / r) / (t * t);
37 }
38
39 float hann(float x, float d) {
40
41     if (x < 0.0 || x > d)
42         return 0.0;
43
44     return 0.5 * (1.0 - cos((M_PI * 2.0 * x) / (d - 1.0)));
45 }
46
47 int clamp(int a, int b, int c) {
48
49     if (a < b)
50         a = b;
51
52     if (a > c)
53         a = c;
54
55     return a;
56 }
57
58 void lopass(vc *vi, vc *vo, int l, int r) {
59
60     int d = r * 2 + 1;
61     float *ck = (float *)malloc(d * sizeof(float));
62     float cw = 0.0;
63
64     int i, j;
65
66     for (i = 0; i < d; i ++)
67         cw += ck[i] = hann(i, d - 1);
68
69     for (i = 0; i < l; i ++) {
70     
71         vc a = vc_zero();
72
73         for (j = i - r; j <= i + r; j ++) {
74
75             int jc = clamp(j, 0, l - 1);
76
77             vc_mul_acc(&a, vi[jc], ck[j - i + r]);
78         }
79
80         vo[i] = vc_div(a, cw);
81     }
82     
83     free(ck);
84 }
85
86 void hipass(vc *vi, vc *vo, int l, int r) {
87
88     int i;
89
90     lopass(vi, vo, l, r);
91
92     for (i = 0; i < l; i ++)
93         vo[i] = vc_sub(vi[i], vo[i]);
94 }
95
96 void prepare_lanc_kernels() {
97
98     int i, j;
99
100     lanc_kernels = (int *)malloc(256 * 8 * sizeof(int));
101
102     for (i = 0; i < 256; i ++)
103         for (j = -3; j < 5; j ++)
104             lanc_kernels[i * 8 + j + 3] = lanc(j - i / 256.0, 4) * 1024.0;
105 }
106
107 int *select_lanc_kernel(float x) {
108
109     return lanc_kernels + (int)((x - floor(x)) * 256.0) * 8;
110 }
111
112 void free_lanc_kernels() {
113
114     free(lanc_kernels);
115 }
116
117 vc interp(vc *vi, int l, float x) {
118
119     vc a = vc_zero();
120     int xd = floor(x);
121     int *lk = select_lanc_kernel(x);
122
123     int i;
124
125     for (i = -3; i < 5; i ++) {
126     
127         int ic = clamp(xd + i, 0, l - 1);
128
129         vc_mul_acc(&a, vi[ic], lk[i + 3]);
130     }
131
132     return vc_div(a, 1024.0);
133 }
134