aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Native
diff options
context:
space:
mode:
authorMirta <mirta@twine-s.com>2019-08-08 15:23:50 +0300
committerMirta <mirta@twine-s.com>2019-08-08 15:23:50 +0300
commitb112abfecb622ac7fcb7c161b03f450fbb58b00a (patch)
treec526a43e72192a0c009e7d32fb085dccb899b60c /Software/Visual_Studio/Native
parentdf1ddcd6af0db2c912171e318ae4c967cc17f112 (diff)
downloadTango-b112abfecb622ac7fcb7c161b03f450fbb58b00a.tar.gz
Tango-b112abfecb622ac7fcb7c161b03f450fbb58b00a.zip
ColorLib 2 gamut regions!
Diffstat (limited to 'Software/Visual_Studio/Native')
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.cpp1449
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/ColorConverter.h43
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Exports.cpp17
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj2
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj.filters20
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.cpp23
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/CalibData.h5
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.cpp24
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorConvert.h1
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.cpp271
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/ColorTransf.h17
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.cpp154
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/Curves.h23
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp8
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.cpp15
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/NDInterpUtils.h1
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);