各個顏色空間的轉換
阿新 • • 發佈:2019-01-22
// 沒有驗證過
// 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