mirror of https://github.com/mpv-player/mpv
Simplify yuv to rgb conversion matrix stuff.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@26871 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
5ba240c875
commit
6701227e16
|
@ -14,6 +14,7 @@
|
|||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "gl_common.h"
|
||||
#include "libavutil/common.h"
|
||||
|
||||
/**
|
||||
* \defgroup glextfunctions OpenGL extension functions
|
||||
|
@ -866,29 +867,35 @@ static void create_scaler_textures(int scaler, int *texu, char *texs) {
|
|||
|
||||
static void gen_gamma_map(unsigned char *map, int size, float gamma);
|
||||
|
||||
static void get_yuv2rgb_coeffs(gl_conversion_params_t *params,
|
||||
float *ry, float *ru, float *rv, float *rc,
|
||||
float *gy, float *gu, float *gv, float *gc,
|
||||
float *by, float *bu, float *bv, float *bc) {
|
||||
#define ROW_R 0
|
||||
#define ROW_G 1
|
||||
#define ROW_B 2
|
||||
#define COL_Y 0
|
||||
#define COL_U 1
|
||||
#define COL_V 2
|
||||
#define COL_C 3
|
||||
|
||||
static void get_yuv2rgb_coeffs(gl_conversion_params_t *params, float yuv2rgb[3][4]) {
|
||||
float uvcos = params->saturation * cos(params->hue);
|
||||
float uvsin = params->saturation * sin(params->hue);
|
||||
*ry = 1.164 * params->contrast;
|
||||
*gy = 1.164 * params->contrast;
|
||||
*by = 1.164 * params->contrast;
|
||||
*ru = 0 * uvcos + 1.596 * uvsin;
|
||||
*rv = 0 * uvsin + 1.596 * uvcos;
|
||||
*gu = -0.391 * uvcos + -0.813 * uvsin;
|
||||
*gv = -0.391 * uvsin + -0.813 * uvcos;
|
||||
*bu = 2.018 * uvcos + 0 * uvsin;
|
||||
*bv = 2.018 * uvsin + 0 * uvcos;
|
||||
*rc = (-16 * *ry + (-128) * *ru + (-128) * *rv) / 255.0 + params->brightness;
|
||||
*gc = (-16 * *gy + (-128) * *gu + (-128) * *gv) / 255.0 + params->brightness;
|
||||
*bc = (-16 * *by + (-128) * *bu + (-128) * *bv) / 255.0 + params->brightness;
|
||||
// these "center" contrast control so that e.g. a contrast of 0
|
||||
// leads to a grey image, not a black one
|
||||
*rc += 0.5 - params->contrast / 2.0;
|
||||
*gc += 0.5 - params->contrast / 2.0;
|
||||
*bc += 0.5 - params->contrast / 2.0;
|
||||
int i;
|
||||
float uv_coeffs[3][2] = {
|
||||
{ 0.000, 1.596},
|
||||
{-0.391, -0.813},
|
||||
{ 2.018, 0.000}
|
||||
};
|
||||
for (i = 0; i < 3; i++) {
|
||||
yuv2rgb[i][COL_C] = params->brightness;
|
||||
yuv2rgb[i][COL_Y] = 1.164 * params->contrast;
|
||||
yuv2rgb[i][COL_C] += (-16 / 255.0) * yuv2rgb[i][COL_Y];
|
||||
yuv2rgb[i][COL_U] = uv_coeffs[i][0] * uvcos + uv_coeffs[i][1] * uvsin;
|
||||
yuv2rgb[i][COL_C] += (-128 / 255.0) * yuv2rgb[i][COL_U];
|
||||
yuv2rgb[i][COL_V] = uv_coeffs[i][0] * uvsin + uv_coeffs[i][1] * uvcos;
|
||||
yuv2rgb[i][COL_C] += (-128 / 255.0) * yuv2rgb[i][COL_V];
|
||||
// this "centers" contrast control so that e.g. a contrast of 0
|
||||
// leads to a grey image, not a black one
|
||||
yuv2rgb[i][COL_C] += 0.5 - params->contrast / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
//! size of gamma map use to avoid slow exp function in gen_yuv2rgb_map
|
||||
|
@ -900,40 +907,28 @@ static void get_yuv2rgb_coeffs(gl_conversion_params_t *params,
|
|||
* \param size size of the map, excluding border
|
||||
*/
|
||||
static void gen_yuv2rgb_map(gl_conversion_params_t *params, unsigned char *map, int size) {
|
||||
int i, j, k;
|
||||
int i, j, k, l;
|
||||
float step = 1.0 / size;
|
||||
float y, u, v;
|
||||
float r, g, b;
|
||||
float ry, ru, rv, rc;
|
||||
float gy, gu, gv, gc;
|
||||
float by, bu, bv, bc;
|
||||
float yuv2rgb[3][4];
|
||||
unsigned char gmaps[3][GMAP_SIZE];
|
||||
gen_gamma_map(gmaps[0], GMAP_SIZE, params->rgamma);
|
||||
gen_gamma_map(gmaps[1], GMAP_SIZE, params->ggamma);
|
||||
gen_gamma_map(gmaps[2], GMAP_SIZE, params->bgamma);
|
||||
get_yuv2rgb_coeffs(params,
|
||||
&ry, &ru, &rv, &rc, &gy, &gu, &gv, &gc, &by, &bu, &bv, &bc);
|
||||
ry *= GMAP_SIZE - 1; ru *= GMAP_SIZE - 1; rv *= GMAP_SIZE - 1; rc *= GMAP_SIZE - 1;
|
||||
gy *= GMAP_SIZE - 1; gu *= GMAP_SIZE - 1; gv *= GMAP_SIZE - 1; gc *= GMAP_SIZE - 1;
|
||||
by *= GMAP_SIZE - 1; bu *= GMAP_SIZE - 1; bv *= GMAP_SIZE - 1; bc *= GMAP_SIZE - 1;
|
||||
get_yuv2rgb_coeffs(params, yuv2rgb);
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
yuv2rgb[i][j] *= GMAP_SIZE - 1;
|
||||
v = 0;
|
||||
for (i = -1; i <= size; i++) {
|
||||
u = 0;
|
||||
for (j = -1; j <= size; j++) {
|
||||
y = 0;
|
||||
for (k = -1; k <= size; k++) {
|
||||
r = ry * y + ru * u + rv * v + rc;
|
||||
g = gy * y + gu * u + gv * v + gc;
|
||||
b = by * y + bu * u + bv * v + bc;
|
||||
if (r > GMAP_SIZE - 1) r = GMAP_SIZE - 1;
|
||||
if (r < 0) r = 0;
|
||||
if (g > GMAP_SIZE - 1) g = GMAP_SIZE - 1;
|
||||
if (g < 0) g = 0;
|
||||
if (b > GMAP_SIZE - 1) b = GMAP_SIZE - 1;
|
||||
if (b < 0) b = 0;
|
||||
*map++ = gmaps[0][(int)r];
|
||||
*map++ = gmaps[1][(int)g];
|
||||
*map++ = gmaps[2][(int)b];
|
||||
for (l = 0; l < 3; l++) {
|
||||
float rgb = yuv2rgb[l][COL_Y] * y + yuv2rgb[l][COL_U] * u + yuv2rgb[l][COL_V] * v + yuv2rgb[l][COL_C];
|
||||
*map++ = gmaps[l][av_clip(rgb, 0, GMAP_SIZE - 1)];
|
||||
}
|
||||
y += (k == -1 || k == size - 1) ? step / 2 : step;
|
||||
}
|
||||
u += (j == -1 || j == size - 1) ? step / 2 : step;
|
||||
|
@ -1166,9 +1161,7 @@ static void glSetupYUVFragprog(gl_conversion_params_t *params) {
|
|||
GLint i;
|
||||
// this is the conversion matrix, with y, u, v factors
|
||||
// for red, green, blue and the constant offsets
|
||||
float ry, ru, rv, rc;
|
||||
float gy, gu, gv, gc;
|
||||
float by, bu, bv, bc;
|
||||
float yuv2rgb[3][4];
|
||||
create_conv_textures(params, &cur_texu, conv_texs);
|
||||
create_scaler_textures(YUV_LUM_SCALER(type), &cur_texu, lum_scale_texs);
|
||||
if (YUV_CHROM_SCALER(type) == YUV_LUM_SCALER(type))
|
||||
|
@ -1194,21 +1187,29 @@ static void glSetupYUVFragprog(gl_conversion_params_t *params) {
|
|||
'1', 'g', rect, texw / 2, texh / 2, params->filter_strength);
|
||||
add_scaler(YUV_CHROM_SCALER(type), &prog_pos, &prog_remain, chrom_scale_texs,
|
||||
'2', 'b', rect, texw / 2, texh / 2, params->filter_strength);
|
||||
get_yuv2rgb_coeffs(params,
|
||||
&ry, &ru, &rv, &rc, &gy, &gu, &gv, &gc, &by, &bu, &bv, &bc);
|
||||
get_yuv2rgb_coeffs(params, yuv2rgb);
|
||||
switch (YUV_CONVERSION(type)) {
|
||||
case YUV_CONVERSION_FRAGMENT:
|
||||
snprintf(prog_pos, prog_remain, yuv_prog_template,
|
||||
ry, gy, by, ru, gu, bu, rv, gv, bv, rc, gc, bc);
|
||||
yuv2rgb[ROW_R][COL_Y], yuv2rgb[ROW_G][COL_Y], yuv2rgb[ROW_B][COL_Y],
|
||||
yuv2rgb[ROW_R][COL_U], yuv2rgb[ROW_G][COL_U], yuv2rgb[ROW_B][COL_U],
|
||||
yuv2rgb[ROW_R][COL_V], yuv2rgb[ROW_G][COL_V], yuv2rgb[ROW_B][COL_V],
|
||||
yuv2rgb[ROW_R][COL_C], yuv2rgb[ROW_G][COL_C], yuv2rgb[ROW_B][COL_C]);
|
||||
break;
|
||||
case YUV_CONVERSION_FRAGMENT_POW:
|
||||
snprintf(prog_pos, prog_remain, yuv_pow_prog_template,
|
||||
ry, gy, by, ru, gu, bu, rv, gv, bv, rc, gc, bc,
|
||||
yuv2rgb[ROW_R][COL_Y], yuv2rgb[ROW_G][COL_Y], yuv2rgb[ROW_B][COL_Y],
|
||||
yuv2rgb[ROW_R][COL_U], yuv2rgb[ROW_G][COL_U], yuv2rgb[ROW_B][COL_U],
|
||||
yuv2rgb[ROW_R][COL_V], yuv2rgb[ROW_G][COL_V], yuv2rgb[ROW_B][COL_V],
|
||||
yuv2rgb[ROW_R][COL_C], yuv2rgb[ROW_G][COL_C], yuv2rgb[ROW_B][COL_C],
|
||||
(float)1.0 / params->rgamma, (float)1.0 / params->bgamma, (float)1.0 / params->bgamma);
|
||||
break;
|
||||
case YUV_CONVERSION_FRAGMENT_LOOKUP:
|
||||
snprintf(prog_pos, prog_remain, yuv_lookup_prog_template,
|
||||
ry, gy, by, ru, gu, bu, rv, gv, bv, rc, gc, bc,
|
||||
yuv2rgb[ROW_R][COL_Y], yuv2rgb[ROW_G][COL_Y], yuv2rgb[ROW_B][COL_Y],
|
||||
yuv2rgb[ROW_R][COL_U], yuv2rgb[ROW_G][COL_U], yuv2rgb[ROW_B][COL_U],
|
||||
yuv2rgb[ROW_R][COL_V], yuv2rgb[ROW_G][COL_V], yuv2rgb[ROW_B][COL_V],
|
||||
yuv2rgb[ROW_R][COL_C], yuv2rgb[ROW_G][COL_C], yuv2rgb[ROW_B][COL_C],
|
||||
conv_texs[0], conv_texs[0], conv_texs[0]);
|
||||
break;
|
||||
case YUV_CONVERSION_FRAGMENT_LOOKUP3D:
|
||||
|
|
Loading…
Reference in New Issue