Mercurial > mplayer.hg
changeset 26839:91f8d353b6d2
Simplify yuv to rgb conversion matrix stuff.
author | reimar |
---|---|
date | Sat, 24 May 2008 12:10:08 +0000 |
parents | a6ef642cdd86 |
children | ea6c5ea1aa64 |
files | libvo/gl_common.c |
diffstat | 1 files changed, 52 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/libvo/gl_common.c Sat May 24 11:31:49 2008 +0000 +++ b/libvo/gl_common.c Sat May 24 12:10:08 2008 +0000 @@ -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 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 @@ * \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 @@ 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 @@ '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: