2013 ACM/ICPC Asia Regional Changsha Online Contest C

莫名其妙的WA,莫名其妙的A……

不过正好练练代码风格。

So far, there are many color models in different area. For screen display, the most popular model is RGB color model. A color in the RGB color model is described indicating how much of each of the red, green, and blue is included. So one can easily determined a color by an RGB triplet (r, g, b). But there are other representation of the points in RGB color model,HSL and HSV are the two most popular representations among them and widely used in color pickers and in image editing software. They also use a triple (h,s,l) or (h,s,v) to determine a color but each component are with different meanings. each channel in HSL stands for hue, saturation, and lightness and in HSV stands for hue, saturation, and value. Note that while "hue" in HSL and HSV refers to the same attribute, their definitions of "saturation" differ dramatically.

For RGB triplet, we use digital 8-bit per channel notation, so the r,g,b can vary from 0 to 255. If all the components are at zero the result is black; if all are at maximum, the result is the brightest representable white.

For HSV and HSL, the hue channel is in unit of degrees, its value vary from 0 to 360(exclusive), and the saturation, lightness and value channel use percentage notation and their value vary from 0% to 100%.

For more detail about the RGB model and these representations, you can refer to HERE .

The problem here is ask you to implement a color representation conversion procedure to convert the representation between RGB,HSL and HSV following the methods below. Or you can find more detail of the converting method in HERE .

Converting HSV to RGB

Given a color with hue H ∈ [0°, 360°), saturation SHSV ∈ [0, 1], and value V ∈ [0, 1], we first find chroma:

C = V \times S_{HSV}\,\!

Then we can find a point (R1G1B1) along the bottom three faces of the RGB cube, with the same hue and chroma as our color (using the intermediate value X for the second largest component of this color):

\begin{align}  H^\prime &= \frac{H}{60^\circ} \\  X        &= C (1 - |H^\prime \;\bmod 2 - 1|)\end{align}
  (R_1, G_1, B_1) =    \begin{cases}      (0, 0, 0) &\mbox{if } H \mbox{ is undefined} \\      (C, X, 0) &\mbox{if } 0 \leq H^\prime < 1 \\      (X, C, 0) &\mbox{if } 1 \leq H^\prime < 2 \\      (0, C, X) &\mbox{if } 2 \leq H^\prime < 3 \\      (0, X, C) &\mbox{if } 3 \leq H^\prime < 4 \\      (X, 0, C) &\mbox{if } 4 \leq H^\prime < 5 \\      (C, 0, X) &\mbox{if } 5 \leq H^\prime < 6    \end{cases}
\begin{align}  &m = V - C \\  &(R, G, B) = (R_1 + m, G_1 + m, B_1 + m)\end{align}

Finally, we can find RG, and B by adding the same amount to each component, to match value:

\begin{align}  &m = V - C \\  &(R, G, B) = (R_1 + m, G_1 + m, B_1 + m)\end{align}

Converting HSL to RGB

Given an HSL color with hue H ∈ [0°, 360°), saturation SHSL ∈ [0, 1], and lightness L ∈ [0, 1], we can use the same strategy. First, we find chroma:

C = \begin{align}  (1 - \left\vert 2 L - 1 \right\vert) \times S_{HSL} \end{align}

Then we can, again, find a point (R1G1B1) along the bottom three faces of the RGB cube, with the same hue and chroma as our color (using the intermediate value X for the second largest component of this color):

\begin{align}  H^\prime &= \frac{H}{60^\circ} \\  X        &= C (1 - |H^\prime \;\bmod 2 - 1|)\end{align}
  (R_1, G_1, B_1) =    \begin{cases}      (0, 0, 0) &\mbox{if } H \mbox{ is undefined} \\      (C, X, 0) &\mbox{if } 0 \leq H^\prime < 1 \\      (X, C, 0) &\mbox{if } 1 \leq H^\prime < 2 \\      (0, C, X) &\mbox{if } 2 \leq H^\prime < 3 \\      (0, X, C) &\mbox{if } 3 \leq H^\prime < 4 \\      (X, 0, C) &\mbox{if } 4 \leq H^\prime < 5 \\      (C, 0, X) &\mbox{if } 5 \leq H^\prime < 6    \end{cases}

Finally, we can find RG, and B by adding the same amount to each component, to match lightness:

\begin{align}  &m = L - \textstyle{\frac{1}{2}}C \\  &(R, G, B) = (R_1 + m, G_1 + m, B_1 + m)\end{align}

Convert RGB to HSL and HSV

First unify (rgb) into a number between 0 and 1. Let max equals to the maximum value in rg and b. Let min equals to the minimum value in rg and b. The HSL is with hue h ∈ [0°, 360°), saturation s ∈ [0, 1], and lightness l ∈ [0, 1]

h =\begin{cases}0^\circ & \mbox{if } max = min \\60^\circ \times \frac{g - b}{max - min} + 0^\circ,   & \mbox{if } max = r \mbox{ and } g \ge b \\60^\circ \times \frac{g - b}{max - min} + 360^\circ,   & \mbox{if } max = r \mbox{ and } g < b \\60^\circ \times \frac{b - r}{max - min} + 120^\circ, & \mbox{if } max = g \\60^\circ \times \frac{r - g}{max - min} + 240^\circ, & \mbox{if } max = b\end{cases}
l = \begin{matrix} \frac{1}{2} \end{matrix} (max + min)
s = \begin{cases}0 & \mbox{if } l = 0 \mbox{ or } max = min \\\frac{max-min}{max+min} = \frac{max-min}{2l}, & \mbox{if } 0  \frac{1}{2}\end{cases}


When max = minh is defined as 0.

HSL and HSV have the same definition of hue. The s and v value in HSV is defined as follows:


s =\begin{cases}0, & \mbox{if } max = 0 \\\frac{max - min}{max} = 1 - \frac{min}{max}, & \mbox{otherwise}\end{cases}
v = max \,
#include <cstdio>
#include <algorithm>
using namespace std;
typedef void(*cfunc)(double f[], double t[]);
double getH(double ma, double mi, double r, double g, double b)
{
	if (ma == mi)
		return 0;
	else if (ma == r && g >= b)
		return  60 * (g - b) / (ma - mi);
	else if (ma == r && g < b)
		return 60 * (g - b) / (ma - mi) + 360;
	else if (ma == g)
		return 60 * (b - r) / (ma - mi) + 120;
	else
		return 60 * (r - g) / (ma - mi) + 240;
}
void RGBtoHSL(double f[], double t[])
{
	double r = f[0] / 255, g = f[1] / 255, b = f[2] / 255;
	double ma = max(r, max(g, b));
	double mi = min(r, min(g, b));
	t[0] = getH(ma, mi, r, g, b);
	if (ma + mi == 0 || ma == mi)
		t[1] = 0;
	else if (0 < ma + mi && ma + mi <= 1)
		t[1] = (ma - mi) / (ma + mi);
	else if (ma + mi > 1)
		t[1] = (ma - mi) / (2 - (ma + mi));
	t[2] = (ma + mi) * .5;
	for (size_t i = 1; i < 3; i++)
		t[i] *= 100;
}
void RGBtoHSV(double f[], double t[])
{
	double r = f[0] / 255, g = f[1] / 255, b = f[2] / 255;
	double ma = max(r, max(g, b));
	double mi = min(r, min(g, b));
	t[0] = getH(ma, mi, r, g, b);
	t[1] = ma == 0 ? 0 : 1 - mi / ma;
	t[2] = ma;
	for (size_t i = 1; i < 3; i++)
		t[i] *= 100;
}
void getBase(double c, double h, double v[])
{
	double h_ = h / 60;
	double x = c * (1 - abs(fmod(h_, 2) - 1));
	if (0 <= h_ && h_ < 1)
		v[0] = c, v[1] = x;
	else if (h_ < 2)
		v[0] = x, v[1] = c;
	else if (h_ < 3)
		v[1] = c, v[2] = x;
	else if (h_ < 4)
		v[1] = x, v[2] = c;
	else if (h_ < 5)
		v[0] = x, v[2] = c;
	else if (h_ < 6)
		v[0] = c, v[2] = x;
}
void HSLtoRGB(double f[], double t[])
{
	double h = f[0], s = f[1] / 100, l = f[2] / 100;
	double c = (1 - abs(2 * l - 1)) * s;
	double rgb[3] = { 0,0,0 };
	getBase(c, h, rgb);
	double m = l - c * .5;
	for (int i = 0; i < 3; i++)
		t[i] = rgb[i] + m;
	for (size_t i = 0; i < 3; i++)
		t[i] *= 255;
}
void HSVtoRGB(double f[], double t[])
{
	double h = f[0], s = f[1] / 100, v = f[2] / 100;
	double c = v * s;
	double rgb[3] = { 0,0,0 };
	getBase(c, h, rgb);
	double m = v - c;
	for (int i = 0; i < 3; i++)
		t[i] = rgb[i] + m;
	for (size_t i = 0; i < 3; i++)
		t[i] *= 255;
}
void HSLtoHSV(double f[], double t[])
{
	double tmp[3];
	HSLtoRGB(f, tmp);
	RGBtoHSV(tmp, t);
}
void HSVtoHSL(double f[], double t[])
{
	double tmp[3];
	HSVtoRGB(f, tmp);
	RGBtoHSL(tmp, t);
}
cfunc crt['V' + 1]['V' + 1];
int main()
{
	crt['B']['L'] = RGBtoHSL;
	crt['B']['V'] = RGBtoHSV;
	crt['L']['B'] = HSLtoRGB;
	crt['L']['V'] = HSLtoHSV;
	crt['V']['B'] = HSVtoRGB;
	crt['V']['L'] = HSVtoHSL;
	crt['B']['B'] = crt['L']['L'] = crt['V']['V'] = [](double f[], double t[]) {
		for (int i = 0; i < 3; i++)
			t[i] = f[i];
	};
	char t[16], f[16];
	while (scanf("%s%s", t, f) != EOF)
	{
		double v[3], a[3];
		switch (f[2])
		{
		case 'B': scanf("%lf%lf%lf", v, v + 1, v + 2); break;
		case 'L':
		case 'V': scanf("%lf%lf%%%lf%%", v, v + 1, v + 2); break;
		}
		crt[f[2]][t[2]](v, a);
		switch (t[2])
		{
		case 'B': printf("RGB %.0f %.0f %.0f\n", a[0], a[1], a[2]); break;
		case 'L': printf("HSL %.0f %.0f%% %.0f%%\n", a[0], a[1], a[2]); break;
		case 'V': printf("HSV %.0f %.0f%% %.0f%%\n", a[0], a[1], a[2]); break;
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值