int RgbToHsi(struct RgbTriadStruct *RgbTriadStructPtr,
struct HsiTriadStruct *HsiTriadStructPtr)
{
double R, G, B, Sum, Quotient;
double Radians, Angle, MinValue, MaxValue, TempDouble1, TempDouble2;
R = ((double) RgbTriadStructPtr->Red) / 255.0;
G = ((double) RgbTriadStructPtr->Green) / 255.0;
B = ((double) RgbTriadStructPtr->Blue) / 255.0;
Sum = R + G + B;
HsiTriadStructPtr->Intensity = Sum / 3.0;
MinValue = (R < G) ? R : G;
MinValue = (B < MinValue) ? B : MinValue;
MaxValue = (R > G) ? R : G;
MaxValue = (B > MaxValue) ? B : MaxValue;
if (HsiTriadStructPtr->Intensity < 0.00001)
HsiTriadStructPtr->Saturation = ZERO_SATURATION;
else
HsiTriadStructPtr->Saturation = 1.0 - (3.0 * MinValue) / Sum;
if (MinValue == MaxValue)
{
HsiTriadStructPtr->Hue = UNDEFINED_HUE;
HsiTriadStructPtr->Saturation = ZERO_SATURATION;
return 0;
}
TempDouble1 = (((R - G) + (R - B)) / 2.0);
TempDouble2 = (R - G)*(R - G) + (R - B)*(G - B);
Quotient = (TempDouble1 / sqrt(TempDouble2));
if (Quotient > 0.99999999999999999)
Radians = 0.0;
else if (Quotient < -0.99999999999999999)
Radians = 3.1415926535;
else
Radians = acos(TempDouble1 / sqrt(TempDouble2));
Angle = Radians * DEGREES_PER_RADIAN;
if (B > G)
HsiTriadStructPtr->Hue = 360.0 - Angle;
else
HsiTriadStructPtr->Hue = Angle;
return 0;
}
int HsiToRgb(struct HsiTriadStruct *HsiTriadStructPtr,
struct RgbTriadStruct *RgbTriadStructPtr)
{
double r, g, b, Hue, Fraction, MaxDouble;
if (HsiTriadStructPtr->Saturation == ZERO_SATURATION)
{
if (HsiTriadStructPtr->Hue == UNDEFINED_HUE)
{
RgbTriadStructPtr->Red =
RgbTriadStructPtr->Green =
RgbTriadStructPtr->Blue =
HsiTriadStructPtr->Intensity * 255.0 + 0.5;
} else
{
printf("/n/nHsiToRgb: Illegal HSI hue value (saturation == 0)");
printf("/nHue == %5.3f, Saturation = %5.3f, Intensity == %5.3f",
HsiTriadStructPtr->Hue,
HsiTriadStructPtr->Saturation,
HsiTriadStructPtr->Intensity);
}
return 0;
}
if (HsiTriadStructPtr->Hue > 0.0 &&
HsiTriadStructPtr->Hue <= 120.0 )
{
b = (1.0 - HsiTriadStructPtr->Saturation) / 3.0;
Hue = HsiTriadStructPtr->Hue;
Fraction = (HsiTriadStructPtr->Saturation *
cos(Hue / DEGREES_PER_RADIAN))
/
cos((60.0 - Hue) / DEGREES_PER_RADIAN);
r = (1.0 + Fraction) / 3.0;
g = 1.0 - (r + b);
} else if (HsiTriadStructPtr->Hue > 120.0 &&
HsiTriadStructPtr->Hue <= 240.0 )
{
Hue = HsiTriadStructPtr->Hue - 120.0;
r = (1.0 - HsiTriadStructPtr->Saturation) / 3.0;
Fraction = (HsiTriadStructPtr->Saturation *
cos(Hue / DEGREES_PER_RADIAN))
/
cos((60.0 - Hue) / DEGREES_PER_RADIAN);
g = (1.0 + Fraction) / 3.0;
b = 1.0 - (r + g);
} else
{
Hue=
HsiTriadStructPtr->Hue - 240.0;
g = (1.0 - HsiTriadStructPtr->Saturation) / 3.0;
Fraction = (HsiTriadStructPtr->Saturation *
cos(Hue / DEGREES_PER_RADIAN))
/
cos((60.0 - Hue) / DEGREES_PER_RADIAN);
b = (1.0 + Fraction) / 3.0;
r = 1.0 - (g + b);
}
MaxDouble = ((r > g) ? r : g);
MaxDouble = ((MaxDouble > b) ? MaxDouble : b);
if (3.0 * HsiTriadStructPtr->Intensity * MaxDouble > 1.0)
HsiTriadStructPtr->Intensity = (1.0 / (3.0 * MaxDouble));
r *= 255.0;
g *= 255.0;
b *= 255.0;
RgbTriadStructPtr->Red =
(USGC) ((3.0 * HsiTriadStructPtr->Intensity * r) + 0.5);
RgbTriadStructPtr->Green =
(USGC) ((3.0 * HsiTriadStructPtr->Intensity * g) + 0.5);
RgbTriadStructPtr->Blue =
(USGC) ((3.0 * HsiTriadStructPtr->Intensity * b) + 0.5);
return 0;
}