[encoder] New scene change detection algorithm
[schroedinger/research-port.git] / testsuite / colorspace.c
blobbf52033ad6f506c56c59348e5a6c35adbef9e6e6
2 #include <schroedinger/schro.h>
3 #include <schroedinger/schroutils.h>
5 #include <stdio.h>
6 #include <math.h>
7 #include <string.h>
9 typedef struct _ColorMatrix ColorMatrix;
10 struct _ColorMatrix {
11 double m[4][4];
14 void color_matrix_build (ColorMatrix *dst);
15 void color_matrix_apply_u8 (ColorMatrix *m, uint8_t *dest, uint8_t *src);
16 void color_matrix_apply_f64_u8 (ColorMatrix *m, double *dest, uint8_t *src);
17 void color_matrix_dump(ColorMatrix *m);
19 uint8_t colors[][3] = {
20 { 168, 44, 136 },
21 { 61, 153, 99 },
22 { 35, 174, 152 },
23 #if 0
24 { 235, 128, 128 },
25 { 226, 0, 155 },
26 { 179, 170, 0 },
27 { 150, 46, 21 },
28 { 105, 212, 235 },
29 { 76, 85, 255 },
30 { 29, 255, 107 },
31 { 16, 128, 128 },
32 #endif
35 int
36 main (int argc, char *argv[])
38 ColorMatrix m;
39 double dest[3];
40 //uint8_t src[3];
41 int i;
43 color_matrix_build (&m);
44 color_matrix_dump (&m);
45 for(i=0;i<8;i++){
46 color_matrix_apply_f64_u8 (&m, dest, colors[i]);
47 #if 0
48 src[0] = (i&2)?191:0;
49 src[1] = (i&4)?191:0;
50 src[2] = (i&1)?191:0;
51 color_matrix_apply_f64_u8 (&m, dest, src);
52 #endif
53 printf("%8.4g %8.4g %8.4g\n", dest[0], dest[1], dest[2]);
56 return 0;
60 void
61 color_matrix_set_identity (ColorMatrix *m)
63 int i,j;
65 for(i=0;i<4;i++){
66 for(j=0;j<4;j++){
67 m->m[i][j] = (i==j);
72 /* Prettyprint a 4x4 matrix @m@ */
73 void
74 color_matrix_dump(ColorMatrix *m)
76 int i,j;
78 printf("[\n");
79 for (i = 0; i < 4; i++) {
80 printf(" ");
81 for (j = 0; j < 4; j++) {
82 printf(" %8.5g", m->m[i][j]);
84 printf("\n");
86 printf("]\n");
89 /* Perform 4x4 matrix multiplication:
90 * - @dst@ = @a@ * @b@
91 * - @dst@ may be a pointer to @a@ andor @b@
93 void
94 color_matrix_multiply (ColorMatrix *dst, ColorMatrix *a, ColorMatrix *b)
96 ColorMatrix tmp;
97 int i,j,k;
99 for (i = 0; i < 4; i++) {
100 for (j = 0; j < 4; j++) {
101 double x = 0;
102 for (k = 0; k < 4; k++) {
103 x += a->m[i][k] * b->m[k][j];
105 tmp.m[i][j] = x;
109 memcpy(dst, &tmp, sizeof(ColorMatrix));
114 void
115 color_matrix_offset_components (ColorMatrix *m, double a1, double a2,
116 double a3)
118 ColorMatrix a;
120 color_matrix_set_identity (&a);
121 a.m[0][3] = a1;
122 a.m[1][3] = a2;
123 a.m[2][3] = a3;
124 color_matrix_multiply (m, &a, m);
127 void
128 color_matrix_scale_components (ColorMatrix *m, double a1, double a2,
129 double a3)
131 ColorMatrix a;
133 color_matrix_set_identity (&a);
134 a.m[0][0] = a1;
135 a.m[1][1] = a2;
136 a.m[2][2] = a3;
137 color_matrix_multiply (m, &a, m);
140 void
141 color_matrix_YCbCr_to_RGB (ColorMatrix *m, double Kr, double Kb)
143 double Kg = 1.0 - Kr - Kb;
144 ColorMatrix k = {
146 {1., 0., 2*(1-Kr), 0.},
147 {1., -2*Kb*(1-Kb)/Kg, -2*Kr*(1-Kr)/Kg, 0.},
148 {1., 2*(1-Kb), 0., 0.},
149 {0., 0., 0., 1.},
153 color_matrix_multiply (m, &k, m);
156 void
157 color_matrix_RGB_to_YCbCr (ColorMatrix *m, double Kr, double Kb)
159 double Kg = 1.0 - Kr - Kb;
160 ColorMatrix k;
161 double x;
163 k.m[0][0] = Kr;
164 k.m[0][1] = Kg;
165 k.m[0][2] = Kb;
166 k.m[0][3] = 0;
168 x = 1/(2*(1-Kb));
169 k.m[1][0] = -x*Kr;
170 k.m[1][1] = -x*Kg;
171 k.m[1][2] = x*(1-Kb);
172 k.m[1][3] = 0;
174 x = 1/(2*(1-Kr));
175 k.m[2][0] = x*(1-Kr);
176 k.m[2][1] = -x*Kg;
177 k.m[2][2] = -x*Kb;
178 k.m[2][3] = 0;
180 k.m[3][0] = 0;
181 k.m[3][1] = 0;
182 k.m[3][2] = 0;
183 k.m[3][3] = 1;
185 color_matrix_multiply (m, &k, m);
188 void
189 color_matrix_build (ColorMatrix *dst)
191 #if 0
193 * At this point, everything is in YCbCr
194 * All components are in the range [0,255]
196 color_matrix_set_identity (dst);
198 /* offset required to get input video black to (0.,0.,0.) */
199 color_matrix_offset_components (dst, -16, -128, -128);
201 /* scale required to get input video black to (0.,0.,0.) */
202 color_matrix_scale_components (dst, (1/219.0), (1/224.0), (1/224.0));
204 /* colour matrix, YCbCr -> RGB */
205 /* Requires Y in [0,1.0], Cb&Cr in [-0.5,0.5] */
206 color_matrix_YCbCr_to_RGB (dst, 0.2990, 0.1140); // SD
207 //color_matrix_YCbCr_to_RGB (dst, 0.2126, 0.0722); // HD
210 * We are now in RGB space
213 /* scale to output range. */
214 color_matrix_scale_components (dst, 255.0, 255.0, 255.0);
215 #else
216 color_matrix_set_identity (dst);
218 color_matrix_scale_components (dst, (1/255.0), (1/255.0), (1/255.0));
220 color_matrix_RGB_to_YCbCr (dst, 0.2990, 0.1140); // SD
221 //color_matrix_RGB_to_YCbCr (dst, 0.2126, 0.0722); // HD
222 color_matrix_RGB_to_YCbCr (dst, 0.212, 0.087); // SMPTE 240M
224 color_matrix_scale_components (dst, 219.0, 224.0, 224.0);
226 color_matrix_offset_components (dst, 16, 128, 128);
227 #endif
230 void
231 color_matrix_apply_u8 (ColorMatrix *m, uint8_t *dest, uint8_t *src)
233 int i;
235 for (i = 0; i < 3; i++) {
236 double x = 0;
237 x += m->m[i][0] * src[0];
238 x += m->m[i][1] * src[1];
239 x += m->m[i][2] * src[2];
240 x += m->m[i][3];
241 dest[i] = CLAMP(floor(x + 0.5),0,255);
245 void
246 color_matrix_apply_f64_u8 (ColorMatrix *m, double *dest, uint8_t *src)
248 int i;
250 for (i = 0; i < 3; i++) {
251 double x = 0;
252 x += m->m[i][0] * src[0];
253 x += m->m[i][1] * src[1];
254 x += m->m[i][2] * src[2];
255 x += m->m[i][3];
256 dest[i] = CLAMP(floor(x + 0.5),0,255);
257 //dest[i] = x;
262 * SMPTE 170M
263 * ==========
265 * NTSC, SD, 525 lines
267 * color primaries:
268 * "SMPTE C set"
269 * r 0.630 0.340
270 * g 0.310 0.595
271 * b 0.155 0.070
272 * w D65
274 * "NTSC 1953"
275 * r 0.67 0.33
276 * g 0.21 0.71
277 * b 0.14 0.08
278 * w D65
280 * transfer function:
282 * LT= [(Vr + 0.099)/1.099]^(1/0.4500) for 0.0812 ≤ Vr ≤ 1
283 * LT = Vr/4.500 for 0 ≤ Vr < 0.0812
285 * also defines SD SMPTE color bars
289 * EBU 3213-E
290 * ==========
292 * r 0.64 0.33
293 * g 0.29 0.60
294 * b 0.15 0.06
295 * w D65