2 #include <schroedinger/schro.h>
3 #include <schroedinger/schroutils.h>
9 typedef struct _ColorMatrix ColorMatrix
;
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] = {
36 main (int argc
, char *argv
[])
43 color_matrix_build (&m
);
44 color_matrix_dump (&m
);
46 color_matrix_apply_f64_u8 (&m
, dest
, colors
[i
]);
51 color_matrix_apply_f64_u8 (&m
, dest
, src
);
53 printf("%8.4g %8.4g %8.4g\n", dest
[0], dest
[1], dest
[2]);
61 color_matrix_set_identity (ColorMatrix
*m
)
72 /* Prettyprint a 4x4 matrix @m@ */
74 color_matrix_dump(ColorMatrix
*m
)
79 for (i
= 0; i
< 4; i
++) {
81 for (j
= 0; j
< 4; j
++) {
82 printf(" %8.5g", m
->m
[i
][j
]);
89 /* Perform 4x4 matrix multiplication:
91 * - @dst@ may be a pointer to @a@ andor @b@
94 color_matrix_multiply (ColorMatrix
*dst
, ColorMatrix
*a
, ColorMatrix
*b
)
99 for (i
= 0; i
< 4; i
++) {
100 for (j
= 0; j
< 4; j
++) {
102 for (k
= 0; k
< 4; k
++) {
103 x
+= a
->m
[i
][k
] * b
->m
[k
][j
];
109 memcpy(dst
, &tmp
, sizeof(ColorMatrix
));
115 color_matrix_offset_components (ColorMatrix
*m
, double a1
, double a2
,
120 color_matrix_set_identity (&a
);
124 color_matrix_multiply (m
, &a
, m
);
128 color_matrix_scale_components (ColorMatrix
*m
, double a1
, double a2
,
133 color_matrix_set_identity (&a
);
137 color_matrix_multiply (m
, &a
, m
);
141 color_matrix_YCbCr_to_RGB (ColorMatrix
*m
, double Kr
, double Kb
)
143 double Kg
= 1.0 - Kr
- Kb
;
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.},
153 color_matrix_multiply (m
, &k
, m
);
157 color_matrix_RGB_to_YCbCr (ColorMatrix
*m
, double Kr
, double Kb
)
159 double Kg
= 1.0 - Kr
- Kb
;
171 k
.m
[1][2] = x
*(1-Kb
);
175 k
.m
[2][0] = x
*(1-Kr
);
185 color_matrix_multiply (m
, &k
, m
);
189 color_matrix_build (ColorMatrix
*dst
)
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);
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);
231 color_matrix_apply_u8 (ColorMatrix
*m
, uint8_t *dest
, uint8_t *src
)
235 for (i
= 0; i
< 3; i
++) {
237 x
+= m
->m
[i
][0] * src
[0];
238 x
+= m
->m
[i
][1] * src
[1];
239 x
+= m
->m
[i
][2] * src
[2];
241 dest
[i
] = CLAMP(floor(x
+ 0.5),0,255);
246 color_matrix_apply_f64_u8 (ColorMatrix
*m
, double *dest
, uint8_t *src
)
250 for (i
= 0; i
< 3; i
++) {
252 x
+= m
->m
[i
][0] * src
[0];
253 x
+= m
->m
[i
][1] * src
[1];
254 x
+= m
->m
[i
][2] * src
[2];
256 dest
[i
] = CLAMP(floor(x
+ 0.5),0,255);
265 * NTSC, SD, 525 lines
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