题意:给你三种颜色表示模式,RGB,HSV和HSL,实现任意模式之间两两转化。
1.最好别看题目中给的转化公式描述,我觉得叙述的一点也不清楚,看维基百科,把维基百科上的公式一句一句翻译过来就好
2.在公式换算的时候,全部转成小数形式。例如:RGB的取值范围0-255转化成0-1, 即r = R/255.0, g = G/255.0 b = B/255.0……
3.HSL->RGB和HSV->RGB需要四舍五入,而HSV和HSL之间的互相转化需要通过RGB: HSV<=>RGB<=>HSL,这里转RGB的时候不需要四舍五入。
4.对于自己转自己的情况,例如RGB->RGB,直接原样输出。
写的时候脑子不是很清楚,加上WA之后各种瞎改,代码略丑= =凑合着看吧……
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; const double eps = 1e-9; struct node { int val[3]; bool second; double ang[3]; }; char tar[8]; char ori[8]; node A, ans; int dcmp( double a ) { if ( fabs(a) < eps ) return 0; return a < 0 ? -1 : 1; } int Round( double a ) { return (int)(a + 0.5); } void init() { scanf( "%s", ori ); //printf("A: "); char tmp[20]; for ( int i = 0; i < 3; ++i ) { scanf( "%s", tmp ); sscanf( tmp, "%d", &A.val[i] ); //printf( "%d ", A.val[i] ); } A.second = false; //puts(""); return; } void RGBtoHSL() { double r, g, b; if ( A.second ) { r = A.ang[0]; g = A.ang[1]; b = A.ang[2]; } else { r = A.val[0]/255.0; g = A.val[1]/255.0; b = A.val[2]/255.0; } double h, l, s; //printf( "rgb: %f %f %f ", r, g, b ); double maxi = max( max(r, g), b ); double mini = min( min(r, g), b ); double delta = maxi - mini; if ( dcmp( maxi - mini ) == 0 ) { h = 0.0; } else if ( dcmp( maxi - r ) == 0 ) { if ( dcmp( g - b ) >= 0 ) { h = 60.0*(g-b)/delta+0; } else { h = 60.0*(g-b)/delta+360; } } else if ( dcmp( maxi - g ) == 0 ) { h = 60.0*(b-r)/delta+120; } else if ( dcmp( maxi - b ) == 0 ) { h = 60.0*(r-g)/delta+240; } l = 0.5*(maxi+mini); //printf("l:%f ", l); if ( dcmp(l) == 0 || dcmp( delta ) == 0 ) { s = 0.0; } else if ( dcmp(l) > 0 && dcmp( 0.5 - l ) >= 0 ) { s = delta/(maxi+mini); } else { s = delta/(2.0-(maxi+mini)); } //printf( "%s ", tar ); //printf("%.0f %.0f%% %.0f%% ", h+eps, s*100+eps, l*100+eps ); //printf("%d %d%% %d%% ", Round(h+eps), Round(s*100+eps), Round(l*100+eps) ); ans.val[0] = Round(h); ans.val[1] = Round(s*100); ans.val[2] = Round(l*100); return; } void RGBtoHSV() { double r, g, b; if ( A.second ) { r = A.ang[0]; g = A.ang[1]; b = A.ang[2]; } else { r = A.val[0]/255.0; g = A.val[1]/255.0; b = A.val[2]/255.0; } double h, v, s; double maxi = max( max(r, g), b ); double mini = min( min(r, g), b ); double delta = maxi - mini; if ( dcmp( delta ) == 0 ) { h = 0; } else if ( dcmp( maxi - r ) == 0 ) { if ( dcmp( g - b ) >= 0 ) { h = 60.0*(g-b)/delta+0; } else { h = 60.0*(g-b)/delta+360; } } else if ( dcmp( maxi - g ) == 0 ) { h = 60.0*(b-r)/delta+120; } else if ( dcmp( maxi - b ) == 0 ) { h = 60.0*(r-g)/delta+240; } if ( dcmp( maxi ) == 0 ) { s = 0; } else s = (double)(maxi-mini)/maxi; v = maxi; //printf( "%s ", tar ); //printf("%f %f %f ", h+eps, s*100+eps, v*100+eps ); //printf("%d %d%% %d%% ", Round(h+eps), Round(s*100+eps), Round(v*100+eps) ); ans.val[0] = Round(h); ans.val[1] = Round(s*100); ans.val[2] = Round(v*100); return; } void jiuzheng( double &tC ) { if ( dcmp( tC ) < 0 ) tC += 1.0; if ( dcmp( tC - 1.0 ) > 0 ) tC -= 1.0; return; } double GetRGB( double p, double q, double tC ) { if ( dcmp( 1.0/6.0 - tC ) > 0 ) { return p + ( (q - p) * 6.0 * tC ); } else if ( dcmp( 0.5 - tC ) > 0 ) { return q; } else if ( dcmp( 2.0/3.0 - tC ) > 0 ) { return p + ( (q-p)*4.0 - (q-p)*6.0*tC ); } else return p; } void HSLtoRGB() { double h, s, l; double r, g, b; //int R, G, B; h = A.val[0]/360.0; s = A.val[1]/100.0; l = A.val[2]/100.0; if ( dcmp(s) == 0 ) { r = l; g = l; b = l; } else { double p, q, tR, tG, tB; if ( dcmp( 0.5 - l ) > 0 ) q = l * ( 1.0 + s ); else q = l + s - ( l * s ); p = 2 * l - q; tR = h + 1.0/3.0; tG = h; tB = h - 1.0/3.0; jiuzheng( tR ); jiuzheng( tG ); jiuzheng( tB ); //r = GetRGB( p, q, tR )*255.0; r = GetRGB( p, q, tR ); //g = GetRGB( p, q, tG )*255.0; g = GetRGB( p, q, tG ); //b = GetRGB( p, q, tB )*255.0; b = GetRGB( p, q, tB ); } //printf( "%s ", tar ); //printf( "RGB: %d %d %d ", r, g, b ); A.ang[0] = r; A.ang[1] = g; A.ang[2] = b; A.val[0] = Round( r * 255 ); A.val[1] = Round( g * 255 ); A.val[2] = Round( b * 255 ); //printf("HSLtoRGB: %d %d %d ", A.val[0], A.val[1], A.val[2] ); for ( int i = 0; i < 3; ++i ) ans.val[i] = A.val[i]; return; } void HSVtoRGB() { double h, s, v; int R, G, B; double r, g, b; h = A.val[0]; s = A.val[1] / 100.0; v = A.val[2] / 100.0; if ( dcmp(s) == 0 ) { r = g = b = v; } else { int hi = (int)floor(h/60); double f = h / 60 - hi; double p = v * ( 1 - s ); double q = v * ( 1 - f*s ); double t = v * ( 1 - (1-f)*s ); switch( hi ) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } } R = Round( r * 255.0 ); G = Round( g * 255.0 ); B = Round( b * 255.0 ); //printf( "%s ", tar ); //printf( "%d %d %d ", R, G, B ); A.ang[0] = r; A.ang[1] = g; A.ang[2] = b; A.val[0] = R; A.val[1] = G; A.val[2] = B; for ( int i = 0; i < 3; ++i ) ans.val[i] = A.val[i]; return; } void HSVtoHSL() { HSVtoRGB(); A.second = true; RGBtoHSL(); return; } void HSLtoHSV() { HSLtoRGB(); A.second = true; RGBtoHSV(); return; } int main() { while ( scanf( "%s", tar ) == 1 ) { init(); if ( ori[0] == 'R' ) { if ( tar[2] == 'L' ) RGBtoHSL(); else if ( tar[0] == 'R' ) { for ( int i = 0; i < 3; ++i ) ans.val[i] = A.val[i]; } else RGBtoHSV(); } else if ( ori[2] == 'L' ) { if ( tar[0] == 'R' ) HSLtoRGB(); else if ( tar[2] == 'L' ) { for ( int i = 0; i < 3; ++i ) ans.val[i] = A.val[i]; } else HSLtoHSV(); } else { if ( tar[0] == 'R' ) HSVtoRGB(); else if ( tar[2] == 'V' ) { for ( int i = 0; i < 3; ++i ) ans.val[i] = A.val[i]; } else HSVtoHSL(); } printf( "%s ", tar ); if ( tar[0] == 'R' ) { printf( "%d %d %d ", ans.val[0], ans.val[1], ans.val[2] ); } else printf( "%d %d%% %d%% ", ans.val[0], ans.val[1], ans.val[2] ); } return 0; }