// 没有验证过
// RGB<->YUV
// RGB<->XYZ
// RGB<->LAB
// RGB<->HSV
// RGB<->CMY
// XYZ<->LAB
// YUV ->XYZ
// LAB ->HSV
// XYZ ->HSV
// RGB ->CMYK
// CMYK->CMY
// http://www.cnblogs.com/phinecos/archive/2009/05/03/1448121.html
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
// http://www.programmershare.com/1288015/
// http://blog.sina.com.cn/s/blog_6806030c0101ei9z.html
#include <math.h>
template <class T>
const T& HYMin(const T& refT1, const T& refT2)
{
return (refT1 < refT2) ? refT1 : refT2;
}
template <class T>
const T& HYMax(const T& refT1, const T& refT2)
{
return (refT1 > refT2) ? refT1 : refT2;
}
// RGB转换为YUV
void RGB2YUV(double dR, double dG, double dB, double &dY, double &dU, double &dV)
{
dY = 0.257 * dR + 0.504 * dG + 0.098 * dB + 16; // y
dU = -0.148 * dR - 0.291 * dG + 0.439 * dB + 128; // u
dV = 0.439 * dR - 0.368 * dG - 0.071 * dB + 128; // v
}
// YUV转换为RGB
void YUV2RGB(double dY, double dU, double dV, double &dR, double &dG, double &dB)
{
dR = 1.0 * dY + 8 + 1.402 * (dV - 128);
dG = 1.0 * dY - 0.34413 * (dU - 128) - 0.71414 * (dV - 128);
dB = 1.0 * dY + 1.772 * (dU - 128) + 0;
}
// RGB转换为XYZ
void RGB2XYZ(double dR, double dG, double dB, double &dX, double &dY, double &dZ)
{
double dTempR = (dR / 255.0);
double dTempG = (dG / 255.0);
double dTempB = (dB / 255.0);
if(0.04045 < dTempR)
{
dTempR = pow((dTempR + 0.055) / 1.055, 2.4);
}
else
{
dTempR /= 12.92;
}
if(0.04045 < dTempG)
{
dTempG = pow((dTempG + 0.055) / 1.055, 2.4);
}
else
{
dTempG /= 12.92;
}
if(0.04045 < dTempB)
{
dTempB = pow((dTempB + 0.055) / 1.055, 2.4);
}
else
{
dTempB /= 12.92;
}
dTempR *= 100.0;
dTempG *= 100.0;
dTempB *= 100.0;
//Observer. = 2°, Illuminant = D65
dX = 0.4124564 * dTempR + 0.3575761 * dTempG + 0.1804375 * dTempB;
dY = 0.2126729 * dTempR + 0.7151522 * dTempG + 0.0721750 * dTempB;
dZ = 0.0193339 * dTempR + 0.1191920 * dTempG + 0.9503041 * dTempB;
}
// XYZ转换为LAB
void XYZ2LAB(double dX, double dY, double dZ, double &dL, double &dA ,double &dB)
{
double dTempX = dX / 95.047;
double dTempY = dY / 100.000;
double dTempZ = dZ / 108.883;
if(0.008856 < dTempX)
{
dTempX = pow((float)dTempX, 1.0f / 3.0f);
}
else
{
dTempX = ( 7.787 * dTempX ) + (16.0 / 116.0);
}
if(0.008856 < dTempY)
{
dTempY = pow((float)dTempY, 1.0f / 3.0f);
}
else
{
dTempY = (7.787 * dTempY) + (16.0 / 116.0);
}
if(0.008856 < dTempZ)
{
dTempZ = pow((float)dTempZ, 1.0f / 3.0f);
}
else
{
dTempZ = (7.787 * dTempZ) + (16.0 / 116.0);
}
dL = (116 * dTempY) - 16;
dA = 500 * (dTempX - dTempY);
dB = 200 * (dTempY - dTempZ);
}
// RGB转换为LAB
void RGB2LAB(double dR, double dG, double dB, double &dLAB_L, double &dLAB_A, double &dLAB_B)
{
double dX, dY, dZ;
RGB2XYZ(dR, dG, dB, dX, dY, dZ);
XYZ2LAB(dX, dY, dZ, dLAB_L, dLAB_A, dLAB_B);
}
// LAB转换为XYZ
void LAB2XYZ(double dLAB_L, double dLAB_A, double dLAB_B, double &dX, double &dY, double &dZ)
{
double dTempY = (dLAB_L + 16) / 116;
double dTempX = dLAB_A / 500 + dTempY;
double dTempZ = dTempY - dLAB_B / 200;
if(pow((double)dTempY, 3) > 0.008856)
{
dTempY = pow((double)dTempY, 3);
}
else
{
dTempY = (dTempY - 16 / 116) / 7.787;
}
if(pow((double)dTempX, 3) > 0.008856)
{
dTempX = pow((double)dTempX, 3);
}
else
{
dTempX = (dTempX - 16 / 116) / 7.787;
}
if(pow((double)dTempZ, 3) > 0.008856)
{
dTempZ = pow((double)dTempZ, 3);
}
else
{
dTempZ = (dTempZ - 16.0 / 116.0) / 7.787;
}
dX = 95.047 * dTempX;
dY = 100.000 * dTempY;
dZ = 108.883 * dTempZ;
}
// XYZ转换为RGB
void XYZ2RGB(double dX, double dY, double dZ, double &dR, double &dG, double &dB)
{
double dTempX = dX / 100.0f; // X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
double dTempY = dY / 100.0f; // Y from 0 to 100.000
double dTempZ = dZ / 100.0f; // Z from 0 to 108.883
double dTempR = dTempX * 3.2404542 + dTempY * -1.5371385 + dTempZ * -0.4985314;
double dTempG = dTempX * -0.9692660 + dTempY * 1.8760108 + dTempZ * 0.0415560;
double dTempB = dTempX * 0.0556434 + dTempY * -0.2040259 + dTempZ * 1.0572252;
if(0.0031308 < dTempR)
{
dTempR = 1.055 * (pow(dTempR, (1 / 2.4))) - 0.055;
}
else
{
dTempR *= 12.92;
}
if(0.0031308 < dTempG)
{
dTempG = 1.055 * (pow(dTempG, (1 / 2.4))) - 0.055;
}
else
{
dTempG *= 12.92;
}
if(0.0031308 < dTempB)
{
dTempB = 1.055 * (pow(dTempB, (1 / 2.4))) - 0.055;
}
else
{
dTempB *= 12.92;
}
dR = 255.0f * dTempR;
dG = 255.0f * dTempG;
dB = 255.0f * dTempB;
}
// LAB转换为RGB
void LAB2RGB(double dLAB_L, double dLAB_A, double dLAB_B, double &dR, double &dG, double &dB)
{
double dX, dY, dZ;
LAB2XYZ(dLAB_L, dLAB_A, dLAB_B, dX, dY, dZ);
XYZ2RGB(dX, dY, dZ, dR, dG, dB);
}
// RGB转换为HSV
void RGB2HSV(double dR, double dG, double dB, double &dH, double &dS, double& dV)
{
double dTempR = (dR / 255); // RGB from 0 to 255
double dTempG = (dG / 255);
double dTempB = (dB / 255);
double dMin, dMax, dDelMax;
dMin = HYMin(HYMin(dTempR, dTempG), dTempB);
dMax = HYMax(HYMax(dTempR, dTempG), dTempB);
dDelMax = dMax - dMin; // Delta RGB value
dV = dMax;
if(0 == dMax) // This is a gray, no chroma
{
dH = 0.0; // HSV results from 0 to 1
dS = 0.0;
}
else // Chromatic data
{
dS = dDelMax / dMax;
double dDelR = (((dMax - dTempR) / 6) + (dDelMax / 2)) / dDelMax;
double dDelG = (((dMax - dTempG) / 6) + (dDelMax / 2)) / dDelMax;
double dDelB = (((dMax - dTempB) / 6) + (dDelMax / 2)) / dDelMax;
if(dTempR == dMax)
{
dH = dDelB - dDelG;
}
else if(dTempG == dMax)
{
dH = (1.0 / 3.0) + dDelR - dDelB;
}
else if(dTempB == dMax)
{
dH = (2.0 / 3.0) + dDelG - dDelR;
}
if(0 > dH)
{
dH += 1.0;
}
if(1 < dH)
{
dH -= 1.0;
}
}
}
// HSV转换为RGB
void HSV2RGB(double dH, double dS, double dV, double &dR, double &dG, double &dB)
{
if(dS == 0) // HSV from 0 to 1
{
dR = 255.0f * dV;
dG = 255.0f * dV;
dB = 255.0f * dV;
}
else
{
// 86912219
double dTempH, dTempI, dTemp1, dTemp2, dTemp3;
dTempH = 6.0f * dH;
if(6 == dTempH)
{
dTempH = 0.0; // H must be < 1
}
dTempI = int(dTempH); //Or var_i = floor( var_h )
dTemp1 = dV * (1 - dS);
dTemp2 = dV * (1 - dS * (dTempH - dTempI));
dTemp3 = dV * (1 - dS * (1 - (dTempH - dTempI)));
double dTempR, dTempG, dTempB;
if(0 == dTempI)
{
dTempR = dV;
dTempG = dTemp3 ;
dTempB = dTemp1;
}
else if(1 == dTempI)
{
dTempR = dTemp2 ;
dTempG = dV;
dTempB = dTemp1;
}
else if(2 == dTempI)
{
dTempR = dTemp1;
dTempG = dV;
dTempB = dTemp3;
}
else if (3 == dTempI)
{
dTempR = dTemp1 ;
dTempG = dTemp2 ;
dTempB = dV;
}
else if(4 == dTempI)
{
dTempR = dTemp3;
dTempG = dTemp1;
dTempB = dV;
}
else
{
dTempR = dV;
dTempG = dTemp1;
dTempB = dTemp2;
}
dR = 255.0f * dTempR; // RGB results from 0 to 255
dG = 255.0f * dTempR;
dB = 255.0f * dTempR;
}
}
// YUV转换为XYZ
void YUV2XYZ(double dL, double dU, double dV, double &dX, double &dY, double &dZ)
{
double dTempY, dRefX, dRefY, dRefZ, dRefU, dRefV, dTempU, dTempV;
dTempY = (dL + 16) / 116;
if(pow(dTempY, 3) > 0.008856)
{
dTempY = pow(dTempY, 3);
}
else
{
dTempY = (dTempY - 16.0 / 116.0) / 7.787;
}
dRefX = 95.047; //Observer= 2°, Illuminant= D65
dRefY = 100.000;
dRefZ = 108.883;
dRefU = (4 * dRefX ) / (dRefX + (15 * dRefY) + (3 * dRefZ));
dRefV = (9 * dRefY ) / (dRefX + (15 * dRefY) + (3 * dRefZ));
dTempU = dU / (13 * dL) + dRefU;
dTempV = dV / (13 * dL) + dRefV;
dY = dTempY * 100;
dX = -(9 * dY * dTempU) / ((dTempU - 4) * dTempV - dTempU * dTempV);
dZ = (9 * dY - (15 * dTempV * dY) - (dTempV * dX)) / (3 * dTempV);
}
// XYZ转换为HSV
void XYZ2HSV(double dX, double dY, double dZ,double &dH, double &dS, double &dV)
{
double dR, dG, dB;
XYZ2RGB(dX, dY, dZ, dR, dG, dB);
RGB2HSV(dR, dG, dB, dH, dS, dV);
}
// LAB转换为HSV
void LAB2HSV(double dL, double dA, double dB, double &dH, double &dS, double &dV)
{
double dX, dY, dZ;
LAB2XYZ(dL, dA, dB, dX, dY, dZ);
XYZ2HSV(dX, dY, dZ, dH, dS, dV);
}
// RGB转换为CMY
void RGB2CMY(double dR, double dG, double dB, double &dC, double &dM, double dY)
{
dC = 1.0 - (dR / 255.0f);
dM = 1.0 - (dG / 255.0f);
dY = 1.0 - (dB / 255.0f);
}
//CMY转换为RGB
void CMY2RGB(double dC, double dM, double dY, double &dR, double &dG, double &dB)
{
dR = (1.0f - dC) * 255.0f;
dG = (1.0f - dM) * 255.0f;
dB = (1.0f - dY) * 255.0f;
}
//RGB转换为CMYK
void RGB2CMYK(double dR, double dG, double dB, double &dC, double &dM, double dY, double &dK)
{
// RGB2CMY
RGB2CMY(dR, dG, dB, dC, dM, dY);
//CMYK and CMY values from 0 to 1
double dTempK = 1.0;
if(dC < dTempK)
{
dTempK = dC;
}
if(dM < dTempK)
{
dTempK = dM;
}
if(dY < dTempK)
{
dTempK = dY;
}
if(1 == dTempK)
{ //Black
dC = 0;
dM = 0;
dY = 0;
}
else
{
dC = (dC - dTempK) / (1 - dTempK);
dM = (dM - dTempK) / (1 - dTempK);
dY = (dY - dTempK) / (1 - dTempK);
}
dK = dTempK;
}
// CMYK转换为CMY
void CMYK2CMY(double dC1, double dM1, double dY1, double dK1, double &dC2, double &dM2, double dY2)
{
dC2 = (dC1 * (1 - dK1) + dK1);
dM2 = (dM1 * (1 - dK1) + dK1);
dY2 = (dY1 * (1 - dK1) + dK1);
}
// RGB<-->HSL互转描述, 我已验证, 这个就是Windows颜色选择对话框的颜色选择转换算法
http://www.cnblogs.com/daiguagua/p/3311756.html