diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2019-08-08 15:51:50 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2019-08-08 15:51:50 +0300 |
| commit | 93573c53b155e2c07b6f41a53f93c38c774cbade (patch) | |
| tree | cfaee9b106a84b10c626f2a4cdf967c93810853c /Software/Visual_Studio/Native | |
| parent | f0cf4833650e087b7c2fd776820d4e917af020ce (diff) | |
| parent | c7afd7e05b3230a4c652d74effd813b858da8ee3 (diff) | |
| download | Tango-93573c53b155e2c07b6f41a53f93c38c774cbade.tar.gz Tango-93573c53b155e2c07b6f41a53f93c38c774cbade.zip | |
Merge branch 'master' of https://twinetfs.visualstudio.com/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/Native')
16 files changed, 1362 insertions, 711 deletions
diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.cpp index b64ece88a..d8abe700f 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.cpp @@ -9,9 +9,6 @@ #include "OutputLiquid.pb-c.h" #include "InputLiquid.pb-c.h" #include "LiquidType.pb-c.h" -#include "GradientConversionInput.pb-c.h" -#include "GradientConversionOutput.pb-c.h" -#include "InputRGB.pb-c.h" #include <iostream> #include <stdio.h> #include "Dense" @@ -25,8 +22,8 @@ #include <sstream> //#include <vld.h> -/*#define _CRTDBG_MAP_ALLOC -#include <stdlib.h> +/*#define _CRTDBG_MAP_ALLOC +#include <stdlib.h> #include <crtdbg.h> #include <cstdlib> @@ -53,10 +50,13 @@ #define maxPerRegion 100.0 -Tango::ColorLib::ColorConverter::ColorConverter() :m_A2BTransform(NULL), m_B2ATransform(NULL), -m_GBD(NULL), m_CalibCurves(NULL), m_Conv02(NULL), +Tango::ColorLib::ColorConverter::ColorConverter() : m_A2BTransform(NULL), m_B2ATransform(NULL), +m_GBD(NULL), m_CalibCurves(NULL), m_Conv02(NULL), m_GamutRegionMaxLim(NULL), m_maxNlPerCM(NULL), m_nA2BnSepIn(0), m_nA2BnSepOut(0), m_nB2AnSepIn(0), m_nB2AnSepOut(0), -m_nInks(0), m_nVolumes(0), m_AdaptWP(false), m_LinInterp(NULL), m_InvLinInterp(NULL) +m_nInks(0), m_nVolumes(0), m_AdaptWP(false), m_nGamutRegions(0), m_LinCurves(NULL), + m_nProcessRanges(0), m_ProcessRangesMaxP(NULL) + //m_ProcessRangesMinInkUptake(NULL),m_ProcessRangesMinP(NULL), + //m_ProcessRangesMaxInkUptake(NULL) { m_whitepointLab.Set(-1, -1, -1); m_whitepointXYZ_Strip.Set(-1, -1, -1); @@ -91,140 +91,204 @@ Tango::ColorLib::ColorConverter::~ColorConverter() delete[] m_CalibCurves; m_CalibCurves = NULL; } - if (m_LinInterp != NULL) + if (m_GamutRegionMaxLim != NULL) { - delete[] m_LinInterp; - m_LinInterp = NULL; + delete[] m_GamutRegionMaxLim; + m_GamutRegionMaxLim = NULL; } - if (m_InvLinInterp != NULL) + if (m_LinCurves != NULL) { - delete[] m_InvLinInterp; - m_InvLinInterp = NULL; + delete m_LinCurves; + m_LinCurves = NULL; } + if (m_ProcessRangesMaxP != NULL) + { + delete[] m_ProcessRangesMaxP; + m_ProcessRangesMaxP = NULL; + } +/* if (m_ProcessRangesMinP != NULL) + { + delete[] m_ProcessRangesMinP; + m_ProcessRangesMinP = NULL; + }*/ + /*if (m_ProcessRangesMaxInkUptake != NULL) + { + delete[] m_ProcessRangesMaxInkUptake; + m_ProcessRangesMaxInkUptake = NULL; + } + if (m_ProcessRangesMinInkUptake != NULL) + { + delete[] m_ProcessRangesMinInkUptake; + m_ProcessRangesMinInkUptake = NULL; + }*/ } -void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(VectorXd Lab, VectorXd RGB, VectorXd Volume, int InGamutRegion, - MatrixXd &ORGBHive, MatrixXd &OVolumeHive, int nHive, int *&OGamutRegion, int *indDataMax) +void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(ConversionInput *conversionInput, VectorXd Lab, + VectorXd RGB, VectorXd Volume, int InGamutRegion, MatrixXd &ORGBHive, MatrixXd &OLabHive, + MatrixXd &OVolumeHive, int nHive, int *&OGamutRegion, int *indDataMax) { size_t retVal = 0; - - VectorXd LabV(3); - LabV = Lab; - // LabV << Lab[0], Lab[1], Lab[2]; - VectorXd Jab(3); + ColorConvert ColConv(D65, D65); SURROUND sur = m_Conv02->getSurround(); CAM02CS CS = m_Conv02->getCAM02CS(); - Jab = m_Conv02->LabToJab(LabV, sur); + VectorXd LabV(3); + LabV = Lab; - //JCH coordinates + //LCH coordinates double hue = 0.0; - double chroma = sqrt(Jab(1)*Jab(1) + Jab(2)*Jab(2)); - if ((abs(Jab(1)) < eps) & (abs(Jab(2)) < eps)) + double chroma = sqrt(Lab(1)*Lab(1) + Lab(2)*Lab(2)); + + if ((abs(Lab(1)) < eps) & (abs(Lab(2)) < eps)) hue = 0.0; else - hue = atan2(Jab(2), Jab(1)); - - MatrixXd Jab1(nHive, 6); + hue = atan2(Lab(2), Lab(1)); + double d1 = dC; + double de = 0; + MatrixXd Lab1(nHive, 3); for (int i = 0; i < 6; ++i) { - Jab1(i, 0) = Jab(0); - Jab1(i, 1) = Jab(1) + dC * cos(hue + i * dH6); - Jab1(i, 2) = Jab(2) + dC * sin(hue + i * dH6); + LabV(0) = Lab(0); + LabV(1) = Lab(1) + dC*cos( i*dH6); + LabV(2) = Lab(2) + dC*sin(i*dH6); + //Iterate to get the correct dECMC + d1 =dC; + de = 0.0; + while (abs(de - dC) > 0.01) + { + ColConv.dEcmc(LabV, Lab, de); + d1 = dC*d1 / de; + LabV(0) = Lab(0); + LabV(1) = Lab(1) + d1 * cos(i*dH6); + LabV(2) = Lab(2) + d1 * sin(i*dH6); + } + //fix + Lab1(i, 0) = LabV(0); + Lab1(i, 1) = Lab(1) + d1 * cos(i*dH6); + Lab1(i, 2) = Lab(2) + d1 * sin(i*dH6); } + int j1 = 0, j2 = 0; - double dC2 = dC * 2.0; + double dC2 = dC*2.0; for (int i = 0; i < 12; ++i) { j1 = i + 6; - Jab1(j1, 0) = Jab(0); - Jab1(j1, 1) = Jab(1) + dC2 * cos(hue + i * dH12); - Jab1(j1, 2) = Jab(2) + dC2 * sin(hue + i * dH12); - } - /* for (int i = 0; i < 2; ++i) + LabV(0) = Lab(0); + LabV(1) = Lab(1) + dC2 * cos(i*dH12); + LabV(2) = Lab(2) + dC2 * sin(i*dH12); + de = 0.0; + while (abs(de - dC2) > 0.01) { - j1 = i + 18; - Jab1(j1, 0) = Jab(0) + (i + 1)*dL; - Jab1(j1, 1) = Jab(1); - Jab1(j1, 2) = Jab(2); + ColConv.SymmetricaldECMC(LabV, Lab, de); + d1 = dC2 * d1 / de; + LabV(0) = Lab(0); + LabV(1) = Lab(1) + d1 * cos(i*dH12); + LabV(2) = Lab(2) + d1 * sin(i*dH12); } - for (int i = 0; i < 2; ++i) - { - j1 = i + 20; - Jab1(j1, 0) = Jab(0) - (i + 1)*dL; - Jab1(j1, 1) = Jab(1); - Jab1(j1, 2) = Jab(2); - }*/ - - //convert back to CIELab - MatrixXd Lab1(nHive, 3); - //MatrixXd RGBTmpVec(nHive + 2, 3); - //MatrixXd VolumeHive(nHive + 2, m_nVolumes); + //fix + Lab1(j1, 0) = LabV(0); + Lab1(j1, 1) = Lab(1) + d1 * cos(i*dH12); + Lab1(j1, 2) = Lab(2) + d1 * sin(i*dH12); + } + MatrixXd RGBTmpVec(nHive + 1, 3); MatrixXd VolumeHive(nHive + 1, m_nVolumes); + MatrixXd LabHive(nHive + 1, 3); VectorXd xyz(3); - VectorXd JabTmp(3); C_RGB_XYZ_Lab xyzVal, LabVal; double *tmpRGB = new double[3]; //double *tmpRGB = DBG_NEW double[3]; double *InkOut = new double[m_nInks]; //double *InkOut = DBG_NEW double[m_nInks]; - + int *GamutRegion = new int[nHive + 1]; //int *GamutRegion = DBG_NEW int[nHive + 1]; double *Lab1P = new double[3]; //double *Lab1P = DBG_NEW double[3]; VectorXd Vol(m_nVolumes); int j = 0; - double * LabInFinal1 = new double[3]; + double * LabInFinal1= new double[3]; //double * LabInFinal1 = DBG_NEW double[3]; - double * LabInFinal2; //= new double[3]; + double * LabInFinal2 = new double[3]; + double * LabOnGamut = new double[3]; + bool InGamut = true; for (int i = 0; i < nHive; ++i) { - //fill data - JabTmp << Jab1(i, 0), Jab1(i, 1), Jab1(i, 2); - xyz = m_Conv02->Jab_2_XYZ(JabTmp, CS); - xyzVal.Set(xyz / 100.0); - LabVal = m_Conv02->XYZToLab(xyzVal); - Lab1(i, 0) = LabVal.Get_x(); - Lab1(i, 1) = LabVal.Get_y(); - Lab1(i, 2) = LabVal.Get_z(); //Get Lab's inGamut for (j = 0; j < 3; ++j) Lab1P[j] = Lab1(i, j); - m_B2ATransform->evalLab2InkP(Lab1P, InkOut, GamutRegion[i]); //InkOut is in units of 16 bits - m_A2BTransform->evalInkP2Lab(InkOut, Lab1P, GamutRegion[i]); //Check if whitepoints match - //LabOut is under D65 illumination + if (m_AdaptWP) + { + //Convert to CT whitepoint + m_Conv02->ChangeWP(Lab1P, Lab1P, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); + LimitLab(LabInFinal1); + } + ColConv.ChangeWP(Lab1P, Lab1P, m_WP, m_whitepointXYZ_CT); //to Relative + + m_B2ATransform->evalLab2InkP(Lab1P, InkOut, GamutRegion[i]); //InkOut is in units of 16 bits + InGamut = IsInGamut(Lab1P, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + //m_A2BTransform->evalInkP2Lab(InkOut, Lab1P, GamutRegion[i]); //Convert to CT WP - m_Conv02->ChangeWP(Lab1P, LabInFinal1, m_whitepointXYZ_CT, m_WP); //dest, source - LabInFinal2 = LabInFinal1; + m_Conv02->ChangeWP(LabOnGamut, LabInFinal1, m_whitepointXYZ_CT, m_WP); //convert back to Absolute + LimitLab(LabInFinal1); //Absolute + + //Check if whitepoints match if (m_AdaptWP) { //Convert to Strip whitepoint - m_Conv02->ChangeWP(LabInFinal2, LabInFinal2, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); + m_Conv02->ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); + LimitLab(LabInFinal1); } m_Conv02->SetReferenceWhite(D65); - //Convert to RGB - //m_Conv02->LabtoRGB(LabInFinal2, tmpRGB); - m_Conv02->LabtoRGB(Lab1P, tmpRGB); + for (int j = 0; j < 3; ++j) + LabHive(i, j) = LabInFinal1[j]; + + //Convert to RGB, relative col is converted + m_Conv02->LabtoRGB(LabOnGamut, tmpRGB); + //m_Conv02->LabtoRGB(Lab1P, tmpRGB); for (int j = 0; j < 3; ++j) RGBTmpVec(i, j) = std::min(std::max(tmpRGB[j], 0.0), 255.0); + double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + for (int j = 0; j < m_nB2AnSepOut; ++j) + { + InkOut[j] *= NormFactor; + if (InkOut[j] <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[j].Eval(InkOut[j] * 655.35, InkOut[j]); + InkOut[j] /= 655.35; + } + } + VectorXd InkOutV = DoubleToVector(InkOut, m_nInks); + ConvertToNLInks(InkOutV, InkOutV); + double maxNLInk = -10; + for (int j = 0; j < m_nInks; ++j) + maxNLInk = std::max(InkOutV(j), maxNLInk); + + for (int j = 0; j < (int)(conversionInput->n_processranges - 1); ++j) + { + if (maxNLInk > m_ProcessRangesMaxP[j]) + GamutRegion[i]++; + } + NLInkPToVolume(InkOutV, Vol); //make sure the rounded sum does not exceed the limit in the gamut region for (int j = 0; j < m_nInks; ++j) VolumeHive(i, j) = Vol(j); } - //for (int i = 0; i < 2; ++i) for (int i = 0; i < 1; ++i) { for (j = 0; j < m_nInks; ++j) VolumeHive(nHive + i, j) = Volume(j); for (j = 0; j < 3; ++j) + { RGBTmpVec(nHive + i, j) = RGB(j); + LabHive(nHive + i, j) = Lab(j); + } GamutRegion[nHive + i] = InGamutRegion; } @@ -232,9 +296,21 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(VectorXd Lab, VectorX //Hive Vector follows the ordering 0-(0,0) 1-(0,1) 2-(0,2),...., //22-(4,2), 23-(4,3), 24-(4,4) not implemented yet //Some of the matrix elements are empty - ArrangeHiveData(RGBTmpVec, VolumeHive, GamutRegion, nHive, ORGBHive, OVolumeHive, OGamutRegion); + VectorXd xpos(nHive + 1); + xpos << 1, 1, 1, 2, 3, 2, 1, 0, 0, 0, 1, 2, 3, 3, 4, 3, 3, 2, /*, 5, 5, 5, 5, 5,*/ 2; + VectorXd ypos(nHive + 1); + ypos << 3, 2, 1, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0, 1, 2, 3, 4, 4,/* 0, 1, 3, 4, 2,*/ 2; + ArrangeHiveData(LabHive, RGBTmpVec, VolumeHive, GamutRegion, xpos, ypos, nHive, + OLabHive, ORGBHive, OVolumeHive, OGamutRegion); FindTriplet(Lab, Lab1, nHive, indDataMax); - + indDataMax[0] = (int)(xpos(indDataMax[0]) * 5 + ypos(indDataMax[0])); + indDataMax[1] = (int)(xpos(indDataMax[1]) * 5 + ypos(indDataMax[1])); + + if (LabOnGamut != NULL) + { + delete[]LabOnGamut; + LabOnGamut = NULL; + } if (InkOut != NULL) { delete[]InkOut; @@ -255,11 +331,11 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(VectorXd Lab, VectorX delete[] tmpRGB; tmpRGB = NULL; } - /*if (LabInFinal2 != NULL) + if (LabInFinal2 != NULL) { delete[]LabInFinal2; LabInFinal2 = NULL; - }*/ + } if (LabInFinal1 != NULL) { delete[]LabInFinal1; @@ -271,7 +347,7 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(VectorXd Lab, VectorX void Tango::ColorLib::ColorConverter::FindTriplet(VectorXd Lab, MatrixXd Lab1, int nHive, int*indDataMax) { - int vecSize = nHive * (nHive - 1) / 2; + int vecSize = nHive*(nHive - 1) / 2; double *dECMC = new double[vecSize]; //double *dECMC = DBG_NEW double[vecSize]; int i, j; @@ -280,14 +356,18 @@ void Tango::ColorLib::ColorConverter::FindTriplet(VectorXd Lab, MatrixXd Lab1, int **indexpairs = new int*[vecSize]; //int **indexpairs = DBG_NEW int*[vecSize]; for (i = 0; i < vecSize; ++i) + { indexpairs[i] = new int[2]; - //indexpairs[i] = DBG_NEW int[2]; + for (int j = 0; j < 2; ++j) + indexpairs[i][j] = 0; + } + //indexpairs[i] = DBG_NEW int[2]; int ind = -1; ColorConvert ColConv(D65, D65); VectorXd Labi(3); VectorXd Labj(3); - + for (i = 0; i < nHive; ++i) { Labi << Lab1(i, 0), Lab1(i, 1), Lab1(i, 2); @@ -328,26 +408,30 @@ void Tango::ColorLib::ColorConverter::FindTriplet(VectorXd Lab, MatrixXd Lab1, return; } -void Tango::ColorLib::ColorConverter::ArrangeHiveData(MatrixXd RGBTmpVec, MatrixXd VolumeHive, int *GamutRegion, int nHive, MatrixXd &RGBHive, MatrixXd &OVolumeHive, int *&OGamutRegion) +void Tango::ColorLib::ColorConverter::ArrangeHiveData(MatrixXd LabHive, MatrixXd RGBTmpVec, MatrixXd VolumeHive, int *GamutRegion, + VectorXd xpos, VectorXd ypos,int nHive, MatrixXd &OLabHive, MatrixXd &RGBHive, MatrixXd &OVolumeHive, int *&OGamutRegion) { //Hive Vector follows the ordering 0-(0,0) 1-(0,1) 2-(0,2),...., 22-(4,2), 23-(4,3), 24-(4,4) //Some of the matrix elements are empty //Ordering is by hexagon position in a 5x5 grid. - //VectorXd xpos(nHive + 2); - VectorXd xpos(nHive + 1); - xpos << 1, 1, 1, 2, 3, 2, 1, 0, 0, 0, 1, 2, 3, 3, 4, 3, 3, 2, /*, 5, 5, 5, 5, 5,*/ 2; - //VectorXd ypos(nHive + 2); - VectorXd ypos(nHive + 1); - ypos << 3, 2, 1, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0, 1, 2, 3, 4, 4,/* 0, 1, 3, 4, 2,*/ 2; + //VectorXd xpos(nHive + 1); + //xpos << 1, 1, 1, 2, 3, 2, 1, 0, 0, 0, 1, 2, 3, 3, 4, 3, 3, 2, /*, 5, 5, 5, 5, 5,*/ 2; + //VectorXd ypos(nHive + 1); + //ypos << 3, 2, 1, 1, 2, 3, 4, 3, 2, 1, 0, 0, 0, 1, 2, 3, 4, 4,/* 0, 1, 3, 4, 2,*/ 2; int i, j; for (i = 0; i < nHive + 1; ++i) { int index = (int)(xpos(i) * 5 + ypos(i)); for (j = 0; j < 3; ++j) + OLabHive(index, j) = LabHive(i, j); + + for (j = 0; j < 3; ++j) RGBHive(index, j) = RGBTmpVec(i, j); + for (j = 0; j < m_nVolumes; ++j) OVolumeHive(index, j) = VolumeHive(i, j); + OGamutRegion[index] = GamutRegion[i]; } } @@ -393,19 +477,29 @@ void Tango::ColorLib::ColorConverter::fillRGB(OutputCoordinates *outputCoords, V outputCoords->blue = (int32_t)std::round(RGBOut(2)); } +void Tango::ColorLib::ColorConverter::fillLab(OutputCoordinates *outputCoords, VectorXd LabOut) +{ + outputCoords->has_l = true; + outputCoords->l = LabOut(0); + outputCoords->has_a = true; + outputCoords->a = LabOut(1); + outputCoords->has_b = true; + outputCoords->b = LabOut(2); +} + void Tango::ColorLib::ColorConverter::readColorTransformations(ConversionInput* conversionInput) { //Read thread white. Thread White is given in CIELab Space - - m_whitepointLab.Set(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); - //White point in XYZ Color Space - ColorConvert CConvert(D65, D65); - C_RGB_XYZ_Lab tmpW; - tmpW = CConvert.LabToXYZ(m_whitepointLab); - m_whitepointXYZ_Strip.Set(tmpW.Get_x(), tmpW.Get_y(), tmpW.Get_z()); - + + m_whitepointLab.Set(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + //White point in XYZ Color Space + ColorConvert CConvert(D65, D65); + C_RGB_XYZ_Lab tmpW; + tmpW = CConvert.LabToXYZ(m_whitepointLab); + m_whitepointXYZ_Strip.Set(tmpW.Get_x(), tmpW.Get_y(), tmpW.Get_z()); + //parse Color Tansformations, placed in forward data int bytesread = 0; NumConversions conv; @@ -414,6 +508,19 @@ void Tango::ColorLib::ColorConverter::readColorTransformations(ConversionInput* { //Read Header CT_Header header = read_header(conversionInput, bytesread); + SetnGamutRegions((int)header.nGamutRegions); + + m_GamutRegionMaxLim = new double[m_nGamutRegions]; + for (int i = 0; i < m_nGamutRegions; ++i) + m_GamutRegionMaxLim[i] = header.GRegMaxLim[i]; + + if (header.GRegMaxLim != NULL) + { + delete[]header.GRegMaxLim; + header.GRegMaxLim = NULL; + } + + uint32_t tmp; uint8_t *buff = conversionInput->forwarddata.data; tmp = conv.ByteToInt(buff, bytesread); @@ -463,8 +570,12 @@ void Tango::ColorLib::ColorConverter::readColorTransformations(ConversionInput* TList[k] = desc; else if (strncmp(TagNames[k], "gbd ", 4) == 0) TList[k] = gbd; - else if (strncmp(TagNames[k], "cprt", 2) == 0) + else if (strncmp(TagNames[k], "cprt", 4) == 0) TList[k] = cprt; + else if (strncmp(TagNames[k], "lcrv", 4) == 0) + TList[k] = lcrv; +// else if (strncmp(TagNames[k], "GReg", 2) == 0) +// TList[k] = GReg; else throw std::exception("Unknown Tag in Color Tables"); } @@ -490,6 +601,15 @@ void Tango::ColorLib::ColorConverter::readColorTransformations(ConversionInput* m_B2ATransform->InitData(B2ALUT, B2ALutsize); break; } +/* case GReg: + { + uint8_t *GRegLUT = &(conversionInput->forwarddata.data[TagSize[k][0]]); + int GRegLutsize = TagSize[k][1]; + m_GRegTransform = new ColorTransf(); + //m_B2ATransform = DBG_NEW ColorTransf(); + m_GRegTransform->InitData(GRegLUT, GRegLutsize); + break; + } */ case gbd: { uint8_t *GBDList = &(conversionInput->forwarddata.data[TagSize[k][0]]); @@ -499,6 +619,14 @@ void Tango::ColorLib::ColorConverter::readColorTransformations(ConversionInput* m_GBD->InitData(GBDList, GBDSize); break; } + case lcrv: + { + uint8_t *CurvesData = &(conversionInput->forwarddata.data[TagSize[k][0]]); + m_LinCurves = new Curves(); + int CurvesSize = TagSize[k][1]; + m_LinCurves->InitData(CurvesData, CurvesSize); + break; + } case wtpt: { read_xyz_type(TagSize[k][0], TagSize[k][1], &m_whitepointXYZ_CT, conversionInput); @@ -572,9 +700,9 @@ void Tango::ColorLib::ColorConverter::readCalibrationTables(ConversionInput* con for (int i = 0; i < m_nInks; ++i) { InputLiquid* InkType = conversionInput->inputcoordinates->inputliquids[i]; - + m_CalibCurves[i].SetCalibName((int)(InkType->calibrationdata->liquidtype)); - + m_CalibCurves[i].SetMaxNlPerCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter); switch (InkType->calibrationdata->liquidtype) { @@ -583,9 +711,10 @@ void Tango::ColorLib::ColorConverter::readCalibrationTables(ConversionInput* con case LIQUID_TYPE__Yellow: case LIQUID_TYPE__Black: { - // calibration data. + // calibration data. CalibrationData* calibrationData = InkType->calibrationdata; SetCalibData(calibrationData, i, &m_CalibCurves[i]); + m_CalibCurves[i].InitInterpolations(); break; } default: @@ -598,6 +727,7 @@ void Tango::ColorLib::ColorConverter::readCalibrationTables(ConversionInput* con return; } + void Tango::ColorLib::ColorConverter::SetCalibData(CalibrationData *calibrationData, int i, CalibData *tmpCurve) { if (calibrationData->calibrationpoints <= 0) @@ -645,6 +775,7 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* C_RGB_XYZ_Lab DataLab; SURROUND sur = m_Conv02->getSurround(); + CAM02CS CS = m_Conv02->getCAM02CS(); switch (conversionInput->colorspace) { case (COLOR_SPACE__RGB): @@ -656,7 +787,7 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* //1. Convert RGB to Lab (Whitepoint is D65, same as tables) //2. Convert Lab to Inks (B2A tables), Inks to Volume //3. Convert Inks to Lab (A2B tables) to get the in/on Gamut Lab - //4. Convert Lab to Absolute colorimetric taking into account the Strip and CT whitepoints + //4. Convert Lab to Absolute colorimetric taking into account the Strip and Color Table whitepoints //5. Use the Relative Colorimetric Lab to obtain RGB RGBOut(0) = conversionInput->inputcoordinates->red; @@ -670,45 +801,58 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* //double *RGBOutP = DBG_NEW double[3]; VectorToDouble(RGBOut, RGBOutP); //RGB to Lab - CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 - - double *LabInFinal = new double[3]; - //double *LabInFinal = DBG_NEW double[3]; - memcpy(LabInFinal, LabIn, 3 * sizeof(double)); - //Is In Gamut? - InGamut = IsInGamut(LabIn, sur); + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 + LimitLab(LabIn); + //Is In Gamut? + double *LabInFinal = new double[3]; + double *LabOnGamut = new double[3]; + InGamut = IsInGamut(LabIn, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + //convert to inks int GamutRegion; double *InkOutP = new double[m_nB2AnSepOut]; //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; //LabInFinal is in Relative Colorimetric, just like the Color Tables - m_B2ATransform->evalLab2InkP(LabInFinal, InkOutP, GamutRegion); //InkOut is in units of 16 bits - InkOut = DoubleToVector(InkOutP, m_nInks); + m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is in units of 16 bits + //Convert to Lab to get the actual in Gamut Lab - double *LabInP = new double[3]; + //double *LabInP = new double[3]; //double *LabInP = DBG_NEW double[3]; - m_A2BTransform->evalInkP2Lab(InkOutP, LabInP, GamutRegion); //Lab is in Relative Colorimetric - LabOut = DoubleToVector(LabInP, 3); - //Convert to CT thread, LabIn is in Relative Colorimetric Space - CConvertD65.ChangeWP(LabInP, LabInFinal, m_whitepointXYZ_CT, m_WP); + //m_A2BTransform->evalInkP2Lab(InkOutP, LabInP, GamutRegion); //Lab is in Relative Colorimetric + double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + //Convert InkOut to Linear via initial calibration Tables + //Initial calibration tables are the ones that were included in the color table + for (int i = 0; i < m_nB2AnSepOut; ++i) + { + InkOutP[i] *= NormFactor; + if (InkOutP[i] <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + } + } + InkOut = DoubleToVector(InkOutP, m_nInks); + + //Convert to CT thread, LabOnGamut is in Relative Colorimetric Space + CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_CT, m_WP); //check if the thread to be used is the same as the one in the color tables if (m_AdaptWP) { //Convert to Strip White Point CConvertD65.ChangeWP(LabInFinal, LabInFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); } - + LabOut = DoubleToVector(LabInFinal, 3); CConvertD65.SetReferenceWhite(D65); - //Get the Gamut Mapped RGB Based on Absolute Colorimetric Data double *RGBOutP1 = new double[3]; //double *RGBOutP1 = DBG_NEW double[3]; - //CConvertD65.LabtoRGB(LabInFinal, RGBOutP1); - CConvertD65.LabtoRGB(LabInP, RGBOutP1); + CConvertD65.LabtoRGB(LabOnGamut, RGBOutP1); + //CConvertD65.LabtoRGB(LabInP, RGBOutP1); RGBOut = DoubleToVector(RGBOutP1, 3); - if (LabInP != NULL) + if (LabOnGamut != NULL) { - delete[] LabInP; - LabInP = NULL; + delete[] LabOnGamut; + LabOnGamut = NULL; } if (InkOutP != NULL) { @@ -717,22 +861,22 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* } if (LabIn != NULL) { - delete[] LabIn; + delete [] LabIn; LabIn = NULL; } if (RGBOutP != NULL) { - delete[] RGBOutP; + delete [] RGBOutP; RGBOutP = NULL; } if (RGBOutP1 != NULL) { - delete[] RGBOutP1; + delete [] RGBOutP1; RGBOutP1 = NULL; } if (LabInFinal != NULL) { - delete[] LabInFinal; + delete [] LabInFinal; LabInFinal = NULL; } break; @@ -741,45 +885,62 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* { // Basic assumption: Lab data has the same whitepoint as the STRIP thread. //The workflow is a follows: - //1. Convert Lab to Relative colorimetric. chack if there is a match between STRIP and Color Tables + //1. Convert Lab to Relative colorimetric. check if there is a match between STRIP and Color Tables //2. Convert Lab to Inks (B2A tables), Inks to Volume - //3. Convert Inks to Lab (A2B tables) to get the in/on Gamut Lab + //3. Map the Lab value onto the gamut surface, if it is out of gamut //4. Convert Lab to Absolute colorimetric taking into account the Strip and CT whitepoints //5. Use the Relative Colorimetric Lab to obtain RGB double *LabIn = new double[3]; //double *LabIn = DBG_NEW double[3]; - LabIn[0] = conversionInput->inputcoordinates->l; + LabIn[0] = conversionInput->inputcoordinates->l; //Absolute Colorimetric LabIn[1] = conversionInput->inputcoordinates->a; LabIn[2] = conversionInput->inputcoordinates->b; //the assumption is that the color space has illumination that matches the whitepoint of the Strip ColorConvert CConvertD65(D65, D65); //Destination, source double *LabInFinal1 = new double[3]; //double *LabInFinal1 = DBG_NEW double[3]; - memcpy(LabInFinal1, LabIn, 3 * sizeof(double)); + for (int i=0; i<3; ++i) + LabInFinal1[i]= LabIn[i]; //LabInFinal1 = LabIn; // Lab is assumed to match the color of the STRIP, however the tables could have a different WP //Check if Color Tables and Strip whitepoints are the same, otherwise convert if (m_AdaptWP) { CConvertD65.ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables - LabIn = LabInFinal1; + for (int i = 0; i < 3; ++i) + LabIn[i] = LabInFinal1[i]; } double *LabInFinal2 = new double[3]; + double *LabOnGamut = new double[3]; //double *LabInFinal2 = DBG_NEW double[3]; - CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //to Relative - InGamut = IsInGamut(LabInFinal2, sur); + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //LabInFinal2 is in Relative Colorimetric Space + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + //convert to Inks int GamutRegion; double *InkOutP = new double[m_nB2AnSepOut]; //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; - m_B2ATransform->evalLab2InkP(LabInFinal2, InkOutP, GamutRegion); //InkOut is in units of 16 bits + m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is in units of 16 bits //Convert Inks to Lab to get the Gamut Mapped Lab - m_A2BTransform->evalInkP2Lab(InkOutP, LabIn, GamutRegion); - LabOut = DoubleToVector(LabIn, 3); + //m_A2BTransform->evalInkP2Lab(InkOutP, LabIn, GamutRegion); + //LabOut = DoubleToVector(LabIn, 3); + //Convert InkOutP to linear in the m_ProcessRangesMaxP[0] range + double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + for (int i = 0; i < m_nB2AnSepOut; ++i) + { + InkOutP[i] *= NormFactor; + if (InkOutP[i] <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + } + } InkOut = DoubleToVector(InkOutP, m_nInks); double *LabOutFinal = new double[3]; //double *LabOutFinal = DBG_NEW double[3]; - memcpy(LabOutFinal, LabIn, 3 * sizeof(double)); + for (int i = 0; i < 3; ++i) + LabOutFinal[i] = LabOnGamut[i]; //LabOutFinal is in Relative Colorimetric //Reverse the conversion process to bring back Lab to STRIP white point CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_CT, m_WP); @@ -787,14 +948,20 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* { CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); } + LabOut = DoubleToVector(LabOutFinal, 3); CConvertD65.SetReferenceWhite(D65); //Convert to RGB - double *RGBOutP = new double[3]; + double *RGBOutP = new double[3]; // double *RGBOutP = DBG_NEW double[3]; - //CConvertD65.LabtoRGB(LabOutFinal, RGBOutP); - CConvertD65.LabtoRGB(LabIn, RGBOutP); + //Use Relative colorimetric to get RGB + CConvertD65.LabtoRGB(LabOnGamut, RGBOutP); + //CConvertD65.LabtoRGB(LabIn, RGBOutP); RGBOut = DoubleToVector(RGBOutP, 3); - + if (LabOnGamut != NULL) + { + delete[] LabOnGamut; + LabOnGamut = NULL; + } if (InkOutP != NULL) { delete[] InkOutP; @@ -826,7 +993,7 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* delete[] RGBOutP; RGBOutP = NULL; } - break; + break; } case(COLOR_SPACE__CMYK): @@ -840,8 +1007,8 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* outData[1] = (double)(conversionInput->inputcoordinates->magenta); outData[2] = (double)(conversionInput->inputcoordinates->yellow); outData[3] = conversionInput->inputcoordinates->key; - CountSep = 4; - + CountSep=4; + if (CountSep != m_nA2BnSepIn) { //mismatch between table and sent data @@ -862,30 +1029,33 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* ColorConvert CConvertD65(D65, D65); double *LabOutFinal1 = new double[3]; //double *LabOutFinal1 = DBG_NEW double[3]; - LabOutFinal1 = LabOutP; + for (int i = 0; i < 3; ++i) + LabOutFinal1[i] = LabOutP[i]; double *LabOutFinal2 = new double[3]; //double *LabOutFinal2 = DBG_NEW double[3]; - LabOutFinal2 = LabOutP; + for ( int i = 0; i < 3; ++i) + LabOutFinal2[i] = LabOutP[i]; InGamut = true; //Check if white points match - CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_CT, m_WP); + CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_CT, m_WP); //To Absolute if (m_AdaptWP) - {//check if this is needed + { CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal2, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); - LabOutFinal1 = LabOutFinal2; + for (int i=0; i<3; ++i) + LabOutFinal1[i] = LabOutFinal2[i]; } LabOut = DoubleToVector(LabOutFinal1, 3); CConvertD65.SetReferenceWhite(D65); //Get RGB double *RGBOutP = new double[3]; //double *RGBOutP = DBG_NEW double[3]; - //CConvertD65.LabtoRGB(LabOutFinal1, RGBOutP); CConvertD65.LabtoRGB(LabOutP, RGBOutP); + //CConvertD65.LabtoRGB(LabOutP, RGBOutP); RGBOut = DoubleToVector(RGBOutP, 3); - + if (outData != NULL) { - delete[] outData; + delete[] outData; outData = NULL; } if (LabOutP != NULL) @@ -905,35 +1075,30 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* } if (LabOutFinal1 != NULL) { - delete[] LabOutFinal1; + delete [] LabOutFinal1; LabOutFinal1 = NULL; } if (LabOutFinal2 != NULL) { - delete[] LabOutFinal2; + delete [] LabOutFinal2; LabOutFinal2 = NULL; } - if (RGBOutP != NULL) + break; + } + case(COLOR_SPACE__Coats): + { + int32_t inData; + if (conversionInput->inputcoordinates->has_pantoncode) + inData = conversionInput->inputcoordinates->pantoncode; + else { - delete[] RGBOutP; - RGBOutP = NULL; + //mismatch between color space and data + throw std::exception("Mismatch between color space and data"); + return; } break; + //missing calculation method and pantone table, either in terms of RGB or CMY or Lab } - //case(COLOR_SPACE__PANTON): - //{ - // int32_t inData; - // if (conversionInput->inputcoordinates->has_pantoncode) - // inData = conversionInput->inputcoordinates->pantoncode; - // else - // { - // //mismatch between color space and data - // throw std::exception("Mismatch between color space and data"); - // return; - // } - // break; - // //missing calculation method and pantone table, either in terms of RGB or CMY or Lab - //} default: { @@ -945,13 +1110,16 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(ConversionInput* return; } + void Tango::ColorLib::ColorConverter::ConvertToNLInks(VectorXd InkIn, VectorXd &InkOut) { for (int i = 0; i < m_nVolumes; ++i) { - m_InvLinInterp[i].Eval(InkIn(i), InkOut(i)); + if (InkIn(i) <= m_ProcessRangesMaxP[0]) + m_CalibCurves[i].m_InvLinearInterp->Eval(InkIn(i), InkOut(i)); + else + InkOut(i) = InkIn(i); } - return; } @@ -959,7 +1127,7 @@ void Tango::ColorLib::ColorConverter::ConvertToLinearInks(VectorXd InkIn, Vecto { for (int i = 0; i < m_nVolumes; ++i) { - m_LinInterp[i].Eval(InkIn(i), InkOut(i)); + m_CalibCurves[i].m_LinearInterp->Eval(InkIn(i), InkOut(i)); } return; @@ -1015,7 +1183,7 @@ void Tango::ColorLib::ColorConverter::VolumeToNLInkP(VectorXd Volume, VectorXd & //Solve System of Linear Equations MatrixXd MatNLIInv(m_nVolumes - 1, m_nVolumes - 1); MatNLIInv = MatNLI.inverse(); - VectorXd Result = MatNLIInv * RHSide; + VectorXd Result = MatNLIInv*RHSide; //VectorXd Result = MatNLI.colPivHouseholderQr().solve(RHSide); //rearrange solution ind = -1; @@ -1050,13 +1218,13 @@ void Tango::ColorLib::ColorConverter::NLInkPToVolume(VectorXd NLInk, VectorXd &V { for (i = 0; i < m_nInks; ++i) { - InkNorm(i) = MaxInk * NLInk(i) / InkSum; + InkNorm(i) = MaxInk*NLInk(i) / InkSum; Volume(i) = InkNorm(i); // InkNorm(i) * m_maxNlPerCM(i) / 100; // Volume is in % } // Round to k decimal digits, verify that sum in within allowed values. double sumNorm = 0.0; double RsumNorm = 0.0; - VectorXd RVolNorm(m_nInks); + VectorXd RVolNorm(m_nInks); double ROUNDINGTol = pow(10, ROUNDINGDigits); for (i = 0; i < m_nInks; ++i) @@ -1065,25 +1233,27 @@ void Tango::ColorLib::ColorConverter::NLInkPToVolume(VectorXd NLInk, VectorXd &V RVolNorm(i) = round(Volume(i)*ROUNDINGTol) / ROUNDINGTol; RsumNorm += RVolNorm(i); } - if (RsumNorm > 200.0 || abs(sumNorm - RsumNorm) >= 1 / ROUNDINGTol) + if (RsumNorm >m_ProcessRangesMaxP[m_nProcessRanges-1] || abs(sumNorm - RsumNorm) >= 1 / ROUNDINGTol) { VectorXd dd(m_nInks); double maxdd = -1; - int maxInd; + int maxInd= -1; for (int i = 0; i < m_nInks; ++i) { - dd(i) = Volume(i) - RVolNorm(i); + dd(i) =Volume(i) - RVolNorm(i); if (abs(dd(i)) > maxdd) { - maxdd = dd(i); + maxdd = abs(dd(i)); maxInd = i; } } int signdd = 0; if (dd(maxInd) > 0) signdd = 1; - else + else if(dd(maxInd) < 0) signdd = -1; + else + signdd = 0; RVolNorm(maxInd) = RVolNorm(maxInd) + signdd / ROUNDINGTol; } for (int i = 0; i < m_nInks; ++i) @@ -1103,7 +1273,7 @@ void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(ConversionInput* // Set Calibration Data LiquidType LQ; if (m_CalibCurves == NULL) - { + { m_CalibCurves = new CalibData[m_nInks]; //m_CalibCurves = DBG_NEW CalibData[m_nInks]; for (int i = 0; i < m_nVolumes; ++i) @@ -1121,54 +1291,90 @@ void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(ConversionInput* std::exception("unsupported volume"); } } - VectorXd NLInkP((int)(m_nVolumes)); VectorXd InkOut((int)(m_nVolumes)); //Convert to Nonlinear Inks for (int i = 0; i < m_nVolumes; ++i) Volume(i) = conversionInput->inputcoordinates->inputliquids[i]->volume; //volume is given in % VolumeToNLInkP(Volume, NLInkP); - //Convert to Linear Inks - ConvertToLinearInks(NLInkP, InkOut); + double *InkOutP = new double[m_nA2BnSepIn]; + VectorToDouble(NLInkP, InkOutP); + //for (int i = 0; i < m_nA2BnSepIn; ++i) + // InkOutP[i] = NLInkP(i); + double *LinInkP = new double[m_nA2BnSepIn]; + double NormFactor =100/ m_ProcessRangesMaxP[m_nProcessRanges - 1]; + + if (conversionInput->colorspace == COLOR_SPACE__Twine) + { + for (int i = 0; i < m_nB2AnSepOut; ++i) + { + if (NLInkP(i) <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + NLInkP(i) = InkOutP[i]; + } + } + for (int i = 0; i < (int)(m_nVolumes); ++i) + { + if(NLInkP(i) <= m_ProcessRangesMaxP[0]) + { + m_CalibCurves[i].m_InvLinearInterp->Eval(InkOutP[i], InkOutP[i]); + NLInkP(i) = InkOutP[i]; + } + } + NLInkPToVolume(NLInkP, Volume); + } + //Convert to RGB GamutRegion = 0; //Convert to Lab - double *InkOutP = new double[m_nA2BnSepIn]; + double *LabOutP = new double[m_nA2BnSepOut]; //double *InkOutP = DBG_NEW double[m_nA2BnSepIn]; //double *LabOutP = DBG_NEW double[m_nA2BnSepOut]; - for (int i = 0; i < m_nA2BnSepIn; ++i) - InkOutP[i] = InkOut(i); - m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion); + //InkOutP has to be normalized to match the transform units + for (int i = 0; i < m_nB2AnSepOut; ++i) + InkOutP[i] *= NormFactor; + + m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion); - //LabOut is in Relative Colorimetric + //LabOutP is in Relative Colorimetric ColorConvert CConvertD65(D65, D65); double *LabOutFinal1 = new double[3]; //double *LabOutFinal1 = DBG_NEW double[3]; - double *LabOutFinal = LabOutP; - CConvertD65.ChangeWP(LabOutFinal, LabOutFinal1, m_whitepointXYZ_CT, m_WP); - LabOutFinal = LabOutFinal1; + double *LabOutFinal = new double[3]; + + CConvertD65.ChangeWP(LabOutP, LabOutFinal1, m_whitepointXYZ_CT, m_WP); //To Absolute + for (int i=0; i<3; ++i) + LabOutFinal[i] = LabOutFinal1[i]; + if (m_AdaptWP) { - CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); + CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); } + LabOut = DoubleToVector(LabOutFinal, 3); + CConvertD65.SetReferenceWhite(D65); double *RGBOutP = new double[3]; //double *RGBOutP = DBG_NEW double[3]; - //CConvertD65.LabtoRGB(LabOutFinal, RGBOutP); - CConvertD65.LabtoRGB(LabOutP, RGBOutP); + CConvertD65.LabtoRGB(LabOutP, RGBOutP); + for (int i = 0; i < 3; ++i) { RGBOut(i) = RGBOutP[i]; - //LabOut(i) = LabOutFinal[i]; - LabOut(i) = LabOutP[i]; } if (InkOutP != NULL) { delete[]InkOutP; InkOutP = NULL; } + if (LinInkP != NULL) + { + delete[]LinInkP; + LinInkP = NULL; + } if (LabOutP != NULL) { delete[] LabOutP; @@ -1176,14 +1382,19 @@ void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(ConversionInput* } if (RGBOutP != NULL) { - delete[] RGBOutP; + delete [] RGBOutP; RGBOutP = NULL; } if (LabOutFinal1 != NULL) { - delete[] LabOutFinal1; + delete [] LabOutFinal1; LabOutFinal1 = NULL; } + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } return; } @@ -1203,6 +1414,14 @@ VectorXd Tango::ColorLib::ColorConverter::DoubleToVector(double *doub, int nSize return(Vec); } +void Tango::ColorLib::ColorConverter::LimitLab(double* LabIn) +{ + LabIn[0] = std::min(std::max(LabIn[0], 0.0), 100.0); + LabIn[1] = std::min(std::max(LabIn[1], -128.0), 127.0); + LabIn[2] = std::min(std::max(LabIn[2], -128.0), 127.0); + return; +} + size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) { @@ -1217,9 +1436,238 @@ size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t i conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); - ConversionOutput* conversionOutput = ConvertInternal(conversionInput); - //Pack output... + //Filter and arrange colors (Should change from 3 to 4 if black ink is included) + + int numofInks = CountNumberofInks(conversionInput); + if(numofInks <0) + throw std::exception("Duplicate inks"); + int expected_liquids = numofInks; + original_input_liquids_count = conversionInput->inputcoordinates->n_inputliquids; + original_input_liquids = conversionInput->inputcoordinates->inputliquids; + + InputLiquid** filteredInputLiquids = (InputLiquid**)malloc(sizeof(InputLiquid*) * expected_liquids); + + for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) + { + InputLiquid* liquid = conversionInput->inputcoordinates->inputliquids[i]; + + switch (liquid->liquidtype) + { + case LIQUID_TYPE__Cyan: + filteredInputLiquids[0] = liquid; + break; + case LIQUID_TYPE__Magenta: + filteredInputLiquids[1] = liquid; + break; + case LIQUID_TYPE__Yellow: + filteredInputLiquids[2] = liquid; + break; + case LIQUID_TYPE__Black: + filteredInputLiquids[3] = liquid; + break; + } + } + + conversionInput->inputcoordinates->inputliquids = filteredInputLiquids; + conversionInput->inputcoordinates->n_inputliquids = expected_liquids; + //Filter and arrange colors + + + + //Initialize Output... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + conversion_output__init(conversionOutput); + // ConversionOutput conversionOutput = CONVERSION_OUTPUT__INIT; + + + size_t n_elements = 0; + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + //count number if inks + // int numofInks = CountNumberofInks(conversionInput); + readColorTransformations(conversionInput); + if (m_nGamutRegions != conversionInput->n_processranges) + throw std::exception("Number of gamut regions in teble does not match STRIP"); + + //read calibration tables and store them in m_CalibCurves + + readCalibrationTables(conversionInput); + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + //m_Conv02 = DBG_NEW ColorConvert(IL, IL, Y_b, L_A, sur, CS); + SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn()); + SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut()); + SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn()); + SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut()); + + SetNumberOfInks(m_nB2AnSepOut); + // Compare Strip White point to Color Table White Point + CompareWhitePoints(); + + if (numofInks != m_nB2AnSepOut) + throw std::exception("Number of available inks does not match ink tables"); + + //Tables have been filled + + //Convert maxInkUptake to percentages + m_nProcessRanges = (int)(conversionInput->n_processranges); + //m_ProcessRangesMinP = new double[m_nProcessRanges]; + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + //m_ProcessRangesMinInkUptake = new double[m_nProcessRanges]; + //m_ProcessRangesMaxInkUptake = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + // m_ProcessRangesMinP[i] = 100*(conversionInput->processranges[i]->mininkuptake)/ (conversionInput->processranges[0]->mininkuptake); + m_ProcessRangesMaxP[i] = 100 * (conversionInput->processranges[i]->maxinkuptake) / (conversionInput->processranges[0]->maxinkuptake); + //m_ProcessRangesMinInkUptake[i] = conversionInput->processranges[i]->mininkuptake; + //m_ProcessRangesMaxInkUptake[i] = conversionInput->processranges[i]->maxinkuptake; + } + + VectorXd InkOut(m_nB2AnSepOut); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nB2AnSepOut); + VectorXd Volume(m_nB2AnSepOut); + VectorXd VolumeOut(m_nB2AnSepOut); + //set maxNlPerCM + VectorXd NlperCM(m_nB2AnSepOut); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nB2AnSepOut; ++i) + SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); + m_nVolumes = m_nB2AnSepOut; + int GamutRegion = 0; + //Convert input data to linear inks + if (conversionInput->colorspace == COLOR_SPACE__Volume || conversionInput->colorspace == COLOR_SPACE__Twine) + { + ConvertVolumeToRGBDisplay(conversionInput, Volume, RGBOut, LabOut, GamutRegion); + InGamut = true; + } + else + { + ConvertColorToLinearInks(conversionInput, InkOut, RGBOut, LabOut, GamutRegion, InGamut); + //Inks are in Linear Space , convert to nonlinear by using Calibration Tables, + // Right now calibration is in the [0-100] range, values exceeding [0-100] are not transformed + ConvertToNLInks(InkOut, NLInkOut); + //Determine Gamut Region + double maxNLInk = -10; + for (int i = 0; i<m_nInks; ++i) + maxNLInk = std::max(NLInkOut[i], maxNLInk); + + for (int i = 0; i < int(conversionInput->n_processranges - 1); ++i) + { + if (maxNLInk > m_ProcessRangesMaxP[i]) + GamutRegion++; + } + //Convert to [nl/cm] + NLInkPToVolume(NLInkOut, Volume); + //OutputCoordinates outputCoords = OUTPUT_COORDINATES__INIT; + } + OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(outputCoords); + fillRGB(outputCoords, RGBOut); + fillLab(outputCoords, LabOut); + outputCoords->processparameterstableindex = GamutRegion; + fillVolume(outputCoords, Volume); + conversionOutput->has_outofgamut = true; + conversionOutput->outofgamut = !(InGamut); + conversionOutput->singlecoordinates = outputCoords; + + + //input was processed. + //process neighboring values + //nhive includes 2 outer neighbors of the central Lab value, chroma + delta, chroma + 2delta + // and variation in L positioned on the side of the beehive. + //The set is arrange in a 5x6 matrix, where the 5x5 contains the variation in (Hue, chroma) + // and the last 5 contain the variation in L + int nHive = 18; //22; // 18; + int MatHive = 25;// 30; //25; + + MatrixXd RGBHive(MatHive, 3); + VectorXd RGBHive1(3); + VectorXd LabHive1(3); + VectorXd VolumeHive1(m_nVolumes); + MatrixXd VolumeHive(MatHive, m_nVolumes); + MatrixXd LabHive(MatHive, 3); + + int *GamutRegionV = new int[MatHive]; + //int *GamutRegionV = DBG_NEW int[MatHive]; + for (int i = 0; i < MatHive ; ++i) + GamutRegionV[i] = -1; + + int indDataMax[2]; + int j = 0; + // Matrix values are initially set to -1; + RGBHive.setConstant(NegValue); + VolumeHive.setConstant(NegValue); + + ProcessHiveNeighbors(conversionInput, LabOut, RGBOut, Volume, GamutRegion, RGBHive, LabHive,VolumeHive, nHive, GamutRegionV, indDataMax); + OutputCoordinates** hiveData = (OutputCoordinates**)malloc(sizeof(OutputCoordinates*) * MatHive); + conversionOutput->hivecoordinates = hiveData; + conversionOutput->n_hivecoordinates = MatHive; + conversionOutput->n_triplecoordinates = 3; + for (int i = 0; i < MatHive; i++) + { + // OutputCoordinates SingleCell = OUTPUT_COORDINATES__INIT; + hiveData[i] = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(hiveData[i]); + if (RGBHive(i, 0) != NegValue) + { + for (j = 0; j < 3; ++j) + RGBHive1(j) = RGBHive(i, j); + fillRGB(hiveData[i], RGBHive1); + for (j = 0; j < m_nVolumes; ++j) + VolumeHive1(j) = VolumeHive(i, j); + fillVolume(hiveData[i], VolumeHive1); + for (j = 0; j < 3; ++j) + LabHive1(j) = LabHive(i, j); + fillLab(hiveData[i], LabHive1); + hiveData[i]->has_processparameterstableindex = true; + hiveData[i]->processparameterstableindex = GamutRegionV[i]; + hiveData[i]->n_outputliquids = m_nInks; + } + conversionOutput->hivecoordinates[i] = hiveData[i]; + } + + + //Triplet + OutputCoordinates** TripletData = (OutputCoordinates**)malloc(sizeof(OutputCoordinates*) * 3); + conversionOutput->triplecoordinates = TripletData; + int tripletIndex[3] = { indDataMax[0] , (int)(12), indDataMax[1] }; + for (int i = 0; i < 3; ++i) + { + // OutputCoordinates SingleCell = OUTPUT_COORDINATES__INIT; + TripletData[i] = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(TripletData[i]); + for (j = 0; j < 3; ++j) + RGBHive1(j) = RGBHive(tripletIndex[i], j); + fillRGB(TripletData[i], RGBHive1); + for (j = 0; j < m_nVolumes; ++j) + VolumeHive1(j) = VolumeHive(tripletIndex[i], j); + fillVolume(TripletData[i], VolumeHive1); + for (j = 0; j < 3; ++j) + LabHive1(j) = LabHive(tripletIndex[i], j); + fillLab(TripletData[i], LabHive1); + TripletData[i]->has_processparameterstableindex = true; + TripletData[i]->processparameterstableindex = GamutRegionV[tripletIndex[i]]; + TripletData[i]->n_outputliquids = m_nInks; + conversionOutput->triplecoordinates[i] = TripletData[i]; + } + + //Clean up + if (GamutRegionV != NULL) + { + delete [] GamutRegionV; + GamutRegionV = NULL; + } + + + //Pack output... output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(conversionOutput)); int size = conversion_output__pack(conversionOutput, output_buffer); @@ -1245,10 +1693,10 @@ size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t i conversionOutput->has_haserror = true; conversionOutput->haserror = true; - const char* what = e.what(); + const char* what = e.what(); conversionOutput->errormessage = (char*)malloc(strlen(what)); - strcpy(conversionOutput->errormessage, e.what()); + strcpy_s(conversionOutput->errormessage, strlen(what), what); output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(conversionOutput)); int size = conversion_output__pack(conversionOutput, output_buffer); @@ -1266,11 +1714,13 @@ size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t i } } -void Tango::ColorLib::ColorConverter::InitInterpolations(int numofInks, Interp *linearInterp, Interp *InvLinearInterp) + + +/*void Tango::ColorLib::ColorConverter::InitInterpolations(int numofInks, Interp *linearInterp, Interp *InvLinearInterp) { double *xCoords; double *yCoords; - + for (int i = 0; i < numofInks; ++i) { xCoords = m_CalibCurves[i].getxCoords(); @@ -1283,7 +1733,7 @@ void Tango::ColorLib::ColorConverter::InitInterpolations(int numofInks, Interp * InvLinearInterp[i].SetYCoords(xCoords); InvLinearInterp[i].SetNPoints(npts); } -} +}*/ int Tango::ColorLib::ColorConverter::CountNumberofInks(ConversionInput* conversionInput) { @@ -1338,13 +1788,19 @@ int Tango::ColorLib::ColorConverter::CountNumberofInks(ConversionInput* conversi return(numberofInks); } -bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur) +bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord) { - int nInLab = 3; + int nInLab =3; double *xCoord = new double[nInLab]; //double *xCoord = DBG_NEW double[nInLab]; //Convert InLab to CIECam02 coordinates bool InGamut = true; + if (InLab[0] > 100 || InLab[0] < 0 || InLab[1] > 127 || InLab[1] < -128 || InLab[2] > 127 || InLab[2] < -128) + { + InGamut = false; + LimitLab(InLab); + } + double ctr[3]; C_RGB_XYZ_Lab center = m_GBD->getCenter(); VectorXd JInLab(3); @@ -1363,16 +1819,27 @@ bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur) VectorXd V1(3); VectorXd V2(3); V1 << JLab[0], JLab[1], JLab[2]; - V2 << xCoord[0], xCoord[1], xCoord[2]; + V2<< xCoord[0], xCoord[1], xCoord[2]; double dECMC; m_Conv02->SymmetricaldECMC(V1, V2, dECMC); if (dECMC < dETol) InGamut = true; else InGamut = false; + VectorXd JabV(3); + JabV = DoubleToVector(xCoord, 3); + VectorXd LabV(3); + LabV = m_Conv02->Jab_2_Lab(JabV, CS); + VectorToDouble(LabV, LabCoord); } else + { InGamut = true; + for (int i = 0; i < 3; ++i) + LabCoord[i] = InLab[i]; + } + //Convert back to Lab + if (xCoord != NULL) { delete[] xCoord; @@ -1386,6 +1853,7 @@ bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur) return(InGamut); } + Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(ConversionInput* conversionInput, int &bytesread) { //CT_Header *Header = new CT_Header; @@ -1407,13 +1875,14 @@ Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(ConversionInput* c Header.Version[2] = versionBCT[1] & 15; bytesread += 1; uint32_t tmp = Conv.ByteToInt(ColorTable, bytesread); - int n = sizeof((char*)&tmp); + int n = sizeof((char*)&tmp); //char *tmpC = DBG_NEW char[n]; char *tmpC = new char[n]; - Conv.getchar(tmp, n, tmpC); + Conv.getchar(tmp, n, tmpC); //Header.ColorSpace = DBG_NEW char[n]; - Header.ColorSpace = new char[n]; - memcpy_s(Header.ColorSpace, n + 1, tmpC, n); + Header.ColorSpace = new char[n]; + memcpy_s(Header.ColorSpace, n + 1, tmpC, n); + // strncpy_s(Header->ColorSpace, n+1, tmpC, n); //Header->ColorSpace = tmpC; bytesread += 4; @@ -1422,6 +1891,7 @@ Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(ConversionInput* c //Header.ConnectionSpace = DBG_NEW char[n]; Header.ConnectionSpace = new char[n]; memcpy_s(Header.ConnectionSpace, n + 1, tmpC, n); + bytesread += 4; bytesread += 12; @@ -1430,8 +1900,8 @@ Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(ConversionInput* c //Header.DeviceManufacturer = DBG_NEW char[n]; Header.DeviceManufacturer = new char[n]; memcpy_s(Header.DeviceManufacturer, n + 1, tmpC, n); - // strncpy_s(Header->DeviceManufacturer, n + 1, tmpC, n); - //Header->DeviceManufacturer = tmpC; +// strncpy_s(Header->DeviceManufacturer, n + 1, tmpC, n); + //Header->DeviceManufacturer = tmpC; delete[]tmpC; bytesread += 4; //read illuminant @@ -1443,6 +1913,17 @@ Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(ConversionInput* c bytesread += 4; } Header.Illuminant.Set(xyz[0], xyz[1], xyz[2]); + //Read Number of Gamut Regions and Max Limits per Region + Header.nGamutRegions = ColorTable[bytesread]; + bytesread++; + Header.GRegMaxLim = new double[Header.nGamutRegions]; + for (int i = 0; i < Header.nGamutRegions; ++i) + { + tmp = Conv.ByteToShort(ColorTable, bytesread); + bytesread +=2; + Header.GRegMaxLim[i] = (double)tmp; + } + if (bytesread < 128) { bytesread = 128; @@ -1494,7 +1975,7 @@ void Tango::ColorLib::ColorConverter::read_xyz_type(int offset, int data_size, C NumConversions Conv; int bytesread = 0; int tmpxyz = Conv.ByteToInt(buff, bytesread); - + int n = sizeof(tmpxyz); //char* tmpC = DBG_NEW char[n]; char* tmpC = new char[n]; @@ -1576,6 +2057,7 @@ void Tango::ColorLib::ColorConverter::read_text_type(int offset, int data_size, return; } + void Tango::ColorLib::ColorConverter::read_text_description_type(int offset, int data_size, std::string textdescstr, ConversionInput* conversionInput) { @@ -1635,8 +2117,8 @@ void Tango::ColorLib::ColorConverter::CompareWhitePoints() VLab_Strip(2) = Lab_Strip.Get_z(); double dECMC; ColConv.SymmetricaldECMC(VLab_CT, VLab_Strip, dECMC); - if (dECMC < WPTol) - m_AdaptWP = false; + if (dECMC > WPTol) + m_AdaptWP = true; return; } @@ -1787,6 +2269,8 @@ void Tango::ColorLib::ColorConverter::CompareWhitePoints() // return conversion_output__pack(&conversionOutput, output_buffer); //} + + size_t Tango::ColorLib::ColorConverter::P_IsInGamut(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) { @@ -1844,7 +2328,7 @@ size_t Tango::ColorLib::ColorConverter::P_IsInGamut(uint8_t * input_buffer, size //read calibration tables and store them in m_CalibCurves readCalibrationTables(conversionInput); - + //Initialize CIECAM02 transformation Illum IL = D65; SURROUND sur = average; @@ -1868,120 +2352,123 @@ size_t Tango::ColorLib::ColorConverter::P_IsInGamut(uint8_t * input_buffer, size VectorXd LabOut(3); VectorXd NLInkOut(m_nB2AnSepOut); VectorXd Volume(m_nB2AnSepOut); - + C_RGB_XYZ_Lab DataLab; //SURROUND sur = m_Conv02->getSurround(); switch (conversionInput->colorspace) { case (COLOR_SPACE__RGB): { - // Basic assumption: if data is given in RGB space, conversion should be in relative colorimetric, - //We expect that [255,255,255](white) will be mapped to the thread white, meaning all inks should be zero - // and the coverted RGB will refect the color of the thread - //The workflow is a follows: - //1. Convert RGB to Lab (Whitepoint is D65, same as tables) - //2.Fiond if Lab is InGamut - - RGBOut(0) = conversionInput->inputcoordinates->red; - RGBOut(1) = conversionInput->inputcoordinates->green; - RGBOut(2) = conversionInput->inputcoordinates->blue; - //convert to Lab - ColorConvert CConvertD65(D65, D65); //Destination, source - //double *LabIn = DBG_NEW double[3]; - //double *RGBOutP = DBG_NEW double[3]; - double *LabIn = new double[3]; - double *RGBOutP = new double[3]; - VectorToDouble(RGBOut, RGBOutP); - //RGB to Lab - CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 - - //Is In Gamut? - InGamut = IsInGamut(LabIn, sur); - - if (LabIn != NULL) - { - delete[] LabIn; - LabIn = NULL; + // Basic assumption: if data is given in RGB space, conversion should be in relative colorimetric, + //We expect that [255,255,255](white) will be mapped to the thread white, meaning all inks should be zero + // and the coverted RGB will refect the color of the thread + //The workflow is a follows: + //1. Convert RGB to Lab (Whitepoint is D65, same as tables) + //2.Fiond if Lab is InGamut + + RGBOut(0) = conversionInput->inputcoordinates->red; + RGBOut(1) = conversionInput->inputcoordinates->green; + RGBOut(2) = conversionInput->inputcoordinates->blue; + //convert to Lab + ColorConvert CConvertD65(D65, D65); //Destination, source + //double *LabIn = DBG_NEW double[3]; + //double *RGBOutP = DBG_NEW double[3]; + double *LabIn = new double[3]; + double *RGBOutP = new double[3]; + VectorToDouble(RGBOut, RGBOutP); + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 + + //Is In Gamut? + InGamut = IsInGamut(LabIn, sur, CS, LabIn); + + if (LabIn != NULL) + { + delete [] LabIn; + LabIn = NULL; + } + if (RGBOutP != NULL) + { + delete [] RGBOutP; + RGBOutP = NULL; + } + break; } - if (RGBOutP != NULL) + case (COLOR_SPACE__LAB): { - delete[] RGBOutP; - RGBOutP = NULL; - } - break; - } - case (COLOR_SPACE__LAB): - { - // Basic assumption: Lab data has the same whitepoint as the STRIP thread. - //The workflow is a follows: - //1. Convert Lab to Relative colorimetric. check if there is a match between STRIP and Color Tables - //2. Find if Lab is InGamut + // Basic assumption: Lab data has the same whitepoint as the STRIP thread. + //The workflow is a follows: + //1. Convert Lab to Relative colorimetric. check if there is a match between STRIP and Color Tables + //2. Find if Lab is InGamut - double *LabIn = new double[3]; - //double *LabIn = DBG_NEW double[3]; - LabIn[0] = conversionInput->inputcoordinates->l; - LabIn[1] = conversionInput->inputcoordinates->a; - LabIn[2] = conversionInput->inputcoordinates->b; - //the assumption is that the color space has illumination that matches the whitepoint of the Strip - ColorConvert CConvertD65(D65, D65); //Destination, source - double *LabInFinal1 = new double[3]; - //double *LabInFinal1 = DBG_NEW double[3]; - memcpy(LabInFinal1, LabIn, 3 * sizeof(double)); - // Lab is assumed to match the color of the STRIP, however the tables could have a different WP - //Check if Color Tables and Strip whitepoints are the same, otherwise convert - if (m_AdaptWP) - { - CConvertD65.ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables - LabIn = LabInFinal1; + double *LabIn = new double[3]; + //double *LabIn = DBG_NEW double[3]; + LabIn[0] = conversionInput->inputcoordinates->l; + LabIn[1] = conversionInput->inputcoordinates->a; + LabIn[2] = conversionInput->inputcoordinates->b; + //the assumption is that the color space has illumination that matches the whitepoint of the Strip + ColorConvert CConvertD65(D65, D65); //Destination, source + double *LabInFinal1 = new double[3]; + //double *LabInFinal1 = DBG_NEW double[3]; + for (int i=0; i<3; ++i) + LabInFinal1[i] = LabIn[i]; + // Lab is assumed to match the color of the STRIP, however the tables could have a different WP + //Check if Color Tables and Strip whitepoints are the same, otherwise convert + if (m_AdaptWP) + { + CConvertD65.ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables + } + double *LabInFinal2 = new double[3]; + //double *LabInFinal2 = DBG_NEW double[3]; + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //to Relative + InGamut = IsInGamut(LabInFinal2, sur, CS, LabInFinal2); + LimitLab(LabInFinal2); + + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (LabInFinal1 != NULL) + { + delete[]LabInFinal1; + LabInFinal1 = NULL; + } + if (LabInFinal2 != NULL) + { + delete[]LabInFinal2; + LabInFinal2 = NULL; + } + break; } - double *LabInFinal2 = new double[3]; - //double *LabInFinal2 = DBG_NEW double[3]; - CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //to Relative - InGamut = IsInGamut(LabInFinal2, sur); - - if (LabIn != NULL) - { - delete[] LabIn; - LabIn = NULL; + case(COLOR_SPACE__CMYK): + case(COLOR_SPACE__Volume): + case(COLOR_SPACE__Twine): + {//no conversion + //missing from structure light inks or special colors + // just convert Lab for rgb display + InGamut = true; } - if (LabInFinal1 != NULL) + case(COLOR_SPACE__Coats): { - delete[]LabInFinal1; - LabInFinal1 = NULL; + int32_t inData; + if (conversionInput->inputcoordinates->has_pantoncode) + inData = conversionInput->inputcoordinates->pantoncode; + else + { + //mismatch between color space and data + throw std::exception("Mismatch between color space and data"); + return(0); + } + break; + //missing calclulation method and pantone table, either in terms of RGB or CMY or Lab } - if (LabInFinal2 != NULL) + default: { - delete[]LabInFinal2; - LabInFinal2 = NULL; + throw std::exception(" Unsupported Color Space"); + return(0); + } } - break; - } - case(COLOR_SPACE__CMYK): - {//no conversion - //missing from structure light inks or special colors - // just convert Lab for rgb display - InGamut = true; - } - //case(COLOR_SPACE__PANTON): - //{ - // int32_t inData; - // if (conversionInput->inputcoordinates->has_pantoncode) - // inData = conversionInput->inputcoordinates->pantoncode; - // else - // { - // //mismatch between color space and data - // throw std::exception("Mismatch between color space and data"); - // return(0); - // } - // break; - // //missing calclulation method and pantone table, either in terms of RGB or CMY or Lab - //} - default: - { - throw std::exception(" Unsupported Color Space"); - return(0); - } - } //Pack data OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); @@ -2006,324 +2493,4 @@ size_t Tango::ColorLib::ColorConverter::P_IsInGamut(uint8_t * input_buffer, size #pragma endregion return (size); -} - -ConversionOutput* Tango::ColorLib::ColorConverter::ConvertInternal(ConversionInput* conversionInput) -{ - InputLiquid** original_input_liquids = NULL; - int original_input_liquids_count = 0; - - //Filter and arrange colors (Should change from 3 to 4 if black ink is included) - - int numofInks = CountNumberofInks(conversionInput); - if (numofInks < 0) - throw std::exception("Duplicate inks"); - int expected_liquids = numofInks; - original_input_liquids_count = conversionInput->inputcoordinates->n_inputliquids; - original_input_liquids = conversionInput->inputcoordinates->inputliquids; - - InputLiquid** filteredInputLiquids = (InputLiquid**)malloc(sizeof(InputLiquid*) * expected_liquids); - - for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) - { - InputLiquid* liquid = conversionInput->inputcoordinates->inputliquids[i]; - - switch (liquid->liquidtype) - { - case LIQUID_TYPE__Cyan: - filteredInputLiquids[0] = liquid; - break; - case LIQUID_TYPE__Magenta: - filteredInputLiquids[1] = liquid; - break; - case LIQUID_TYPE__Yellow: - filteredInputLiquids[2] = liquid; - break; - case LIQUID_TYPE__Black: - filteredInputLiquids[3] = liquid; - break; - } - } - - conversionInput->inputcoordinates->inputliquids = filteredInputLiquids; - conversionInput->inputcoordinates->n_inputliquids = expected_liquids; - //Filter and arrange colors - - - - //Initialize Output... - ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); - conversion_output__init(conversionOutput); - // ConversionOutput conversionOutput = CONVERSION_OUTPUT__INIT; - - - size_t n_elements = 0; - bool InGamut = false; - m_WP.Set(0.9505, 1.00, 1.0888); //D65 - //count number if inks -// int numofInks = CountNumberofInks(conversionInput); - readColorTransformations(conversionInput); - - //read calibration tables and store them in m_CalibCurves - - readCalibrationTables(conversionInput); - m_LinInterp = new Interp[numofInks]; - //m_LinInterp = DBG_NEW Interp[numofInks]; - m_InvLinInterp = new Interp[numofInks]; - //m_InvLinInterp = DBG_NEW Interp[numofInks]; - InitInterpolations(numofInks, m_LinInterp, m_InvLinInterp); - - //Initialize CIECAM02 transformation - Illum IL = D65; - SURROUND sur = average; - CAM02CS CS = UCS; - m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); - //m_Conv02 = DBG_NEW ColorConvert(IL, IL, Y_b, L_A, sur, CS); - SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn()); - SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut()); - SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn()); - SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut()); - - SetNumberOfInks(m_nB2AnSepOut); - // Compare Strip White point to Color Table White Point - CompareWhitePoints(); - - if (numofInks != m_nB2AnSepOut) - throw std::exception("Number of available inks does not match ink tables"); - - VectorXd InkOut(m_nB2AnSepOut); - VectorXd RGBOut(3); - VectorXd LabOut(3); - VectorXd NLInkOut(m_nB2AnSepOut); - VectorXd Volume(m_nB2AnSepOut); - //set maxNlPerCM - VectorXd NlperCM(m_nB2AnSepOut); - NlperCM.setZero(); - m_maxNlPerCM = NlperCM; - for (int i = 0; i < m_nB2AnSepOut; ++i) - SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); - m_nVolumes = m_nB2AnSepOut; - int GamutRegion = 0; - //Convert input data to linear inks - if (conversionInput->colorspace == COLOR_SPACE__Volume) - { - ConvertVolumeToRGBDisplay(conversionInput, Volume, RGBOut, LabOut, GamutRegion); - InGamut = true; - } - else - { - ConvertColorToLinearInks(conversionInput, InkOut, RGBOut, LabOut, GamutRegion, InGamut); - //Convert to Nonlinear Inks - ConvertToNLInks(InkOut, NLInkOut); - //Convert to [nl/cm] - NLInkPToVolume(NLInkOut, Volume); - //OutputCoordinates outputCoords = OUTPUT_COORDINATES__INIT; - } - OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); - output_coordinates__init(outputCoords); - fillRGB(outputCoords, RGBOut); - fillVolume(outputCoords, Volume); - conversionOutput->has_outofgamut = true; - conversionOutput->outofgamut = !(InGamut); - conversionOutput->singlecoordinates = outputCoords; - - - if (!conversionInput->singlemode) //Skip if input requests single result only. - { - //input was processed. - //process neighboring values - //nhive includes 2 outer neighbors of the central Lab value, chroma + delta, chroma + 2delta - // and variation in L positioned on the side of the beehive. - //The set is arrange in a 5x6 matrix, where the 5x5 contains the variation in (Hue, chroma) - // and the last 5 contain the variation in L - int nHive = 18; //22; // 18; - int MatHive = 25;// 30; //25; - - MatrixXd RGBHive(MatHive, 3); - VectorXd RGBHive1(3); - VectorXd VolumeHive1(m_nVolumes); - MatrixXd VolumeHive(MatHive, m_nVolumes); - int *GamutRegionV = new int[MatHive]; - //int *GamutRegionV = DBG_NEW int[MatHive]; - for (int i = 0; i < MatHive; ++i) - GamutRegionV[i] = -1; - - int indDataMax[2]; - int j = 0; - // Matrix values are initially set to -1; - RGBHive.setConstant(NegValue); - VolumeHive.setConstant(NegValue); - - ProcessHiveNeighbors(LabOut, RGBOut, Volume, GamutRegion, RGBHive, VolumeHive, nHive, GamutRegionV, indDataMax); - OutputCoordinates** hiveData = (OutputCoordinates**)malloc(sizeof(OutputCoordinates*) * MatHive); - conversionOutput->hivecoordinates = hiveData; - conversionOutput->n_hivecoordinates = MatHive; - conversionOutput->n_triplecoordinates = 3; - for (int i = 0; i < MatHive; i++) - { - // OutputCoordinates SingleCell = OUTPUT_COORDINATES__INIT; - hiveData[i] = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); - output_coordinates__init(hiveData[i]); - if (RGBHive(i, 0) != NegValue) - { - for (j = 0; j < 3; ++j) - RGBHive1(j) = RGBHive(i, j); - fillRGB(hiveData[i], RGBHive1); - for (j = 0; j < m_nVolumes; ++j) - VolumeHive1(j) = VolumeHive(i, j); - fillVolume(hiveData[i], VolumeHive1); - hiveData[i]->has_processparameterstableindex = true; - hiveData[i]->processparameterstableindex = GamutRegionV[i]; - hiveData[i]->n_outputliquids = m_nInks; - } - conversionOutput->hivecoordinates[i] = hiveData[i]; - } - - - //Triplet - OutputCoordinates** TripletData = (OutputCoordinates**)malloc(sizeof(OutputCoordinates*) * 3); - conversionOutput->triplecoordinates = TripletData; - int tripletIndex[3] = { indDataMax[0] , (int)(12), indDataMax[1] }; - for (int i = 0; i < 3; ++i) - { - // OutputCoordinates SingleCell = OUTPUT_COORDINATES__INIT; - TripletData[i] = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); - output_coordinates__init(TripletData[i]); - for (j = 0; j < 3; ++j) - RGBHive1(j) = RGBHive(tripletIndex[i], j); - fillRGB(TripletData[i], RGBHive1); - for (j = 0; j < m_nVolumes; ++j) - VolumeHive1(j) = VolumeHive(tripletIndex[i], j); - fillVolume(TripletData[i], VolumeHive1); - TripletData[i]->has_processparameterstableindex = true; - TripletData[i]->processparameterstableindex = GamutRegionV[tripletIndex[i]]; - TripletData[i]->n_outputliquids = m_nInks; - conversionOutput->triplecoordinates[i] = TripletData[i]; - } - - //Clean up - if (GamutRegionV != NULL) - { - delete[] GamutRegionV; - GamutRegionV = NULL; - } - } - - return conversionOutput; -} - -size_t Tango::ColorLib::ColorConverter::ConvertGradient(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) -{ - GradientConversionInput* conversionInput = NULL; - - try - { - //Get Input - conversionInput = (GradientConversionInput*)malloc(sizeof(GradientConversionInput)); - conversionInput = gradient_conversion_input__unpack(NULL, input_buffer_size, input_buffer); - - //Init Output - GradientConversionOutput *conversionOutput = (GradientConversionOutput*)malloc(sizeof(GradientConversionOutput)); - gradient_conversion_output__init(conversionOutput); - - //Init reusable conversion input. - ConversionInput* input = (ConversionInput*)malloc(sizeof(ConversionInput)); - conversion_input__init(input); - - input->colorspace = COLOR_SPACE__RGB; - input->deltachroma = conversionInput->deltachroma; - input->deltal = conversionInput->deltal; - input->forwarddata = conversionInput->forwarddata; - input->processranges = conversionInput->processranges; - input->segmentlength = conversionInput->segmentlength; - input->singlemode = true; - input->threadl = conversionInput->threadl; - input->threada = conversionInput->threada; - input->threadb = conversionInput->threadb; - - input->has_colorspace = true; - input->has_deltachroma = true; - input->has_deltal = true; - input->has_segmentlength = true; - input->has_forwarddata = true; - input->has_singlemode = true; - input->has_threadl = true; - input->has_threada = true; - input->has_threadb = true; - - //Init reusable input coordinates. - InputCoordinates* inputCoords = (InputCoordinates*)malloc(sizeof(InputCoordinates)); - input_coordinates__init(inputCoords); - - inputCoords->inputliquids = conversionInput->inputliquids; - inputCoords->n_inputliquids = conversionInput->n_inputliquids; - - inputCoords->has_red = true; - inputCoords->has_green = true; - inputCoords->has_blue = true; - - input->inputcoordinates = inputCoords; - - OutputCoordinates** outputCoordinatesList = (OutputCoordinates**)malloc(conversionInput->n_colors * sizeof(OutputCoordinates*));; - - for (size_t i = 0; i < conversionInput->n_colors; i++) - { - inputCoords->red = conversionInput->colors[i]->red; - inputCoords->green = conversionInput->colors[i]->green; - inputCoords->blue = conversionInput->colors[i]->blue; - - ConversionOutput* output = ConvertInternal(input); - outputCoordinatesList[i] = output->singlecoordinates; - } - - conversionOutput->coordinates = outputCoordinatesList; - conversionOutput->n_coordinates = conversionInput->n_colors; - - //Pack output... - output_buffer = (uint8_t*)malloc(gradient_conversion_output__get_packed_size(conversionOutput)); - int size = gradient_conversion_output__pack(conversionOutput, output_buffer); - - free(input->forwarddata.data); - - for (size_t i = 0; i < conversionInput->n_colors; i++) - { - for (size_t j = 0; j < outputCoordinatesList[i]->n_outputliquids; j++) - { - free(outputCoordinatesList[i]->outputliquids[j]); - } - - free(outputCoordinatesList[i]); - } - - free(outputCoordinatesList); - - gradient_conversion_input__free_unpacked(conversionInput, NULL); - - return (size); - } - catch (const std::exception& e) - { - //Notify Error... - GradientConversionOutput *conversionOutput = (GradientConversionOutput*)malloc(sizeof(GradientConversionOutput)); - gradient_conversion_output__init(conversionOutput); - - conversionOutput->has_haserror = true; - conversionOutput->haserror = true; - - const char* what = e.what(); - - conversionOutput->errormessage = (char*)malloc(strlen(what)); - strcpy(conversionOutput->errormessage, e.what()); - - output_buffer = (uint8_t*)malloc(gradient_conversion_output__get_packed_size(conversionOutput)); - int size = gradient_conversion_output__pack(conversionOutput, output_buffer); - -#pragma region Free Output - - gradient_conversion_input__free_unpacked(conversionInput, NULL); - -#pragma endregion - - return (size); - } }
\ No newline at end of file diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.h b/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.h index 8976119ad..8b354f42a 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.h +++ b/Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.h @@ -12,18 +12,21 @@ #include "CalibrationData.pb-c.h" #include "ConversionInput.pb-c.h" #include "Interp.h" +#include "Curves.h" #pragma once namespace Tango { typedef struct { - unsigned int TblSIze; - unsigned int Version[3]; + unsigned int TblSIze = 0; + unsigned int Version[3] = { 0,0,0 }; char * ColorSpace; char * ConnectionSpace; char * DeviceManufacturer; C_RGB_XYZ_Lab Illuminant; + unsigned char nGamutRegions=0; + double *GRegMaxLim; } CT_Header; typedef enum { @@ -39,7 +42,9 @@ namespace Tango cprt, gbd, wtpt, - desc + desc, + lcrv +// GReg }TagList; namespace ColorLib @@ -57,8 +62,6 @@ namespace Tango void ConvertVolumeToRGBDisplay(ConversionInput* conversionInput, VectorXd &InkOut, VectorXd &RGBOut, VectorXd &LabOut, int &GamutRegion); size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); - size_t Tango::ColorLib::ColorConverter::ConvertGradient(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); - ConversionOutput* Tango::ColorLib::ColorConverter::ConvertInternal(ConversionInput* conversionInput); void ConvertToNLInks(VectorXd InkIn, VectorXd &InkOut); void ConvertToLinearInks(VectorXd InkIn, VectorXd &InkOut); void VolumeToNLInkP(VectorXd Volume, VectorXd &NLInkP); @@ -68,13 +71,18 @@ namespace Tango private: ColorTransf *m_B2ATransform; ColorTransf *m_A2BTransform; +// ColorTransf *m_GRegTransform; GBD *m_GBD; + Curves *m_LinCurves; ColorConvert *m_Conv02; - Interp *m_LinInterp; - Interp *m_InvLinInterp; +// Interp *m_LinInterp; +// Interp *m_InvLinInterp; C_RGB_XYZ_Lab m_whitepointLab; C_RGB_XYZ_Lab m_whitepointXYZ_Strip; C_RGB_XYZ_Lab m_whitepointXYZ_CT; + void LimitLab(double* LabIn); + int m_nGamutRegions; + double *m_GamutRegionMaxLim; int m_nB2AnSepIn; int m_nB2AnSepOut; int m_nA2BnSepIn; @@ -83,31 +91,40 @@ namespace Tango CalibData *m_CalibCurves; int m_nInks; int m_nVolumes; + int m_nProcessRanges; + //double *m_ProcessRangesMinP; + double *m_ProcessRangesMaxP; + //double *m_ProcessRangesMaxInkUptake; + //double *m_ProcessRangesMinInkUptake; C_RGB_XYZ_Lab m_WP; VectorXd m_maxNlPerCM; void SetnB2AnSepIn(int nB2AnSepIn) { m_nB2AnSepIn = nB2AnSepIn; }; void SetnB2AnSepOut(int nB2AnSepOut) { m_nB2AnSepOut = nB2AnSepOut; }; void SetnA2BnSepIn(int nA2BnSepIn) { m_nA2BnSepIn = nA2BnSepIn; }; void SetnA2BnSepOut(int nA2BnSepOut) { m_nA2BnSepOut = nA2BnSepOut; }; + void SetnGamutRegions(int nGamutRegions) { m_nGamutRegions = nGamutRegions; }; void readColorTransformations(ConversionInput* conversionInput); void readCalibrationTables(ConversionInput* conversionInput); void SetCalibData(CalibrationData* calibrationData, int i, CalibData *tmpCurve); void SetNumberofInks(int nInks) { m_nInks = nInks; }; void SetNumberOfVolumes(int nVol) { m_nVolumes = nVol; }; void SetNumberOfInks(int nInks) { m_nInks = nInks; }; - void InitInterpolations(int numofInks, Interp *linearInterp, Interp *InvLinearInterp); + // void InitInterpolations(int numofInks, Interp *linearInterp, Interp *InvLinearInterp); void fillRGB(OutputCoordinates *outputCoords, VectorXd RGBOut); + void fillLab(OutputCoordinates *outputCoords, VectorXd LabOut); void fillVolume(OutputCoordinates *&outputCoords, VectorXd Volume); - void ProcessHiveNeighbors(VectorXd LabC, VectorXd RGBC, VectorXd VolumeC, int InGamutRegion, - MatrixXd &RGBOut, MatrixXd &VolumeOut, int nHive, int *&GamutRegion, int *indDataMax); - void ArrangeHiveData(MatrixXd RGBTmpVec, MatrixXd VolumeHive, int *GamutRegion, - int nHive, MatrixXd &RGBHive, MatrixXd &OVolumeHive, int *&OGamutRegion); + void ProcessHiveNeighbors(ConversionInput *conversionInput, VectorXd LabC, VectorXd RGBC, VectorXd VolumeC, + int InGamutRegion, MatrixXd &RGBOut, MatrixXd & LabOut, MatrixXd &VolumeOut, + int nHive, int *&GamutRegion, int *indDataMax); + void ArrangeHiveData(MatrixXd LabHive, MatrixXd RGBTmpVec, MatrixXd VolumeHive, int *GamutRegion, + VectorXd xpos, VectorXd ypos, int nHive, MatrixXd &OLabHive, + MatrixXd &ORGBHive, MatrixXd &OVolumeHive, int *&OGamutRegion); void FindTriplet(VectorXd Lab, MatrixXd Lab1, int nHive, int*indDataMax); int CountNumberofInks(ConversionInput* conversionInput); void VectorToDouble(VectorXd Vec, double *doub); VectorXd DoubleToVector(double *doub, int nSize); void CompareWhitePoints(); - bool IsInGamut(double *InLab, SURROUND sur); + bool IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord); CT_Header read_header(ConversionInput* conversionInput, int &bytesread); void read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput); void read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *xyz, ConversionInput* conversionInput); diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Exports.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Exports.cpp index 61410fdc4..b3f111455 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Exports.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Exports.cpp @@ -1,7 +1,20 @@ #include <cstdlib> #include "Exports.h" #include "ColorConverter.h" +//#include <vld.h> +/*#define _CRTDBG_MAP_ALLOC +#include <stdlib.h> +#include <crtdbg.h> +#include <cstdlib> +#ifdef _DEBUG +#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) +// Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the +// allocations to be of _CLIENT_BLOCK type +#else +#define DBG_NEW new +#endif*/ +//#include <vld.h> #pragma once #define EXPORT_API __declspec(dllexport) @@ -15,9 +28,9 @@ extern "C" EXPORT_API size_t __cdecl Convert(uint8_t* input_buffer, size_t input return converter.Convert(input_buffer, input_buffer_size, output_buffer); } -extern "C" EXPORT_API size_t __cdecl ConvertGradient(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +extern "C" EXPORT_API size_t __cdecl P_IsInGamut(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) { ColorConverter converter; - return converter.ConvertGradient(input_buffer, input_buffer_size, output_buffer); + return converter.P_IsInGamut(input_buffer, input_buffer_size, output_buffer); } diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj b/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj index 224588ad3..bf2b50ebd 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj @@ -183,6 +183,7 @@ <ClInclude Include="Utils\CalibData.h" /> <ClInclude Include="Utils\ColorConvert.h" /> <ClInclude Include="Utils\ColorTransf.h" /> + <ClInclude Include="Utils\Curves.h" /> <ClInclude Include="Utils\C_RGB_XYZ_Lab.h" /> <ClInclude Include="Utils\GBD.h" /> <ClInclude Include="Utils\Interp.h" /> @@ -210,6 +211,7 @@ <ClCompile Include="Utils\CalibData.cpp" /> <ClCompile Include="Utils\ColorConvert.cpp" /> <ClCompile Include="Utils\ColorTransf.cpp" /> + <ClCompile Include="Utils\Curves.cpp" /> <ClCompile Include="Utils\C_RGB_XYZ_Lab.cpp" /> <ClCompile Include="Utils\GBD.cpp" /> <ClCompile Include="Utils\Interp.cpp" /> diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj.filters b/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj.filters index 5277161da..b83ed601c 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj.filters +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj.filters @@ -102,14 +102,8 @@ <ClInclude Include="PMR\ColorLab\ProcessRange.pb-c.h"> <Filter>PMR</Filter> </ClInclude> - <ClInclude Include="PMR\ColorLab\GradientConversionOutput.pb-c.h"> - <Filter>PMR</Filter> - </ClInclude> - <ClInclude Include="PMR\ColorLab\InputRGB.pb-c.h"> - <Filter>PMR</Filter> - </ClInclude> - <ClInclude Include="PMR\ColorLab\GradientConversionInput.pb-c.h"> - <Filter>PMR</Filter> + <ClInclude Include="Utils\Curves.h"> + <Filter>Utils</Filter> </ClInclude> </ItemGroup> <ItemGroup> @@ -179,14 +173,8 @@ <ClCompile Include="PMR\ColorLab\ProcessRange.pb-c.c"> <Filter>PMR</Filter> </ClCompile> - <ClCompile Include="PMR\ColorLab\GradientConversionOutput.pb-c.c"> - <Filter>PMR</Filter> - </ClCompile> - <ClCompile Include="PMR\ColorLab\InputRGB.pb-c.c"> - <Filter>PMR</Filter> - </ClCompile> - <ClCompile Include="PMR\ColorLab\GradientConversionInput.pb-c.c"> - <Filter>PMR</Filter> + <ClCompile Include="Utils\Curves.cpp"> + <Filter>Utils</Filter> </ClCompile> </ItemGroup> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.cpp index 67fd024b5..5bc16221e 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.cpp @@ -14,12 +14,13 @@ #endif */ CalibData::CalibData(): m_npoints(0), m_XCoords(NULL), -m_YCoords(NULL), m_InkName(0), m_maxNlPerCM(0) +m_YCoords(NULL), m_InkName(0), m_maxNlPerCM(0), m_LinearInterp(NULL), m_InvLinearInterp(NULL) { } CalibData::CalibData(const CalibData &rhs) : m_npoints(rhs.m_npoints), m_XCoords(rhs.m_XCoords), -m_YCoords(rhs.m_YCoords), m_InkName(rhs.m_InkName), m_maxNlPerCM(rhs.m_maxNlPerCM) +m_YCoords(rhs.m_YCoords), m_InkName(rhs.m_InkName), m_maxNlPerCM(rhs.m_maxNlPerCM), +m_LinearInterp(rhs.m_LinearInterp), m_InvLinearInterp(rhs.m_InvLinearInterp) { } @@ -35,6 +36,16 @@ CalibData::~CalibData() delete[] m_YCoords; m_YCoords = NULL; } + if (m_LinearInterp != NULL) + { + delete m_LinearInterp; + m_LinearInterp = NULL; + } + if (m_InvLinearInterp != NULL) + { + delete m_InvLinearInterp; + m_InvLinearInterp = NULL; + } } void CalibData::SetXCoords(double * XCoords) { @@ -51,3 +62,11 @@ void CalibData::SetYCoords(double* YCoords) for (int i = 0; i<m_npoints; ++i) m_YCoords[i] = YCoords[i]; } + +void CalibData::InitInterpolations() +{ + m_LinearInterp = new Interp(); + m_InvLinearInterp = new Interp(); + m_LinearInterp->Init(m_XCoords, m_YCoords, m_npoints); + m_InvLinearInterp->Init(m_YCoords, m_XCoords, m_npoints); +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.h b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.h index 50f22bccc..f0c4b5a45 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.h +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.h @@ -2,6 +2,8 @@ #define __CALIBDATA_H__ #include <cmath> #include <algorithm> +#include "Interp.h" + class CalibData { public: @@ -17,6 +19,9 @@ class CalibData void SetXCoords(double* XCoords); void SetYCoords(double* YCoords); void SetMaxNlPerCM(double maxNlPerCM) {m_maxNlPerCM = maxNlPerCM;} + Interp *m_LinearInterp; + Interp *m_InvLinearInterp; + void InitInterpolations(); private: int m_npoints; double *m_XCoords; diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.cpp index 07b1535e8..a0d773aee 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.cpp @@ -400,7 +400,7 @@ const C_RGB_XYZ_Lab &ColorConvert::GetReferenceWhite(void) const DataXYZ = RGBtoXYZ(RGBVal); C_RGB_XYZ_Lab DataLab; DataLab = XYZToLab(DataXYZ); - DataLab.Clamp(LowLab, HighLab); +// DataLab.Clamp(LowLab, HighLab); return(DataLab); } @@ -414,7 +414,7 @@ const C_RGB_XYZ_Lab &ColorConvert::GetReferenceWhite(void) const SetReferenceWhite(DestWhite); C_RGB_XYZ_Lab LabOut1; LabOut1 = XYZToLab(XYZ); - LabOut1.Clamp(LowLab, HighLab); + // LabOut1.Clamp(LowLab, HighLab); // double *LabD = new double[3]; LabOut[0] = LabOut1.Get_x(); LabOut[1] = LabOut1.Get_y(); @@ -892,6 +892,20 @@ void ColorConvert::Jab_parameters(CAM02CS CS) return(Jab); } + VectorXd ColorConvert::Jab_2_Lab(VectorXd Jab, CAM02CS CS) + { + VectorXd XYZ(3); + XYZ = Jab_2_XYZ(Jab, CS); + C_RGB_XYZ_Lab LabOut; + C_RGB_XYZ_Lab XYZ1; + XYZ1.Set(XYZ/100.0); + LabOut = XYZToLab(XYZ1); + VectorXd Lab(3); + Lab = LabOut.Get(); + return(Lab); + } + + VectorXd ColorConvert::Jab_2_XYZ(VectorXd Jab, CAM02CS CS) { //convert from Jab colorspace to the XYZ colorspace. @@ -1110,8 +1124,10 @@ void ColorConvert::Jab_parameters(CAM02CS CS) double dL = refX( 0) - samX( 0); double dC = samX_C - refX_C; - double dE = sqrt(dL*dL + (refX(1) - samX(1))* (refX(1) - samX(1)) + (refX(2) - samX(2))* (refX(2) - samX(2))); - double dH = sqrt(dE*dE - dC*dC - dL*dL); + double da = refX(1) - samX(1); + double db = refX(2) - samX(2); + double dH = sqrt(std::max(da*da + db * db - dC * dC, 0.0)); + dECMC = sqrt(pow(dL / (2 * refX_SL),2) + pow(dC / refX_SC,2) + pow(dH / refX_SH,2)); } diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.h b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.h index 6d349da8c..aa1b323b1 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.h +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.h @@ -85,6 +85,7 @@ class ColorConvert C_RGB_XYZ_Lab NormalizeWPXYZ(C_RGB_XYZ_Lab& xyzVal); VectorXd XYZtoJab(VectorXd pColor, SURROUND sur); VectorXd Jab_2_XYZ(VectorXd Jab, CAM02CS CS); + VectorXd Jab_2_Lab(VectorXd Jab, CAM02CS CS); VectorXd LabToJab(VectorXd pColor, SURROUND sur); double *LabToJab(double* pColor, SURROUND sur); void InitCiecamParams(double Y_b, double L_A, SURROUND sur, CAM02CS CS); diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.cpp index 218642472..7bad0f90b 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.cpp @@ -7,6 +7,7 @@ #include <iostream> #include <stdio.h> #include "NumConversions.h" +#include "Interp.h" using namespace std; #define LFactor 100 @@ -36,7 +37,7 @@ using namespace std; ColorTransf::ColorTransf() : m_MSBShift(0), m_DataBuffer(NULL), m_SeparationsIn(0), m_SeparationsOut(0), m_nGridPoints(0), m_GamutLimitsNlperCM(NULL), - m_NGamutRegions(0) + m_NGamutRegions(0), m_ByteBuffer(NULL), m_InputCurves(NULL), m_OutputCurves(NULL) { } @@ -53,17 +54,41 @@ using namespace std; delete[] m_GamutLimitsNlperCM; m_GamutLimitsNlperCM = NULL; } + if (m_ByteBuffer != NULL) + { + delete[] m_ByteBuffer; + m_ByteBuffer = NULL; + } + if (m_InputCurves != NULL) + { + delete[] m_InputCurves; + m_InputCurves = NULL; + } + if (m_OutputCurves != NULL) + { + delete[] m_OutputCurves; + m_OutputCurves = NULL; + } } void ColorTransf::InitData(unsigned char *colorTransformBuffer, long colorTransformSize) { /* the whole file is now loaded in the memory buffer. */ /*Parse data*/ - /*1st Element: Number of Separations In - 2nd Element: Number of Separations Out - 3rd Element: Number of gridpoints - 4th Element: Most Significant bits shift - 5th Element: Number of Gamut Regions N (number between 0 and 3) + /* + 0-3 'prec1', 'prec2' + 4-7 reserved, must be 0 + 8 number of input channels, uint8 + 9 number of output channels, uint8 + 10 number of CLUT grid points, uint8 + 11 Most Significant bits shift + 12 Number of gamut regions + 13-14 Number of Input Table entries + 15-16 Number of Output Table entries + prec 2 (16bit) + 17-n CLUT values, uint16 + prec 1 + 17-n CLUT values, uint8 */ //long lSize, lSizeHalf; @@ -130,36 +155,140 @@ using namespace std; } else SetMSBShift((int)num_Sh4MSB); //Number of MSB's - uint8_t GReg = buffer[ bytesread]; - bytesread += 1; - if (GReg > 0) - SetNGamutRegions((int)GReg); //Number of Gamut Regions + + unsigned short num_input_table_entries = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + Set_NumInputTableEntries((int)num_input_table_entries); + + unsigned short num_output_table_entries = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + Set_NumOutputTableEntries((int)num_output_table_entries); + m_InputCurves = new Interp[m_SeparationsIn]; + double *xIn = new double[m_num_input_table_entries]; + double *yIn = new double[m_num_input_table_entries]; + //read Input tables + if (TablePrecision == 1) + { + double deltax = 255.0 / (m_num_input_table_entries - 1); + for (int i = 0; i < m_num_input_table_entries; ++i) + xIn[i] = deltax * i; + + for (int i = 0; i < m_SeparationsIn; ++i) + { + for (int j = 0; j < m_num_input_table_entries; ++j) + { + yIn[j] = buffer[bytesread]; + bytesread += 1; + } + m_InputCurves[i].Init(xIn, yIn, m_num_input_table_entries); + } + } else { - throw std::exception("No Gamut Regions in table header, ColorTransf::InitData"); + double deltax = 65535.0 / (m_num_input_table_entries - 1); + for (int i = 0; i < m_num_input_table_entries; ++i) + xIn[i] = deltax * i; + for (int i = 0; i < m_SeparationsIn; ++i) + { + for (int j = 0; j < m_num_input_table_entries; ++j) + { + yIn[j] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + } + m_InputCurves[i].Init(xIn, yIn, m_num_input_table_entries); + } } - int clut_size = (int)pow(double(num_clut_grid_points), num_input_channels); + + int clut_size = (int)pow(double(num_clut_grid_points), m_SeparationsIn)* m_SeparationsOut; // lut8Type and lut16Type + if (TablePrecision == 1) + { +// int lsizeH2 = (lSize - bytesread + 1) / 2; + m_ByteBuffer = new unsigned char[clut_size]; + int lSizeperSep = clut_size / m_SeparationsOut; + int indR = 0; + for (int i = 0; i < lSizeperSep; ++i) + { + for (int j = 0; j < m_SeparationsOut; ++j) + { + //m_ByteBuffer[indR] = Conv.ByteToShort(buffer, bytesread); + m_ByteBuffer[indR] = buffer[bytesread]; + bytesread += 1; + indR++; + } + } + m_InterpColor.InitData(m_ByteBuffer, m_SeparationsIn, m_SeparationsOut, m_nGridPoints, m_MSBShift); + } + else + { +// int lsizeH4 = (lSize - bytesread + 1) / 2; + m_DataBuffer = new unsigned short[clut_size]; + //m_DataBuffer = DBG_NEW unsigned short[lsizeH4]; + int lSizeperSep = clut_size / m_SeparationsOut; + int indR = 0; + for (int i = 0; i < lSizeperSep; ++i) + { + for (int j = 0; j < m_SeparationsOut; ++j) + { + m_DataBuffer[indR] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + indR++; + } + } + // terminate reading data file + m_InterpColor.InitData(m_DataBuffer, m_SeparationsIn, m_SeparationsOut, m_nGridPoints, m_MSBShift); + } - //convert to usigned short - - int lsizeH4 =( lSize - bytesread + 1)/2; -// int lsizeH4 = lSizeHalf - totHeader; - m_DataBuffer = new unsigned short[lsizeH4]; - //m_DataBuffer = DBG_NEW unsigned short[lsizeH4]; - int lSizeperSep = lsizeH4 / m_SeparationsOut; - int indR = 0; - for (int i = 0; i < lSizeperSep; ++i) + //Read Output Curves + double *xOut = new double[m_num_output_table_entries]; + double *yOut = new double[m_num_output_table_entries]; + m_OutputCurves = new Interp[m_SeparationsOut]; + //read Input tables + if (TablePrecision == 1) { - for (int j = 0; j < m_SeparationsOut; ++j) + double deltax = 255.0 / (m_num_output_table_entries - 1); + for (int i = 0; i < m_num_output_table_entries; ++i) + xOut[i] = deltax * i; + + for (int i = 0; i < m_SeparationsOut; ++i) { - m_DataBuffer[indR] = Conv.ByteToShort(buffer, bytesread); - bytesread += 2; - indR++; + for (int j = 0; j < m_num_output_table_entries; ++j) + { + yOut[j] = buffer[bytesread]; + bytesread += 1; + } + m_OutputCurves[i].Init(xOut, yOut, m_num_output_table_entries); } } - // terminate reading data file - m_InterpColor.InitData(m_DataBuffer, m_SeparationsIn, m_SeparationsOut, m_nGridPoints, m_MSBShift); + else + { + double deltax = 65535.0 / (m_num_output_table_entries - 1); + for (int i = 0; i < m_num_output_table_entries; ++i) + xOut[i] = deltax * i; + for (int i = 0; i < m_SeparationsOut; ++i) + { + for (int j = 0; j < m_num_output_table_entries; ++j) + { + yOut[j] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + } + m_OutputCurves[i].Init(xOut, yOut, m_num_output_table_entries); + } + } + //clean up + if (xIn != NULL) + delete[] xIn; + xIn = NULL; + if (yIn != NULL) + delete[] yIn; + yIn = NULL; + if (xOut != NULL) + delete[] xOut; + xOut = NULL; + if (yOut != NULL) + delete[] yOut; + yOut = NULL; + return; } @@ -185,12 +314,27 @@ void ColorTransf::evalLab2InkP(double *ColorIn, double *&ColorOut, int &GamutR iColorIn[2] = uint16_t(tmpColorOut.Get_z()); double *tmpColor = new double[m_SeparationsOut]; //double *tmpColor = DBG_NEW double[m_SeparationsIn]; + double tmpIC = 0; + //Aply Input Curves + for (int i = 0; i < m_SeparationsIn; ++i) + { + m_InputCurves[i].Eval((double)iColorIn[i], tmpIC); + iColorIn[i] = (unsigned short)tmpIC; + } if (m_SeparationsIn == 3) m_InterpColor.ColorMap3(iColorIn, tmpColor); else if (m_SeparationsIn == 4) - m_InterpColor.ColorMap4(iColorIn, tmpColor); + { + m_InterpColor.ColorMap4(iColorIn, tmpColor); + } else throw std::exception("Unsupported Number of Separations in ColorTransf::evalLab2Ink"); + //Appy Output Curves + for (int i = 0; i < m_SeparationsOut; ++i) + { + m_OutputCurves[i].Eval((double)tmpColor[i], tmpIC); + tmpColor[i] = (unsigned short)tmpIC; + } //tmpColorOut between 0and 255 //normalize to [0-100] for (int i = 0; i < m_SeparationsOut; ++i) @@ -210,6 +354,61 @@ void ColorTransf::evalLab2InkP(double *ColorIn, double *&ColorOut, int &GamutR return; } +void ColorTransf::evalInCurve(double *ColorIn, double *&ColorOut) +{ + //To be used to transform Nonlinear Inks to Linear with m_A2B transform + + /*Convert ColorIn to uint16 */ + uint16_t *iColorIn = new uint16_t[m_SeparationsIn]; + //uint16_t *iColorIn = DBG_NEW uint16_t[m_SeparationsIn]; + double tmpIC = 0; + + for (int i = 0; i < m_SeparationsIn; ++i) + { + //convert to 16 bits + iColorIn[i] = uint16_t(double(ColorIn[i] / InkFactor)*Uint16Factor); + //Aply Input Curves + m_InputCurves[i].Eval((double)iColorIn[i], tmpIC); + ColorOut[i] = tmpIC * InkFactor / Uint16Factor; + } + + if (iColorIn != NULL) + { + delete[] iColorIn; + iColorIn = NULL; + } + + return; +} + +void ColorTransf::evalOutCurve(double *ColorIn, double *&ColorOut) +{ + //To be used to transform Linear Inks to Nonlinear with m_B2A transform + + /*Convert ColorIn to uint16 */ + uint16_t *iColorIn = new uint16_t[m_SeparationsOut]; + //uint16_t *iColorIn = DBG_NEW uint16_t[m_SeparationsIn]; + double tmpIC = 0; + + for (int i = 0; i < m_SeparationsOut; ++i) + { + //convert to 16 bits + iColorIn[i] = uint16_t(double(ColorIn[i] / InkFactor)*Uint16Factor); + //Aply Output Curves + m_OutputCurves[i].Eval((double)iColorIn[i], tmpIC); + ColorOut[i] = tmpIC * InkFactor / Uint16Factor; + } + + if (iColorIn != NULL) + { + delete[] iColorIn; + iColorIn = NULL; + } + + return; +} + + void ColorTransf::evalInkP2Lab(double *ColorIn, double *&ColorOut, int &GamutRegion) { double *tmpColorOut = new double[m_SeparationsOut]; @@ -217,14 +416,30 @@ void ColorTransf::evalInkP2Lab(double *ColorIn, double *&ColorOut, int &GamutReg /*Convert ColorIn to uint16 */ uint16_t *iColorIn = new uint16_t[m_SeparationsIn]; //uint16_t *iColorIn = DBG_NEW uint16_t[m_SeparationsIn]; + double tmpIC = 0; + //convert to 16 bits for (int i=0; i<m_SeparationsIn; ++i) iColorIn[i] = uint16_t(double(ColorIn[i] / InkFactor)*Uint16Factor); + //Aply Input Curves + for (int i = 0; i < m_SeparationsIn; ++i) + { + m_InputCurves[i].Eval((double)iColorIn[i], tmpIC); + iColorIn[i] = (unsigned short)tmpIC; + } + if (m_SeparationsIn == 3) m_InterpColor.ColorMap3(iColorIn, tmpColorOut); // return Value is double in units of 16 bits else if (m_SeparationsIn == 4) m_InterpColor.ColorMap4(iColorIn, tmpColorOut); // return value is double in units on 16 bits else throw std::exception("Unsupported Number of Separations in ColorTransf::evalInkP2Lab"); + //Appy Output Curves + for (int i = 0; i < m_SeparationsOut; ++i) + { + m_OutputCurves[i].Eval((double)tmpColorOut[i], tmpIC); + tmpColorOut[i] = (unsigned short)tmpIC; + } + //Normalize to Lab Space C_RGB_XYZ_Lab tmpLabOut; uint16_t int16ColorOut[3]; diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.h b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.h index cd3f8131a..963b63deb 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.h +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.h @@ -3,6 +3,7 @@ #include <stdlib.h> #include "NDInterpUtils.h" +#include "Interp.h" class ColorTransf { public: @@ -14,6 +15,8 @@ public: int GetMSBShift() { return(m_MSBShift); }; void evalLab2InkP(double *ColorIn, double *&ColorOut, int &GamutRegion); void evalInkP2Lab(double *ColorIn, double *&ColorOut, int &GamutRegion); + void evalInCurve(double *ColorIn, double *&ColorOut); + void evalOutCurve(double *ColorIn, double *&ColorOut); // int evalCMY2RGB(double *ColorIn, double *ColorOut); void InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize); private: @@ -21,17 +24,29 @@ private: int m_SeparationsIn; int m_SeparationsOut; int m_nGridPoints; + int m_num_input_table_entries; + int m_num_output_table_entries; double *m_GamutLimitsNlperCM; int m_NGamutRegions; NDInterpUtils m_InterpColor; + Interp *m_InputCurves; + Interp *m_OutputCurves; + unsigned short *m_DataBuffer; + unsigned char *m_ByteBuffer; void SetNGridpoints(int nGridPoints) { m_nGridPoints = nGridPoints; }; void SetSeparationsIn(int SeparationsIn) { m_SeparationsIn = SeparationsIn; }; void SetSeparationsOut(int SeparationsOut) { m_SeparationsOut = SeparationsOut; }; void SetMSBShift(int MSBShift) { m_MSBShift = MSBShift; }; - void SetNGamutRegions(int NGamutRegions) {m_NGamutRegions = NGamutRegions;}; + void Set_NumInputTableEntries(int num_input_table_entries) { + m_num_input_table_entries = num_input_table_entries; + }; + void Set_NumOutputTableEntries(int num_output_table_entries) { + m_num_output_table_entries = num_output_table_entries; + }; + //void SetNGamutRegions(int NGamutRegions) {m_NGamutRegions = NGamutRegions;}; void SetGamutLimitsNlperCM(double *GamutLimitsNlperCM); }; diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.cpp new file mode 100644 index 000000000..e6722a582 --- /dev/null +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.cpp @@ -0,0 +1,154 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +/*#define _CRTDBG_MAP_ALLOC +#include <stdlib.h> +#include <crtdbg.h> +#include <cstdlib> + +#ifdef _DEBUG +#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) +// Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the +// allocations to be of _CLIENT_BLOCK type +#else +#define DBG_NEW new +#endif */ + +#include "Curves.h" +#include <iostream> +#include <stdio.h> +#include "NumConversions.h" +#include "C_RGB_XYZ_Lab.h" + +using namespace std; + +Curves::Curves() : + m_prec(0), m_nChannels(0), + m_nEntries(0), m_InterpCurves(NULL) +{ + +} + +Curves::~Curves() +{ + if (m_InterpCurves != NULL) + { + delete[] m_InterpCurves; + m_InterpCurves = NULL; + } + +} + +void Curves::InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize) +{ + // 0-3 prec + //4-7 reserved, must be 0 + // 8-9 number of channels, uint8 + // 10-11 number of entry points, uint16 + // 12-n data + + if (colorTransformFileSize < 32) + { + throw std::exception("Init Curves, invalid size"); + } + + // Check for signature + unsigned char *buffer = colorTransformBuffer; + if (buffer == NULL) + { + throw std::exception("Memory Error, ColorTransf::InitData"); + } + NumConversions Conv; + + int bytesread = 0; + int tmpB = Conv.ByteToInt(buffer, 0); + bytesread += 4; + + int n = sizeof((char*)&tmpB); + //char *tmpC = DBG_NEW char[n] ; + char *tmpC = new char[n]; + Conv.getchar(tmpB, n, tmpC); + char *Curvetype = new char[n + 1]; + //char *luttype = DBG_NEW char[n + 1]; + strncpy_s(Curvetype, n + 1, tmpC, n); + int TablePrecision; + if (strncmp(Curvetype, "prc1", n) == 0) + TablePrecision = 1; + else if (strncmp(Curvetype, "prc2", n) == 0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in Color Tables"); + return; + } + if (Curvetype != NULL) + { + delete[] Curvetype; + Curvetype = NULL; + } + if (tmpC != NULL) + { + delete[] tmpC; + tmpC = NULL; + } + + // Skip past reserved padding bytes + bytesread += 4; + + uint8_t num_channels = buffer[bytesread]; + Set_nChannels((int)num_channels); //Numer of channels + bytesread += 1; + unsigned short nEntries = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + Set_nEntries((int)nEntries); + m_InterpCurves = new Interp[m_nChannels]; + + double *xIn = new double[m_nEntries]; + double *yIn = new double[m_nEntries]; + //read Input tables + if (TablePrecision == 1) + { + double deltax = 255.0 / (m_nEntries - 1); + for (int i = 0; i < m_nEntries; ++i) + xIn[i] = deltax *(double)i; + + for (int i = 0; i < m_nChannels; ++i) + { + for (int j = 0; j <m_nEntries; ++j) + { + yIn[j] = (double)(buffer[bytesread]); + bytesread += 1; + } + m_InterpCurves[i].Init(xIn, yIn, m_nEntries); + } + } + else + { + double deltax = (double)65535.0 / (m_nEntries - 1); + for (int i = 0; i < nEntries; ++i) + xIn[i] = deltax * (double)i; + for (int i = 0; i < m_nChannels; ++i) + { + for (int j = 0; j < nEntries; ++j) + { + yIn[j] = (double)(Conv.ByteToShort(buffer, bytesread)); + bytesread += 2; + } + m_InterpCurves[i].Init(xIn, yIn, nEntries); + } + } + if (xIn != NULL) + { + delete[] xIn; + xIn = NULL; + } + if (yIn != NULL) + { + delete[] yIn; + yIn = NULL; + } + + +} + diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.h b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.h new file mode 100644 index 000000000..748f5a597 --- /dev/null +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.h @@ -0,0 +1,23 @@ +#ifndef _Curves_H_ +#define _Curves_H_ + +#include <stdlib.h> +#include "C_RGB_XYZ_Lab.h" +#include "Interp.h" +class Curves { +public: + Curves(); + ~Curves(); + int Get_nChannels() { return(m_nChannels); }; + int Get_nEntries() { return(m_nEntries); }; + void InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize); + Interp *m_InterpCurves; +private: + int m_prec; + int m_nChannels; + int m_nEntries; + void Set_nChannels(int nChannels) { m_nChannels = nChannels; }; + void Set_nEntries(int nEntries) { m_nEntries = nEntries; }; +}; + +#endif diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp index 802a63b81..ba66ca114 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp @@ -30,7 +30,7 @@ Interp::Interp(const Interp &rhs):m_xValues(NULL), m_yValues(NULL), m_length(0) Interp::~Interp() { - /*if (m_xValues != NULL) + if (m_xValues != NULL) { delete[] m_xValues; m_xValues = NULL; @@ -39,7 +39,7 @@ Interp::~Interp() { delete[] m_yValues; m_yValues = NULL; - }*/ + } } void Interp::Init(double *xValues, double *yValues, int nlength) @@ -47,10 +47,10 @@ void Interp::Init(double *xValues, double *yValues, int nlength) m_length = nlength; if (m_xValues == NULL) //m_xValues = DBG_NEW double(m_length); - m_xValues = new double(m_length); + m_xValues = new double[m_length]; if (m_yValues == NULL) //m_yValues = DBG_NEW double(m_length); - m_yValues = new double(m_length); + m_yValues = new double[m_length]; for (int i=0; i<m_length; ++i) { diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.cpp index dbaeb85b6..dc9c013b1 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.cpp +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.cpp @@ -43,6 +43,21 @@ extern "C" //m_tmpResult = DBG_NEW int[m_nSeparationsOut]; } + void NDInterpUtils::InitData(unsigned char *DataBuffer, int SeparationsIn, int SeparationsOut, int nGridPoints, int MSBShift) + { + SetMSBShift(MSBShift); + SetNDData((unsigned short *)DataBuffer); + SetSeparationsIn(SeparationsIn); + SetSeparationsOut(SeparationsOut); + SetNGridpoints(nGridPoints); + SetSubCubeSize(); + SetLastCubeComp(); + m_Point = new unsigned short[m_nSeparationsIn + 1]; + m_tmpResult = new int[m_nSeparationsOut]; + //m_Point = DBG_NEW unsigned short[m_nSeparationsIn + 1]; + //m_tmpResult = DBG_NEW int[m_nSeparationsOut]; + } + NDInterpUtils::~NDInterpUtils() { if (m_Point != NULL) diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.h b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.h index 2466d9d61..992de082c 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.h +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.h @@ -24,6 +24,7 @@ class NDInterpUtils { public: NDInterpUtils(); /*__declspec(dllexport) */void InitData(unsigned short *DataBuffer, int SeparationsIn, int SeparationsOut, int nGridPoints, int MSBShift); + void InitData(unsigned char *DataBuffer, int SeparationsIn, int SeparationsOut, int nGridPoints, int MSBShift); ~NDInterpUtils(); void ColorMap4(const unsigned short * ValIn, double * ValOut); void ColorMap3(const unsigned short * ValIn, double * ValOut); |
