/* Last edited on 2005-12-10 22:27:35 by stolfi */ extern void set_yuv_matrix (void); /* Computes coefficients for luminance/chrominance transformation, for RGB coordinates in the range {[0..maxval]}. See rgb_to_yuv below. */ extern void rgb_to_yuv ( long R, long G, long B, int maxval, float *yp, float *up, float *vp ); /* Computes luminance {*yp} and chrominance {*up}, {*vp} for the given RGB color {(R,G,B)}. The results are a projective function of {(R,G,B)}, chosen so that Euclidean distance in {(y,u,v)} space corresponds more closely to perceptual color difference. For {(R,G,B)} in the {[0..maxval]^3} cube, the luminance {*yp} lies in {[0..1]}. */ extern float rgb_to_y(long R, long G, long B, int maxval); /* Computes luminance only of pixel (R,G,B), as explined in rgb_to_yuv. */ ---------------------------------------------------------------------- typedef struct yuv_matrix { float RY, GY, BY; float RGU; float RV, GV, BV; float Y0; } yuv_matrix; static yuv_matrix YUVM; extern void set_yuv_matrix (void) { /* The RGB to YUY transformation consists of multiplying the RGB coordinates (in the range [0 _ 1]) by the matrix [ 306, 601, 117] [ 291, -291, 0] / 1024 [-142, -87, 229] The result ranges in [0..1024], [-291..+291], [-229..+229] over 1024. Then we scale U and V by (1 + Y0)/(Y + Y0), where Y0 is a fixed bias. */ YUVM.RY = 306.0/1024.0; YUVM.RY = 306.0/1024.0; YUVM.GY = 601.0/1024.0; YUVM.BY = 117.0/1024.0; YUVM.RGU = 136.0/1024.0; YUVM.RV = -169.0/1024.0; YUVM.GV = 39.0/1024.0; YUVM.BV = 130.0/1024.0; YUVM.Y0 = 0.05; } extern void rgb_to_yuv ( long R, long G, long B, int maxval, float *yp, float *up, float *vp ) { register float Y, u, v, m, s; Y = YUVM.RY * R + YUVM.GY * G + YUVM.BY * B; u = YUVM.RGU * (R - G); v = YUVM.RV * R + YUVM.GV * G + YUVM.BV * B; s = YUVM.Y0 * maxval; m = Y + s; if (m+m <= s) m = s/2; m = (1 + YUVM.Y0)/m; (*yp) = Y; (*up) = u*m; (*vp) = v*m; } extern float rgb_to_y(long R, long G, long B, int maxval) { register float y; y = YUVM.RY * R + YUVM.GY * G + YUVM.BY * B; return y; } ---------------------------------------------------------------------- if (map->maxval != img->maxval) { pixel *pp; int row; register int col; pm_message( "rescaling colormap colors from maxval=%d to maxval=%d", map->maxval, img->maxval ); for (row = 0; row < map->rows; ++row) for (col = 0, pp = map->pixels[row]; col < map->cols; ++col, ++pp) PPM_DEPTH(*pp, *pp, map->maxval, img->maxval); map->maxval = img->maxval; } ----------------------------------------------------------------------