From a2c128c1c00ac74c9c1835a8581aa8f2c4123bde Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 20 Sep 2022 13:22:26 +0300 Subject: Modified all uses of RML to include GBD and LUB. --- .../Tango.MachineStudio.Developer.csproj | 2 +- .../ViewModels/MainViewVM.cs | 2 +- .../ViewModels/ColorCalibrationViewVM.cs | 3 +- .../Tango.MachineStudio.RML/Models/CctModel.cs | 16 - .../Models/DataFileModel.cs | 16 + .../Tango.MachineStudio.RML.csproj | 2 +- .../ViewModels/ColorConversionViewVM.cs | 32 +- .../ViewModels/MainViewVM.cs | 321 +++++++++++++++++++-- .../Tango.MachineStudio.RML/Views/RmlView.xaml | 70 ++++- 9 files changed, 409 insertions(+), 55 deletions(-) delete mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/CctModel.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/DataFileModel.cs (limited to 'Software/Visual_Studio/MachineStudio/Modules') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Tango.MachineStudio.Developer.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Tango.MachineStudio.Developer.csproj index 3853e6763..b7a254a03 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Tango.MachineStudio.Developer.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Tango.MachineStudio.Developer.csproj @@ -393,7 +393,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index f13794c35..cb16c99e7 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -1639,7 +1639,7 @@ namespace Tango.MachineStudio.Developer.ViewModels { LogManager.Log("Invalidating liquid factors, process parameters and process group history..."); - _selectedRML = new RmlBuilder(_activeJobDbContext).Set(SelectedRML).WithAllParametersGroup().WithCAT(SelectedMachine.Guid).WithCctCache(_cctCache).WithCCT().WithLiquidFactors().WithSpools().Build(); + _selectedRML = new RmlBuilder(_activeJobDbContext).Set(SelectedRML).WithAllParametersGroup().WithCAT(SelectedMachine.Guid).WithCctCache(_cctCache).WithCCT().WithGbdAndLub().WithLiquidFactors().WithSpools().Build(); _selectedRMLBeforeLiquidFactorsSaves = RmlDTO.FromObservable(_selectedRML); diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/ColorCalibrationViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/ColorCalibrationViewVM.cs index feee2637a..edfc77274 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/ColorCalibrationViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/ViewModels/ColorCalibrationViewVM.cs @@ -122,6 +122,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels .WithActiveParametersGroup() .WithCAT(Machine.Guid) .WithCCT() + .WithGbdAndLub() .WithLiquidFactors().Build(); LiquidTypesRmls = SelectedRML.LiquidTypesRmls; @@ -165,7 +166,7 @@ namespace Tango.MachineStudio.MachineDesigner.ViewModels ColorConversionViewVM = new ColorConversionViewVM(_notification) { RML = SelectedRML, - CCT = new CctModel() + CCT = new DataFileModel() { Data = SelectedRML.Cct?.Data, }, diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/CctModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/CctModel.cs deleted file mode 100644 index 9079b8fc6..000000000 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/CctModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.MachineStudio.RML.Models -{ - public class CctModel - { - public String Guid { get; set; } - public String FileName { get; set; } - public bool IsNew { get; set; } - public byte[] Data { get; set; } - } -} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/DataFileModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/DataFileModel.cs new file mode 100644 index 000000000..8f8eb58d9 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Models/DataFileModel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.RML.Models +{ + public class DataFileModel + { + public String Guid { get; set; } + public String FileName { get; set; } + public bool IsNew { get; set; } + public byte[] Data { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj index c8b778cc7..4ba97e35b 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Tango.MachineStudio.RML.csproj @@ -82,7 +82,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs index 92d9056bb..9c2c957ab 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs @@ -135,8 +135,8 @@ namespace Tango.MachineStudio.RML.ViewModels set { _liquidsCalibrationData = value; RaisePropertyChangedAuto(); } } - private CctModel _cct; - public CctModel CCT + private DataFileModel _cct; + public DataFileModel CCT { get { return _cct; } set @@ -147,6 +147,30 @@ namespace Tango.MachineStudio.RML.ViewModels } } + private DataFileModel _gbd; + public DataFileModel GBD + { + get { return _gbd; } + set + { + _gbd = value; + RaisePropertyChangedAuto(); + InvalidateRelayCommands(); + } + } + + private DataFileModel _lub; + public DataFileModel LUB + { + get { return _lub; } + set + { + _lub = value; + RaisePropertyChangedAuto(); + InvalidateRelayCommands(); + } + } + private RgbVM _sourceColor; /// /// Gets or sets the color of the source. @@ -203,6 +227,8 @@ namespace Tango.MachineStudio.RML.ViewModels //input.DeltaChroma = DeltaChroma; //input.DeltaL = DeltaL; input.ForwardData = ByteString.CopyFrom(CCT.Data); + input.GbdData = ByteString.CopyFrom(GBD.Data); + input.LubData = ByteString.CopyFrom(LUB.Data); input.InputCoordinates = new InputCoordinates(); input.InputCoordinates.Red = (int)SourceColor.Red; @@ -346,6 +372,8 @@ namespace Tango.MachineStudio.RML.ViewModels ConversionInput input = new ConversionInput(); input.ColorSpace = PMR.ColorLab.ColorSpace.Volume; input.ForwardData = ByteString.CopyFrom(CCT.Data); + input.GbdData = ByteString.CopyFrom(GBD.Data); + input.LubData = ByteString.CopyFrom(LUB.Data); input.GenerateHive = false; input.InputCoordinates = new InputCoordinates(); diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs index deb162687..bb6a3c467 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs @@ -152,20 +152,49 @@ namespace Tango.MachineStudio.RML.ViewModels set { _activeProcessParametersTableView = value; RaisePropertyChangedAuto(); } } - private ObservableCollection _ccts; - public ObservableCollection CCTS + private ObservableCollection _ccts; + public ObservableCollection CCTS { get { return _ccts; } set { _ccts = value; RaisePropertyChangedAuto(); } } - private CctModel _selectedCCT; - public CctModel SelectedCCT + private DataFileModel _selectedCCT; + public DataFileModel SelectedCCT { get { return _selectedCCT; } set { _selectedCCT = value; RaisePropertyChangedAuto(); OnSelectedCCTChanged(); InvalidateRelayCommands(); } } + private ObservableCollection _gbds; + public ObservableCollection GBDS + { + get { return _gbds; } + set { _gbds = value; RaisePropertyChangedAuto(); } + } + + private DataFileModel _selectedGBD; + public DataFileModel SelectedGBD + { + get { return _selectedGBD; } + set { _selectedGBD = value; RaisePropertyChangedAuto(); OnSelectedGBDChanged(); InvalidateRelayCommands(); } + } + + + private ObservableCollection _lubs; + public ObservableCollection LUBS + { + get { return _lubs; } + set { _lubs = value; RaisePropertyChangedAuto(); } + } + + private DataFileModel _selectedLUB; + public DataFileModel SelectedLUB + { + get { return _selectedLUB; } + set { _selectedLUB = value; RaisePropertyChangedAuto(); OnSelectedLUBChanged(); InvalidateRelayCommands(); } + } + private ColorConversionViewVM _colorConversionViewVM; public ColorConversionViewVM ColorConversionViewVM { @@ -227,6 +256,14 @@ namespace Tango.MachineStudio.RML.ViewModels public RelayCommand ExportForwardDataCommand { get; set; } + public RelayCommand ImportGBDCommand { get; set; } + + public RelayCommand ExportGBDCommand { get; set; } + + public RelayCommand ImportLUBCommand { get; set; } + + public RelayCommand ExportLUBCommand { get; set; } + public RelayCommand AddProcessParametersTableCommand { get; set; } public RelayCommand RemoveProcessParametersTableCommand { get; set; } @@ -283,6 +320,14 @@ namespace Tango.MachineStudio.RML.ViewModels ExportForwardDataCommand = new RelayCommand(ExportCCTData, () => ActiveRML != null && SelectedCCT != null && IsFree); + ImportGBDCommand = new RelayCommand(ImportGBDData, () => ActiveRML != null && IsFree); + + ExportGBDCommand = new RelayCommand(ExportGBDData, () => ActiveRML != null && SelectedGBD != null && IsFree); + + ImportLUBCommand = new RelayCommand(ImportLUBData, () => ActiveRML != null && IsFree); + + ExportLUBCommand = new RelayCommand(ExportLUBData, () => ActiveRML != null && SelectedLUB != null && IsFree); + ExportRMLFileCommand = new RelayCommand(ExportRmlFile, () => SelectedRML != null && IsFree); ImportRMLFileCommand = new RelayCommand(ImportRmlFile, () => IsFree); @@ -363,7 +408,7 @@ namespace Tango.MachineStudio.RML.ViewModels _active_context = ObservablesContext.CreateDefault(); CCTS = _active_context.Ccts - .Select(x => new CctModel() + .Select(x => new DataFileModel() { Guid = x.Guid, FileName = x.FileName, @@ -372,6 +417,22 @@ namespace Tango.MachineStudio.RML.ViewModels CCTS.Where(x => String.IsNullOrWhiteSpace(x.FileName)).ToList().ForEach(x => x.FileName = x.Guid); + GBDS = _active_context.Gbds + .Select(x => new DataFileModel() + { + Guid = x.Guid, + FileName = x.FileName, + + }).ToObservableCollection(); + + LUBS = _active_context.Lubs + .Select(x => new DataFileModel() + { + Guid = x.Guid, + FileName = x.FileName, + + }).ToObservableCollection(); + LoadRmlProperties(); ActiveRML = await new RmlBuilder(_active_context) @@ -379,12 +440,26 @@ namespace Tango.MachineStudio.RML.ViewModels .WithActiveParametersGroup() .WithLiquidFactors() .WithCCT() + .WithGbdAndLub() .WithSpools() .BuildAsync(); if (ActiveRML.Cct != null) { - SelectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid); + _selectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid); + RaisePropertyChanged(nameof(SelectedCCT)); + } + + if (ActiveRML.Gbd != null) + { + _selectedGBD = GBDS.SingleOrDefault(x => x.Guid == ActiveRML.Gbd.Guid); + RaisePropertyChanged(nameof(SelectedGBD)); + } + + if (ActiveRML.Lub != null) + { + _selectedLUB = LUBS.SingleOrDefault(x => x.Guid == ActiveRML.Lub.Guid); + RaisePropertyChanged(nameof(SelectedLUB)); } if (ActiveRML.ProcessParametersTablesGroups.ToList().Count == 0) @@ -445,6 +520,8 @@ namespace Tango.MachineStudio.RML.ViewModels { RML = ActiveRML, CCT = SelectedCCT, + GBD = SelectedGBD, + LUB = SelectedLUB, LiquidsCalibrationData = CalibrationDataViewVM.LiquidsCalibrationData, LiquidTypesRmls = LiquidTypesRmls, }; @@ -475,7 +552,7 @@ namespace Tango.MachineStudio.RML.ViewModels } } - private async void OnSelectedCCTChanged() + private async Task OnSelectedCCTChanged() { if (SelectedCCT != null && !SelectedCCT.IsNew) { @@ -496,6 +573,48 @@ namespace Tango.MachineStudio.RML.ViewModels } } + private async Task OnSelectedGBDChanged() + { + if (SelectedGBD != null && !SelectedGBD.IsNew) + { + using (_notification.PushTaskItem("Loading GBD data...")) + { + IsFree = false; + + var gbd = await _active_context.Gbds.SingleOrDefaultAsync(x => x.Guid == SelectedGBD.Guid); + + if (gbd != null) + { + SelectedGBD.Data = gbd.Data; + ColorConversionViewVM.GBD = SelectedGBD; + } + + IsFree = true; + } + } + } + + private async Task OnSelectedLUBChanged() + { + if (SelectedLUB != null && !SelectedLUB.IsNew) + { + using (_notification.PushTaskItem("Loading LUB data...")) + { + IsFree = false; + + var lub = await _active_context.Lubs.SingleOrDefaultAsync(x => x.Guid == SelectedLUB.Guid); + + if (lub != null) + { + SelectedLUB.Data = lub.Data; + ColorConversionViewVM.LUB = SelectedLUB; + } + + IsFree = true; + } + } + } + private void LoadRmlProperties() { Materials = _active_context.MediaMaterials.ToObservableCollection(); @@ -895,6 +1014,40 @@ namespace Tango.MachineStudio.RML.ViewModels } } + if (SelectedGBD != null) + { + if (SelectedGBD.IsNew) + { + Gbd gbd = new Gbd(); + gbd.Guid = SelectedGBD.Guid; + gbd.FileName = SelectedGBD.FileName; + gbd.Data = SelectedGBD.Data; + ActiveRML.Gbd = gbd; + SelectedGBD.IsNew = false; + } + else + { + ActiveRML.GbdGuid = SelectedGBD.Guid; + } + } + + if (SelectedLUB != null) + { + if (SelectedLUB.IsNew) + { + Lub lub = new Lub(); + lub.Guid = SelectedLUB.Guid; + lub.FileName = SelectedLUB.FileName; + lub.Data = SelectedLUB.Data; + ActiveRML.Lub = lub; + SelectedLUB.IsNew = false; + } + else + { + ActiveRML.LubGuid = SelectedLUB.Guid; + } + } + var rmlAfter = RmlDTO.FromObservable(ActiveRML); await _active_context.SaveChangesAsync(); @@ -1016,7 +1169,7 @@ namespace Tango.MachineStudio.RML.ViewModels input.InputCoordinates.B = lab.B; input.ColorSpace = PMR.ColorLab.ColorSpace.Lab; var output = converter.Convert(input, ActiveRML.ColorConversionVersion); - + BatchConversionCsvModelOut result = new BatchConversionCsvModelOut(); result.Index = lab.Index; @@ -1100,7 +1253,7 @@ namespace Tango.MachineStudio.RML.ViewModels item.Volume = result.LightCyan; break; case PMR.ColorLab.LiquidType.LightMagenta: - item.Volume= result.LightMagenta; + item.Volume = result.LightMagenta; break; case PMR.ColorLab.LiquidType.LightYellow: item.Volume = result.LightYellow; @@ -1156,7 +1309,7 @@ namespace Tango.MachineStudio.RML.ViewModels private void ImportCCTData() { - String file = GetCCTFileOpen(); + String file = GetDataFileOpen("Select color adjustment file", "Color Conversion Table|*.cct"); if (file != null) { if (CCTS.ToList().Exists(x => x.FileName == Path.GetFileName(file))) @@ -1165,7 +1318,7 @@ namespace Tango.MachineStudio.RML.ViewModels return; } - CctModel cctModel = new CctModel(); + DataFileModel cctModel = new DataFileModel(); cctModel.Guid = Guid.NewGuid().ToString(); cctModel.IsNew = true; @@ -1183,7 +1336,7 @@ namespace Tango.MachineStudio.RML.ViewModels { if (SelectedCCT != null) { - String file = GetCCTFileSave(ActiveRML.Cct.FileName); + String file = GetDataFileSave("Select color adjustment file", "Color Conversion Table|*.cct", ActiveRML.Cct.FileName); if (file != null) { using (_notification.PushTaskItem("Exporting CCT file...")) @@ -1220,11 +1373,143 @@ namespace Tango.MachineStudio.RML.ViewModels } } - private String GetCCTFileOpen() + private void ExportLUBData() + { + if (SelectedLUB != null) + { + String file = GetDataFileSave("Select lubrication transformation file", "Lubrication Transformation File|*.lub", ActiveRML.Lub.FileName); + if (file != null) + { + using (_notification.PushTaskItem("Exporting LUB file...")) + { + try + { + IsFree = false; + + if (SelectedLUB.IsNew) + { + File.WriteAllBytes(file, SelectedLUB.Data); + } + else + { + var lub = _active_context.Lubs.SingleOrDefault(x => x.Guid == SelectedLUB.Guid); + + if (lub != null) + { + File.WriteAllBytes(file, lub.Data); + } + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error exporting LUB file."); + _notification.ShowError($"An error occurred while trying to export the LUB file.\n{ex.Message}"); + } + finally + { + IsFree = true; + } + } + } + } + } + + private void ImportLUBData() + { + String file = GetDataFileOpen("Select lubrication transformation file", "Lubrication Transformation File|*.lub"); + if (file != null) + { + if (LUBS.ToList().Exists(x => x.FileName == Path.GetFileName(file))) + { + _notification.ShowError("The selected LUB file already exists on the database. Please select the LUB file from the dropdown box."); + return; + } + + DataFileModel lubModel = new DataFileModel(); + lubModel.Guid = Guid.NewGuid().ToString(); + lubModel.IsNew = true; + + lubModel.FileName = Path.GetFileName(file); + lubModel.Data = File.ReadAllBytes(file); + + LUBS.Insert(0, lubModel); + SelectedLUB = lubModel; + + ColorConversionViewVM.LUB = SelectedLUB; + } + } + + private void ExportGBDData() + { + if (SelectedGBD != null) + { + String file = GetDataFileSave("Select gamut boundary descriptor file", "Gamut Boundary Descriptor File|*.gbd", ActiveRML.Gbd.FileName); + if (file != null) + { + using (_notification.PushTaskItem("Exporting GBD file...")) + { + try + { + IsFree = false; + + if (SelectedGBD.IsNew) + { + File.WriteAllBytes(file, SelectedGBD.Data); + } + else + { + var gbd = _active_context.Gbds.SingleOrDefault(x => x.Guid == SelectedGBD.Guid); + + if (gbd != null) + { + File.WriteAllBytes(file, gbd.Data); + } + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error exporting GBD file."); + _notification.ShowError($"An error occurred while trying to export the GBD file.\n{ex.Message}"); + } + finally + { + IsFree = true; + } + } + } + } + } + + private void ImportGBDData() + { + String file = GetDataFileOpen("Select gamut boundary description file", "Gamut Boundary Description File|*.gbd"); + if (file != null) + { + if (GBDS.ToList().Exists(x => x.FileName == Path.GetFileName(file))) + { + _notification.ShowError("The selected GBD file already exists on the database. Please select the GBD file from the dropdown box."); + return; + } + + DataFileModel gbdModel = new DataFileModel(); + gbdModel.Guid = Guid.NewGuid().ToString(); + gbdModel.IsNew = true; + + gbdModel.FileName = Path.GetFileName(file); + gbdModel.Data = File.ReadAllBytes(file); + + GBDS.Insert(0, gbdModel); + SelectedGBD = gbdModel; + + ColorConversionViewVM.GBD = SelectedGBD; + } + } + + private String GetDataFileOpen(String title, String filter) { OpenFileDialog dlg = new OpenFileDialog(); - dlg.Title = "Select color adjustment file"; - dlg.Filter = "Color Conversion Table|*.cct"; + dlg.Title = title; + dlg.Filter = filter; if (dlg.ShowDialogCenter()) { return dlg.FileName; @@ -1233,11 +1518,11 @@ namespace Tango.MachineStudio.RML.ViewModels return null; } - private String GetCCTFileSave(String fileName) + private String GetDataFileSave(String title, String filter, String fileName) { SaveFileDialog dlg = new SaveFileDialog(); - dlg.Title = "Select color adjustment file"; - dlg.Filter = "Color Conversion Table|*.cct"; + dlg.Title = title; + dlg.Filter = filter; dlg.FileName = fileName; dlg.DefaultExt = ".cct"; if (dlg.ShowDialogCenter()) diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml index a9b943525..e2ef8b229 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml @@ -206,21 +206,61 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.3.1 From 2ebd882d708fe4d78d985fcd5d318d8f1794eca9 Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 20 Sep 2022 13:57:22 +0300 Subject: Added support for ColorLib 6. --- .../ColorLib/Tango.ColorLib_v6/ColorCalibrator.cpp | 719 +++ .../ColorLib/Tango.ColorLib_v6/ColorCalibrator.h | 67 + .../ColorLib/Tango.ColorLib_v6/ColorConverter.cpp | 5800 ++++++++++++++++++++ .../ColorLib/Tango.ColorLib_v6/ColorConverter.h | 228 + .../Tango.ColorLib_v6/ColorConverterCLipRGB.cpp | 3219 +++++++++++ .../ColorLib/Tango.ColorLib_v6/Exports.cpp | 68 + .../ColorLib/Tango.ColorLib_v6/Exports.h | 6 + .../ColorLib/Tango.ColorLib_v6/ForwardModel.cpp | 217 + .../ColorLib/Tango.ColorLib_v6/ForwardModel.h | 32 + .../PMR/ColorLab/CalibrationData.pb-c.c | 105 + .../PMR/ColorLab/CalibrationData.pb-c.h | 76 + .../PMR/ColorLab/CalibrationInput.pb-c.c | 145 + .../PMR/ColorLab/CalibrationInput.pb-c.h | 82 + .../PMR/ColorLab/CalibrationMeasurement.pb-c.c | 131 + .../PMR/ColorLab/CalibrationMeasurement.pb-c.h | 78 + .../PMR/ColorLab/CalibrationOutput.pb-c.c | 119 + .../PMR/ColorLab/CalibrationOutput.pb-c.h | 75 + .../PMR/ColorLab/CalibrationPoint.pb-c.c | 105 + .../PMR/ColorLab/CalibrationPoint.pb-c.h | 74 + .../PMR/ColorLab/ColorSpace.pb-c.c | 43 + .../PMR/ColorLab/ColorSpace.pb-c.h | 46 + .../PMR/ColorLab/ConversionInput.pb-c.c | 287 + .../PMR/ColorLab/ConversionInput.pb-c.h | 104 + .../PMR/ColorLab/ConversionOutput.pb-c.c | 158 + .../PMR/ColorLab/ConversionOutput.pb-c.h | 81 + .../PMR/ColorLab/GradientConversionInput.pb-c.c | 209 + .../PMR/ColorLab/GradientConversionInput.pb-c.h | 93 + .../PMR/ColorLab/GradientConversionOutput.pb-c.c | 118 + .../PMR/ColorLab/GradientConversionOutput.pb-c.h | 76 + .../PMR/ColorLab/GradientInputStop.pb-c.c | 248 + .../PMR/ColorLab/GradientInputStop.pb-c.h | 98 + .../PMR/ColorLab/GradientOutputStop.pb-c.c | 118 + .../PMR/ColorLab/GradientOutputStop.pb-c.h | 77 + .../PMR/ColorLab/InputCoordinates.pb-c.c | 248 + .../PMR/ColorLab/InputCoordinates.pb-c.h | 97 + .../PMR/ColorLab/InputLiquid.pb-c.c | 131 + .../PMR/ColorLab/InputLiquid.pb-c.h | 79 + .../PMR/ColorLab/LinearizationInput.pb-c.c | 144 + .../PMR/ColorLab/LinearizationInput.pb-c.h | 82 + .../PMR/ColorLab/LinearizationMeasurement.pb-c.c | 131 + .../PMR/ColorLab/LinearizationMeasurement.pb-c.h | 78 + .../PMR/ColorLab/LinearizationOutput.pb-c.c | 119 + .../PMR/ColorLab/LinearizationOutput.pb-c.h | 75 + .../PMR/ColorLab/LiquidType.pb-c.c | 53 + .../PMR/ColorLab/LiquidType.pb-c.h | 51 + .../PMR/ColorLab/LiquidVolume.pb-c.c | 105 + .../PMR/ColorLab/LiquidVolume.pb-c.h | 75 + .../PMR/ColorLab/OutOfGamutInput.pb-c.c | 196 + .../PMR/ColorLab/OutOfGamutInput.pb-c.h | 90 + .../PMR/ColorLab/OutOfGamutOutput.pb-c.c | 118 + .../PMR/ColorLab/OutOfGamutOutput.pb-c.h | 75 + .../PMR/ColorLab/OutputCoordinates.pb-c.c | 183 + .../PMR/ColorLab/OutputCoordinates.pb-c.h | 87 + .../PMR/ColorLab/OutputLiquid.pb-c.c | 106 + .../PMR/ColorLab/OutputLiquid.pb-c.h | 75 + .../PMR/ColorLab/ProcessRange.pb-c.c | 105 + .../PMR/ColorLab/ProcessRange.pb-c.h | 74 + .../ColorLab/RecommendedProcessTableInput.pb-c.c | 209 + .../ColorLab/RecommendedProcessTableInput.pb-c.h | 93 + .../ColorLab/RecommendedProcessTableOutput.pb-c.c | 118 + .../ColorLab/RecommendedProcessTableOutput.pb-c.h | 75 + .../ColorLib/Tango.ColorLib_v6/ReadMe.txt | 48 + .../Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj | 270 + .../Tango.ColorLib_v6.vcxproj.filters | 318 ++ .../ColorLib/Tango.ColorLib_v6/Utils/CT_Header.cpp | 114 + .../ColorLib/Tango.ColorLib_v6/Utils/CT_Header.h | 63 + .../Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.cpp | 188 + .../Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.h | 48 + .../ColorLib/Tango.ColorLib_v6/Utils/CalibData.cpp | 90 + .../ColorLib/Tango.ColorLib_v6/Utils/CalibData.h | 33 + .../Tango.ColorLib_v6/Utils/ColorConvert.cpp | 1254 +++++ .../Tango.ColorLib_v6/Utils/ColorConvert.h | 140 + .../Tango.ColorLib_v6/Utils/ColorTable.cpp | 769 +++ .../ColorLib/Tango.ColorLib_v6/Utils/ColorTable.h | 94 + .../Tango.ColorLib_v6/Utils/ColorTransf.cpp | 577 ++ .../ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.h | 55 + .../ColorLib/Tango.ColorLib_v6/Utils/Curves.cpp | 155 + .../ColorLib/Tango.ColorLib_v6/Utils/Curves.h | 24 + .../ColorLib/Tango.ColorLib_v6/Utils/GBD.cpp | 340 ++ .../ColorLib/Tango.ColorLib_v6/Utils/GBD.h | 38 + .../ColorLib/Tango.ColorLib_v6/Utils/Gradient.cpp | 45 + .../ColorLib/Tango.ColorLib_v6/Utils/Gradient.h | 39 + .../ColorLib/Tango.ColorLib_v6/Utils/Interp.cpp | 127 + .../ColorLib/Tango.ColorLib_v6/Utils/Interp.h | 24 + .../Tango.ColorLib_v6/Utils/LULinearSolver.cpp | 129 + .../Tango.ColorLib_v6/Utils/LULinearSolver.h | 13 + .../ColorLib/Tango.ColorLib_v6/Utils/LevMar.cpp | 457 ++ .../ColorLib/Tango.ColorLib_v6/Utils/LevMar.h | 66 + .../Tango.ColorLib_v6/Utils/NDInterpUtils.cpp | 333 ++ .../Tango.ColorLib_v6/Utils/NDInterpUtils.h | 60 + .../Tango.ColorLib_v6/Utils/NumConversions.cpp | 85 + .../Tango.ColorLib_v6/Utils/NumConversions.h | 18 + .../Tango.ColorLib_v6/Utils/ObjectiveFunction.cpp | 142 + .../Tango.ColorLib_v6/Utils/ObjectiveFunction.h | 49 + .../Tango.ColorLib_v6/protobuf-c/protobuf-c.c | 3642 ++++++++++++ .../Tango.ColorLib_v6/protobuf-c/protobuf-c.h | 1106 ++++ .../ColorLib/Tango.ColorLib_v6/targetver.h | 8 + .../ViewModels/ColorConversionViewVM.cs | 9 +- .../ViewModels/MainViewVM.cs | 45 +- .../Tango.MachineStudio.RML/Views/RmlView.xaml | 2 +- .../Tango.MachineStudio.UI.csproj | 7 + .../PPC/Tango.PPC.UI/Tango.PPC.UI.csproj | 7 + Software/Visual_Studio/Tango.sln | 29 +- 103 files changed, 27203 insertions(+), 31 deletions(-) create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverterCLipRGB.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ReadMe.txt create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj.filters create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Curves.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Curves.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NumConversions.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NumConversions.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/targetver.h (limited to 'Software/Visual_Studio/MachineStudio/Modules') diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.cpp new file mode 100644 index 000000000..9234a9ed7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.cpp @@ -0,0 +1,719 @@ +#include "ColorCalibrator.h" +#include "CalibrationInput.pb-c.h" +#include "CalibrationOutput.pb-c.h" +#include "CalibrationMeasurement.pb-c.h" +#include "LinearizationInput.pb-c.h" +#include "LinearizationOutput.pb-c.h" +#include "LinearizationMeasurement.pb-c.h" +#include "Interp.h" + +#include +#include +#include +#include +using namespace std; + +#ifdef MEMORY_TEST + #define _CRTDBG_MAP_ALLOC + #include + #include + #include +#endif + +//#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 + +#define MDRThr 1.0 +#define epsTol 0.05 +#define PI 4*atan(1.0) +#define dEThr 1.0 + + +Tango::ColorLib::ColorCalibrator::ColorCalibrator(): m_nsize(0), m_nlcm(NULL), m_LabData(NULL), m_inkChannel(0), m_targetVal(NULL), m_CalIndex(0), m_inkpercentage(NULL) +{ +#ifdef MEMORY_TEST + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); +#endif // MEMORY_TEST +} + + +Tango::ColorLib::ColorCalibrator::~ColorCalibrator() +{ + ClearData(); +#ifdef MEMORY_TEST + _CrtDumpMemoryLeaks(); +#endif // MEMORY_TEST +} + +void Tango::ColorLib::ColorCalibrator::ClearData() +{ + if (m_LabData != NULL) + { + for (int i = 0; i < m_nsize; ++i) + delete[] m_LabData[i]; + delete[] m_LabData; + m_LabData = NULL; + } + if (m_nlcm != NULL) + { + delete[] m_nlcm; + m_nlcm = NULL; + } + if (m_targetVal != NULL) + { + delete[] m_targetVal; + m_targetVal = NULL; + } + if (m_inkpercentage != NULL) + { + delete[] m_inkpercentage; + m_inkpercentage = NULL; + } +} + +size_t Tango::ColorLib::ColorCalibrator::GetLiquidFactor(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +{ + //Get Input + CalibrationInput* calibrationInput = calibration_input__unpack(NULL, input_buffer_size, input_buffer); + + //Investigate Input + InitData((const CalibrationMeasurement**)calibrationInput->measurements, calibrationInput->n_measurements, calibrationInput->liquidtype, calibrationInput->targetl, calibrationInput->targeta, calibrationInput->targetb); + + //Init Output + CalibrationOutput *calibrationOutput = (CalibrationOutput*)malloc(sizeof(CalibrationOutput)); + calibration_output__init(calibrationOutput); + + + //{{{ TEST + //double targetL = calibrationInput->has_targetl; //Get Target LAB... + + //for (size_t i = 0; i < calibrationInput->n_measurements; i++) //Iterate measurements... + //{ + // CalibrationMeasurement* m = calibrationInput->measurements[i]; + + // m->nanoliterpercentimeter; //NL PER CM.. + // m->l; //L + // m->a; //A + // m->b; //B + //} + //calibrationOutput->liquidfactor = 5.0; + //}}} + + //Set Output + calibrationOutput->has_liquidfactor = true; + std::string error_message; + MaximalDispensingRate(calibrationOutput->liquidfactor, error_message); + const char* c_error = error_message.c_str(); + if (strlen(c_error) > 0) + { + calibrationOutput->errormessage = strdup(c_error); + } + + //Pack Output + output_buffer = (uint8_t*)malloc(calibration_output__get_packed_size(calibrationOutput)); + int size = calibration_output__pack(calibrationOutput, output_buffer); + + //Free Resources + calibration_input__free_unpacked(calibrationInput, NULL); + calibration_output__free_unpacked(calibrationOutput, NULL); + + return size; +} + +size_t Tango::ColorLib::ColorCalibrator::GetLinearizationMeasurements(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +{ + //Get Input + LinearizationInput* linearizationInput = linearization_input__unpack(NULL, input_buffer_size, input_buffer); + try + { + //Investigate Input + LinearizationInitData((const LinearizationMeasurement**)linearizationInput->measurements, linearizationInput->n_measurements, linearizationInput->liquidtype, linearizationInput->targetl, linearizationInput->targeta, linearizationInput->targetb); + + //Init Output + LinearizationOutput *linearizationOutput = (LinearizationOutput*)malloc(sizeof(LinearizationOutput)); + linearization_output__init(linearizationOutput); + + std::string error_message; + linearizationOutput->n_inkpercentage = m_nsize; + linearizationOutput->inkpercentage = new double[m_nsize]; + Linearizaton(m_inkpercentage, linearizationOutput->inkpercentage, error_message); + const char* c_error = error_message.c_str(); + if (strlen(c_error) > 0) + { + //linearizationOutput->has_haserror = true; + //linearizationOutput->haserror = true; + linearizationOutput->errormessage = strdup(c_error); + } + //Pack Output + output_buffer = (uint8_t*)malloc(linearization_output__get_packed_size(linearizationOutput)); + int size = linearization_output__pack(linearizationOutput, output_buffer); + + //Free Resources + linearization_input__free_unpacked(linearizationInput, NULL); + linearization_output__free_unpacked(linearizationOutput, NULL); + + return size; + } + catch (const std::exception& e) + { + //Notify Error... + LinearizationOutput *linearizationOutput = (LinearizationOutput*)malloc(sizeof(LinearizationOutput)); + linearization_output__init(linearizationOutput); + + linearizationOutput->has_haserror = true; + linearizationOutput->haserror = true; + + const char* what = e.what(); + linearizationOutput->errormessage = strdup(what); + + output_buffer = (uint8_t*)malloc(linearization_output__get_packed_size(linearizationOutput)); + int size = linearization_output__pack(linearizationOutput, output_buffer); + //Free Resources + linearization_input__free_unpacked(linearizationInput, NULL); + linearization_output__free_unpacked(linearizationOutput, NULL); + + return (size); + } +} + +void Tango::ColorLib::ColorCalibrator::InitData(const CalibrationMeasurement** m, const size_t &nsize, const int &inkChannel, const double& targetl, const double& targeta, const double& targetb) +{ + ClearData(); + + m_nsize = nsize; + m_LabData = new double*[m_nsize]; + m_nlcm = new double[m_nsize]; + + for (int i = 0; i < m_nsize; ++i) + { + m_LabData[i] = new double[3]; + m_LabData[i][0] = m[i]->l; + m_LabData[i][1] = m[i]->a; + m_LabData[i][2] = m[i]->b; + m_nlcm[i] = m[i]->nanoliterpercentimeter; + + } + m_inkChannel = inkChannel; + m_targetVal = new double[3]; + m_targetVal[0] = targetl; + m_targetVal[1] = targeta; + m_targetVal[2] = targetb; + + m_CalIndex = 0; + if (m_inkChannel == 2) + m_CalIndex = 2; +} +void Tango::ColorLib::ColorCalibrator::MaximalDispensingRate(double &MDispRate, std::string &outputmessage) +{ + MDispRate = -1000; + double *yVal = new double[m_nsize]; + + double maxVal = -1000; + double minVal = 1000; + int maxInd = -1; + int minInd = -1; + for (int i = 0; i < m_nsize; ++i) + { + yVal[i] = m_LabData[i][m_CalIndex]; + if (maxVal < yVal[i]) + { + maxVal = yVal[i]; + maxInd = i; + } + if (minVal > yVal[i]) + { + minVal = yVal[i]; + minInd = i; + } + } + if (maxVal - minVal < MDRThr) + { + delete[] yVal; + yVal = NULL; + outputmessage = "Maximal and Minimal Values are too close"; + return; + } + + //increasing or decreasing + int KC = 0; + if (yVal[0] < yVal[m_nsize - 1]) + KC = 1; // increasing + else if (yVal[0] > yVal[m_nsize - 1]) + KC = -1; // decreasing + int indLab = 0; + if (m_inkChannel == 2) //Yellow + indLab = 2; + double dE = 0.0; + if ((m_targetVal[indLab] < minVal) | (m_targetVal[indLab] > maxVal)) + { + //Advice + if (KC == 1) + { + if (m_targetVal[indLab] < minVal) + { + //Increasing Function, dispensing rate above values + dEcmc(m_targetVal, m_LabData[minInd], dE); + if (dE < dEThr) + MDispRate = m_nlcm[minInd]; + else + { + if (yVal != NULL) + { + delete[] yVal; + yVal = NULL; + } + outputmessage = "Target Value does not fall in data interval,decrease dispensing rate"; + return; + } + } + else if (m_targetVal[indLab] > maxVal) + { + //Increasing Function, dispensing rate below values + dEcmc(m_targetVal, m_LabData[maxInd], dE); + if (dE < dEThr) + MDispRate = m_nlcm[maxInd]; + else + { + if (yVal != NULL) + { + delete[] yVal; + yVal = NULL; + } + outputmessage ="Target Value does not fall in data interval,increase dispensing rate"; + return; + } + } + } + else //decreasing //KC = -1 + { + if (m_targetVal[indLab] < minVal) + { + //decreasing Function, dispensing rate above values + dEcmc(m_targetVal, m_LabData[minInd], dE); + if (dE < dEThr) + MDispRate = m_nlcm[minInd]; + else + { + if (yVal != NULL) + { + delete[] yVal; + yVal = NULL; + } + outputmessage = "Target Value does not fall in data interval,increase dispensing rate"; + return; + } + } + else if (m_targetVal[indLab] > maxVal) + { + //Increasing Function, dispensing rate below values + dEcmc(m_targetVal, m_LabData[maxInd], dE); + if (dE < dEThr) + MDispRate = m_nlcm[maxInd]; + else + { + + if (yVal != NULL) + { + delete[] yVal; + yVal = NULL; + outputmessage = "Target Value does not fall in data interval,decrease dispensing rate"; + return; + } + } + } + } + } + else + { + for (int i = 0; i < m_nsize; ++i) + yVal[i] *= KC; + double targetVal = KC * m_targetVal[indLab]; + for (int i = 0; i < m_nsize - 1; ++i) + { + if ((yVal[i] <= targetVal) & (targetVal < yVal[i + 1])) + MDispRate = ((targetVal - yVal[i])*m_nlcm[i + 1] + (yVal[i + 1] - targetVal)*m_nlcm[i]) / (yVal[i + 1] - yVal[i]); + } + } + +} + +void Tango::ColorLib::ColorCalibrator::dEcmc(double *refX, double *samX, double &dECMC) +{ + //dEcmc(refX, samX) calculates color difference CMC(2:1) in + //CIE - L*a*b* colorspace between references(refX) and + // samples(samX) + +// reference parameter calculations + // hue calculation + double h1 = atan2(refX[2], refX[1])*(180 / PI); + if (h1 < 0) + h1 = h1 + 360; + double h2 = atan2(samX[2], samX[1])*(180 / PI); + if (h2 < 0) + h2 = h2 + 360; + double refX_H = h1; + //chroma calculation + double refX_C = sqrt(refX[1] * refX[1] + refX[2] * refX[2]); + //reference SL parameter + double refX_SL; + if (refX[1] <= 16) + refX_SL = 0.511; + else + refX_SL = refX[1] * 0.040975 / (1 + 0.01765*refX[1]); + //reference SC parameter + double refX_SC = (0.638 + 0.0638*refX_C / (1 + 0.0131*refX_C)); + //reference CQ parameter + double refX_CQ = pow(refX_C, 4); + //reference F parameter + double refX_F = sqrt(refX_CQ / (refX_CQ + 1900)); + // reference T parameter + double refX_T = 0; + if ((refX_H > 164) & (refX_H < 345)) + refX_T = 0.56 + abs(0.2*cos(PI*(refX_H + 168) / 180)); + else if ((refX_H >= 345) | (refX_H <= 164)) + refX_T = 0.36 + abs(0.4*cos(PI*(refX_H + 35) / 180)); + // reference SH parameter + double refX_SH = refX_SC * (refX_T*refX_F + 1 - refX_F); + + //sample parameter calculations + //hue calculation + double samX_H = h2; + //chroma calculation + double samX_C = sqrt(samX[1] * samX[1] + samX[2] * samX[2]); + + double dL = refX[0] - samX[0]; + double dC = samX_C - refX_C; + double da = refX[1] - samX[1]; + double db = refX[2] - samX[2]; + double dH = sqrt(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)); +} + +void Tango::ColorLib::ColorCalibrator::LinearizationInitData(const LinearizationMeasurement** m, const size_t &nsize, const int &inkChannel, const double& targetl, const double& targeta, const double& targetb) +{ + ClearData(); + m_nsize = nsize; + m_LabData = new double*[m_nsize]; + m_inkpercentage = new double[m_nsize]; + + for (int i = 0; i < m_nsize; ++i) + { + m_LabData[i] = new double[3]; + m_LabData[i][0] = m[i]->l; + m_LabData[i][1] = m[i]->a; + m_LabData[i][2] = m[i]->b; + m_inkpercentage[i] = m[i]->inkpercentage; + + } + m_inkChannel = inkChannel; + m_targetVal = new double[3]; + m_targetVal[0] = targetl; + m_targetVal[1] = targeta; + m_targetVal[2] = targetb; + + m_CalIndex = 0; + if (m_inkChannel == 2) + m_CalIndex = 2; +} +void Tango::ColorLib::ColorCalibrator::Linearizaton(double *InkVals, double *&LinearInkVal, std::string &error) +{ + double maxVal = -1000; + double minVal = 1000; + double * yVal = new double[m_nsize]; + + for (int i = 0; i < m_nsize; ++i) + { + yVal[i] = m_LabData[i][m_CalIndex]; + } + bool res = SortValues(InkVals, yVal); + + if (CheckDuplicates(InkVals, error)) + return; + int foundValInd = -1; + if (CheckLimits(InkVals, foundValInd, error)) + return; + + //Values are sorted and unique + //SmoothCurveData(InkVals, yVal, 7); + if (CheckMonotonicity(yVal, error)) + return; + //Values are monotonic, therefore can be inverted + + int Kconst = 1; + if (yVal[0] > yVal[m_nsize - 1]) + Kconst = -1; + for (int i = 0; i < m_nsize; ++i) + { + yVal[i] *= Kconst; + } + + if (false == Linearize(yVal, LinearInkVal, 0, m_nsize, error)) + { + return; + } +} + +bool Tango::ColorLib::ColorCalibrator::SortValues(double *InkVals, double *yVal) +{ + //prepare data + std::vector IndVal; + + //fill up first vector pair + + double *tmpLab = new double[m_nsize]; + double *tmpInk = new double[m_nsize]; + int *tmpSort = new int[m_nsize]; + int *SortIndex = new int[m_nsize]; + //init index + IndVal.resize(m_nsize); + for (int i = 0; i < m_nsize; ++i) + { + IndVal[i].m_ID = i; + SortIndex[i] = i; + IndVal[i].m_val = m_inkpercentage[i]; + yVal[i] = m_LabData[i][m_CalIndex]; + } + + std::stable_sort(IndVal.begin(), IndVal.end(), ByDouble()); + //arrange all sorted values + for (int i = 0; i < m_nsize; ++i) + { + tmpLab[i] = yVal[IndVal[i].m_ID]; + tmpInk[i] = InkVals[IndVal[i].m_ID]; + tmpSort[i] = SortIndex[IndVal[i].m_ID]; + } + for (int i = 0; i < m_nsize; ++i) + { + yVal[i] = tmpLab[i]; + m_inkpercentage[i] = tmpInk[i]; + InkVals[i] = tmpInk[i]; + SortIndex[i] = tmpSort[i]; + } + if (tmpSort != NULL) + { + delete[] tmpSort; + tmpSort = NULL; + } + if (tmpLab != NULL) + { + delete[] tmpLab; + tmpLab = NULL; + } + if (tmpInk != NULL) + { + delete[] tmpInk; + tmpInk = NULL; + } + IndVal.resize(0); + return(true); +} +bool Tango::ColorLib::ColorCalibrator::CheckDuplicates(double *InkVals, std::string &error) +{ + double diff; + for (int i = 0; i < m_nsize - 1; ++i) + { + diff = InkVals[i + 1] - InkVals[i]; + if (diff == 0.0) + { + error = "Ink Percentages have to be unique"; + return true; + //throw std::exception("Ink Percentages have to be unique"); + } + } + return false; +} + +bool Tango::ColorLib::ColorCalibrator::CheckLimits(double *InkVals, int &foundValInd, std::string &error) +{ + double maxVal = -1000.0; + double minVal = 1000.0; + double constVal = 100.0; + bool foundVal = false; + + for (int i = 0; i < m_nsize; ++i) + { + if (InkVals[i] == constVal) + { + foundValInd = i; + foundVal = true; + } + maxVal = fmax(maxVal, InkVals[i]); + minVal = fmin(minVal, InkVals[i]); + } + if (maxVal < 100.0) + { + error ="Maximal value has to be at least 100%"; + return true; + } + if (foundVal == false) + { + error = "Inks List has to contain 100%"; + return true; + } + //if (foundValInd >= 0) + // if (maxVal > InkVals[foundValInd]) + // NumIntervals = 2; + if (minVal != 0.0) + { + error = "Minimal value has to be 0"; + return true; + } + return false; +} + +void Tango::ColorLib::ColorCalibrator::SmoothCurveData(double *XVal, double *YVal, int FilterWidth) +{ + int NumIter = max(FilterWidth, 3) - 2; + //Smooth the data with repeated applications of a[1 1 1] filter + int npts = 101; + int n_interval = npts - 1; + double *xinterp = new double[npts]; + double *yinterp = new double[npts]; + Interp AddPts; + double *sxVal = new double[m_nsize]; + double *syVal = new double[m_nsize]; + for (int i = 0; i < m_nsize; ++i) + { + sxVal[i] = XVal[i]; + syVal[i] = YVal[i]; + } + AddPts.SetNPoints(m_nsize); + AddPts.SetXCoords(sxVal); + AddPts.SetYCoords(syVal); + double dInterval = (sxVal[m_nsize - 1] - sxVal[0]) / n_interval; + double ytmp = 0; + for (int iadd = 0; iadd < npts; ++iadd) + { + xinterp[iadd] = double(iadd)*dInterval; + AddPts.Eval(xinterp[iadd], ytmp); + yinterp[iadd] = ytmp; + } + + double *tmpyVal = new double[npts]; + for (int i = 0; i < NumIter; ++i) + { + for (int j = 0; j < npts; ++j) + tmpyVal[j] = yinterp[j]; + for (int j = 1; j < npts - 1; ++j) + yinterp[j] = (tmpyVal[j - 1] + tmpyVal[j] + tmpyVal[j + 1]) / 3; + } + Interp SmoothPts; + SmoothPts.SetNPoints(npts); + SmoothPts.SetXCoords(xinterp); + SmoothPts.SetYCoords(yinterp); + for (int i = 0; i < m_nsize; ++i) + { + SmoothPts.Eval(XVal[i], ytmp); + YVal[i] = ytmp; + } + if(tmpyVal!=NULL) + { + delete[] tmpyVal; + tmpyVal = NULL; + } + /*if (xinterp != NULL) + { + delete[] xinterp; + xinterp = NULL; + } + if (yinterp != NULL) + { + delete[] yinterp; + yinterp = NULL; + }*/ +} + +bool Tango::ColorLib::ColorCalibrator::CheckMonotonicity(double *yVal, std::string &error) +{ + //Check Monotonicity of Smooth Lab Channel + + double diff; + diff = yVal[m_nsize - 1] - yVal[0]; + int CF = 1; + if (diff < 0) + CF = -1; + + for (int i = 0; i < m_nsize - 1; ++i) + { + diff = CF * (yVal[i + 1] - yVal[i]); + if (diff <= 0.0) + { + error = "Non monotonic behavior, please remeasure"; + return true; + } + } + return false; +} +bool Tango::ColorLib::ColorCalibrator::Linearize(double *yVal, double*LinearInkVal, int FirstInkInd, int LasInkInd, std::string &error) +{ + double Gain = (yVal[LasInkInd - FirstInkInd-1] - yVal[0]) / (m_inkpercentage[LasInkInd - 1] - m_inkpercentage[FirstInkInd]); + double Offset = yVal[0] - Gain * m_inkpercentage[FirstInkInd]; + int nPoints = LasInkInd - FirstInkInd ; + double *LabLinear = new double[nPoints]; + double *partialInkPercentage = new double[nPoints]; + for (int i = 0; i < nPoints; i++) + { + LabLinear[i] = Gain * m_inkpercentage[FirstInkInd + i] + Offset; + partialInkPercentage[i] = m_inkpercentage[FirstInkInd + i]; + } + double outVal = 0.0; + for (int i = 0; i < nPoints; i++) + { + if (false == Interp1D(LabLinear, partialInkPercentage, yVal[i], nPoints, outVal, error)) + { + delete[] LabLinear; + LabLinear = NULL; + delete[] partialInkPercentage; + partialInkPercentage = NULL; + return false; + } + LinearInkVal[i] = outVal; + } + delete[] LabLinear; + LabLinear = NULL; + delete[] partialInkPercentage; + partialInkPercentage = NULL; + return true; +} +bool Tango::ColorLib::ColorCalibrator::Interp1D(double* xx, double *yy, double InValue, int np, double &OutValue, std::string &error) +{ + int m, ind; + int errType = 0; + + ind = -1; + + //Check Bounds + if ((InValue < xx[0] - epsTol) || (InValue > xx[np - 1] + epsTol)) + { + error = "Interp1D: In Value out of Bounds"; + return false; + } + + if ((InValue > xx[0] - epsTol) && (InValue < xx[0])) + InValue = xx[0]; + + if ((InValue > xx[np - 1]) && (InValue < xx[np - 1] + epsTol)) + InValue = xx[np - 1]; + + for (m = 0; m < np - 1; ++m) + { + if (xx[m] <= InValue && xx[m + 1] >= InValue) + { + ind = m; + break; + } + } + if (ind == -1) + { + error = "Could not find interpolation interval"; + return false; + } + OutValue = ((InValue - xx[m])*yy[m + 1] + (xx[m + 1] - InValue)*yy[m]) / (xx[m + 1] - xx[m]); + return true; +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.h new file mode 100644 index 000000000..3e9a00e51 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorCalibrator.h @@ -0,0 +1,67 @@ +#include +#include +#include +#include "CalibrationInput.pb-c.h" +#include "CalibrationOutput.pb-c.h" +#include "CalibrationMeasurement.pb-c.h" +#include "LinearizationMeasurement.pb-c.h" + +#pragma once + +namespace Tango +{ + namespace ColorLib + { + class ColorCalibrator + { + public: + ColorCalibrator(); + ~ColorCalibrator(); + size_t Tango::ColorLib::ColorCalibrator::GetLiquidFactor(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + size_t Tango::ColorLib::ColorCalibrator::GetLinearizationMeasurements(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + protected: + void InitData(const CalibrationMeasurement** m, + const size_t &nsize, const int &inkChannel, const double& targetl, const double& targeta, const double& targetb); + void MaximalDispensingRate(double &MDispRate, std::string &outputmessage); + void dEcmc(double *refX, double *samX, double &dECMC); + + void LinearizationInitData(const LinearizationMeasurement** m, + const size_t &nsize, const int &inkChannel, const double& targetl, const double& targeta, const double& targetb); + void Linearizaton(double *InkVals, double*& LinearInkVal, std::string &error); + bool SortValues(double *InkVals, double *yVal); + bool CheckLimits(double *InkVals, int &foundValInd, std::string &error); + void SmoothCurveData(double *XVal, double *YVal, int FilterWidth); + bool CheckMonotonicity(double *yVal, std::string &error); + bool CheckDuplicates(double *InkVals, std::string &error); + bool Linearize(double *yVal, double*LinearInkVal, int FirstInkInd, int LasInkInd, std::string &error); + bool Interp1D(double* xx, double *yy, double InValue, int np, double &OutValue, std::string &error); + + protected: + struct VectorPair + { + int m_ID; + double m_val; + }; + struct ByDouble : public std::binary_function + { + bool operator()(const VectorPair& lhs, const VectorPair& rhs) const + { + return lhs.m_val < rhs.m_val; + } + }; + private: + void ClearData(); + + private: + int m_nsize; + double *m_nlcm; + double **m_LabData; + int m_inkChannel; + double *m_targetVal; + int m_CalIndex; + + double *m_inkpercentage; + }; + } +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.cpp new file mode 100644 index 000000000..58e0237aa --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.cpp @@ -0,0 +1,5800 @@ +#include "ColorConverter.h" +#include "ColorConvert.h" +#include "CalibrationPoint.pb-c.h" +#include "CalibrationData.pb-c.h" +#include "ColorSpace.pb-c.h" +#include "ConversionInput.pb-c.h" +#include "ConversionOutput.pb-c.h" +#include "InputCoordinates.pb-c.h" +#include "OutputCoordinates.pb-c.h" +#include "OutputLiquid.pb-c.h" +#include "InputLiquid.pb-c.h" +#include "LiquidType.pb-c.h" +#include "ObjectiveFunction.h" +#include "LevMar.h" +#include +#include +#include "Dense" +#include "C_RGB_XYZ_Lab.h" +#include "ColorConvert.h" +#include "ColorTransf.h" +#include "NumConversions.h" +#include "Interp.h" +#include +#include +#include +#include +#include + +#include "GradientConversionInput.pb-c.h" +#include "GradientConversionOutput.pb-c.h" +#include "GradientInputStop.pb-c.h" +#include "GradientOutputStop.pb-c.h" +#include "LiquidVolume.pb-c.h" +#include "RecommendedProcessTableInput.pb-c.h" +#include "RecommendedProcessTableOutput.pb-c.h" +#include "OutOfGamutInput.pb-c.h" +#include "OutOfGamutOutput.pb-c.h" + +#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 + +#define dL 2.0 +#define dC 2.0 +#define dH6 EIGEN_PI / 3.0 +#define dH12 EIGEN_PI / 6.0 +#define LUMINANCE_PCS 159.16 +#define L_A LUMINANCE_PCS / 5.0 +#define Y_b 20.0 +#define eps 1e-06 +#define NegValue -1000 +#define WPTol 1.0 +#define dETol 0.5 +# define ROUNDINGDigits 3.0 +#define maxPerRegion 100.0 +#define GamutMinReg0 200 +#define GamutMinReg1 300 +//#define LowVolumeThreshold 0.5 +//#define LowVolHalf LowVolumeThreshold/2 +#define GradientEndThr 0.95 +#define DilutionFactor 10 +//#define LightInksThr 5 + + +Tango::ColorLib::ColorConverter::ColorConverter() : + m_CalibCurves(NULL), m_Conv02(NULL), + m_maxNlPerCM(NULL), m_CTmaxNlPerCM(NULL), m_currentMaxNLPerCM(NULL), m_maxCalX(NULL), + m_nInks(0), m_nVolumes(0), m_CalibMode(0), m_CalibGain(NULL), m_CalibOffset(NULL), + m_GradStops(NULL), m_nGradStops(0), m_colortable(NULL), m_ProcessRangesMaxP(NULL), + m_ProcessRangesMinP(NULL), m_CurrentProcessRangesMax(NULL), m_CurrentProcessRangesMin(NULL), + m_nProcessRanges(0), //m_NormGamutRegionMaxLim(NULL), + m_GamutRegionMaxLim(NULL), + m_GamutRegionMinLim(NULL), m_forwardmodel(NULL), + m_UseLightInks(false), m_InkNames(NULL), m_LightInksThr (0.0), + m_LowVolumeThreshold(0.0), m_LowVolHalf(0.0) + //, m_NormFactor(0.0), m_InvnormFactor(0.0) +{ + m_whitepointLab.Set(-1, -1, -1); + m_whitepointXYZ_Strip.Set(-1, -1, -1); + m_WP.Set(-1, -1, -1); +} + +Tango::ColorLib::ColorConverter::~ColorConverter() +{ + if (m_Conv02 != NULL) + { + delete m_Conv02; + m_Conv02 = NULL; + } + if (m_CalibCurves != NULL) + { + delete[] m_CalibCurves; + m_CalibCurves = NULL; + } + if (m_GradStops != NULL) + { + delete[] m_GradStops; + m_GradStops = NULL; + } + if (m_colortable != NULL) + { + delete m_colortable; + m_colortable = NULL; + } +/* if (m_NormGamutRegionMaxLim != NULL) + { + delete[] m_NormGamutRegionMaxLim; + m_NormGamutRegionMaxLim = NULL; + } */ + if (m_GamutRegionMaxLim != NULL) + { + delete[] m_GamutRegionMaxLim; + m_GamutRegionMaxLim = NULL; + } + if (m_GamutRegionMinLim != NULL) + { + delete[] m_GamutRegionMinLim; + m_GamutRegionMinLim = NULL; + } + if (m_ProcessRangesMaxP != NULL) + { + delete[] m_ProcessRangesMaxP; + m_ProcessRangesMaxP = NULL; + } + if (m_ProcessRangesMinP != NULL) + { + delete[] m_ProcessRangesMinP; + m_ProcessRangesMaxP = NULL; + } + if (m_InkNames != NULL) + { + delete[] m_InkNames; + m_InkNames = NULL; + } + if (m_CalibGain != NULL) + { + delete[] m_CalibGain; + m_CalibGain = NULL; + } + if (m_CalibOffset != NULL) + { + delete[] m_CalibOffset; + m_CalibOffset = NULL; + } + if (m_maxCalX != NULL) + { + delete[] m_maxCalX; + m_maxCalX = NULL; + } + if (m_CurrentProcessRangesMax != NULL) + { + delete[] m_CurrentProcessRangesMax; + m_CurrentProcessRangesMax = NULL; + } + if (m_CurrentProcessRangesMin != NULL) + { + delete[] m_CurrentProcessRangesMin; + m_CurrentProcessRangesMin = NULL; + } + //_CrtDumpMemoryLeaks(); +} + +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; + ColorConvert ColConv(D65, D65); + SURROUND sur = m_Conv02->getSurround(); + CAM02CS CS = m_Conv02->getCAM02CS(); + VectorXd LabV(3); + + LabV = Lab; + + //LCH coordinates + double hue = 0.0; + 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(Lab(2), Lab(1)); + + double d1 = dC; + double de = 0; + MatrixXd Lab1(nHive, 3); + for (int i = 0; i < 6; ++i) + { + 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; + for (int i = 0; i < 12; ++i) + { + j1 = i + 6; + 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) + { + 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); + } + //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_TotalNumberofInks); + MatrixXd LabHive(nHive + 1, 3); + VectorXd xyz(3); + C_RGB_XYZ_Lab xyzVal, LabVal; + double *tmpRGB = new double[3]; +// double *InkOut = new double[m_nInks]; + int *GamutRegion = new int[nHive + 1]; + double *Lab1P = new double[3]; + VectorXd Vol(m_nInks); + int j = 0; + double * LabInFinal1 = new double[3]; + double * LabOnGamut = new double[3]; + double *InkOutP = new double[m_nInks]; + bool InGamut = true; + double *tmpNormFactor = m_colortable->GetNormFactor(); + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int iP = 0; iP < m_nProcessRanges; ++iP) + { + m_CurrentProcessRangesMax[iP] = m_ProcessRangesMaxP[iP]; + m_CurrentProcessRangesMin[iP] = m_ProcessRangesMinP[iP]; + } + VectorXd NLInkOut(m_nInks); + VectorXd InkOutV(m_nInks); + VectorXd RGBOutV(3); + VectorXd LabOutV(3); + for (int iHive = 0; iHive < nHive; ++iHive) + { + //Get Lab's inGamut + for (j = 0; j < 3; ++j) + Lab1P[j] = Lab1(iHive, j); + if (m_colortable->GetTableSubVersion() > 0) + { + DirectInversionCalc(Lab1P, InkOutV, RGBOutV, Vol, LabOutV, + GamutRegion[iHive], InGamut, sur, CS); + PercentagetoNLcm(Vol, Vol); // Volume is in Color Table Units + int CTUnits = 1; + GetClosestInk(Vol, GamutRegion[iHive], Vol, CTUnits, InGamut); //Input Volume is in [nl/cm] Output Volume is in [%] + ConfineVolumes(Vol); + VectorToDouble(LabOutV, LabInFinal1); + VectorToDouble(RGBOutV, tmpRGB); + } + else + { + ColConv.ChangeWP(Lab1P, Lab1P, m_WP, m_whitepointXYZ_Strip); //to Relative + m_colortable->m_B2ATransform->evalLab2InkP(Lab1P, InkOutP, GamutRegion[iHive]); //InkOut is in the [0-100] interval + InGamut = IsInGamut(Lab1P, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + if (m_CalibMode == 1) + { + ApplyCTLinearCurves(InkOutP, InkOutP); // full range color table units + InkOutV = DoubleToVector(InkOutP, m_nInks); + ColorTable2Threadunits(InkOutV, InkOutV); // full range Thread units + ConvertToNLInks(InkOutV, NLInkOut); + int CTUnits = 0; + LimitNLInks2Volume(NLInkOut, GamutRegion[iHive], Vol, CTUnits, InGamut ); + } + else + { + for (int iInk = 0; iInk < m_nInks; ++iInk) + InkOutP[iInk] *= tmpNormFactor[iInk]; //full range Thread units + int CTUnits = 0; + LimitNLInks2Volume(DoubleToVector(InkOutP, m_nInks), GamutRegion[iHive], Vol, CTUnits, InGamut); + } + + m_Conv02->ChangeWP(LabOnGamut, LabInFinal1, m_whitepointXYZ_Strip, m_WP); //convert back to Absolute + LimitLab(LabInFinal1); //Absolute + m_Conv02->SetReferenceWhite(D65); + //Convert to RGB, relative col is converted + m_Conv02->LabtoRGB(LabOnGamut, tmpRGB); + } + + VectorXd VolumeLI(m_TotalNumberofInks); + if (m_UseLightInks) + { + SplitVolume(Vol, VolumeLI, GamutRegion[iHive]); + } + else + { + for (int iVol = 0; iVol < m_nInks; ++iVol) + VolumeLI(iVol) = Vol(iVol); + } + + for (int j = 0; j < 3; ++j) + LabHive(iHive, j) = LabInFinal1[j]; + + for (int j = 0; j < 3; ++j) + RGBTmpVec(iHive, j) = std::min(std::max(tmpRGB[j], 0.0), 255.0); + + for (int j = 0; j < m_TotalNumberofInks; ++j) + VolumeHive(iHive, j) = VolumeLI(j); + } + + VectorXd VolumeLI_s(m_TotalNumberofInks); + if (m_UseLightInks) + { + SplitVolume(Volume, VolumeLI_s, InGamutRegion); + } + else + { + for (int iVol = 0; iVol < m_nInks; ++iVol) + VolumeLI_s(iVol) = Volume(iVol); + } + for (j = 0; j < m_TotalNumberofInks; ++j) + VolumeHive(nHive, j) = VolumeLI_s(j); + for (j = 0; j < 3; ++j) + { + RGBTmpVec(nHive, j) = RGB(j); + LabHive(nHive, j) = Lab(j); + } + GamutRegion[nHive] = InGamutRegion; + + //Organize hive into 5x5 matrix + //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 + 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; + InkOut = NULL; + }*/ + if (GamutRegion != NULL) + { + delete[] GamutRegion; + GamutRegion = NULL; + } + if (Lab1P != NULL) + { + delete[] Lab1P; + Lab1P = NULL; + } + if (tmpRGB != NULL) + { + delete[] tmpRGB; + tmpRGB = NULL; + } + + if (LabInFinal1 != NULL) + { + delete[]LabInFinal1; + LabInFinal1 = NULL; + } + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + return; +} + +void Tango::ColorLib::ColorConverter::FindTriplet(VectorXd Lab, MatrixXd Lab1, int nHive, int*indDataMax) +{ + + int vecSize = nHive * (nHive - 1) / 2; + double *dECMC = new double[vecSize]; + int i, j; + for (i = 0; i < vecSize; ++i) + dECMC[i] = -1; + int **indexpairs = new int*[vecSize]; + for (i = 0; i < vecSize; ++i) + { + indexpairs[i] = new int[2]; + for (int j = 0; j < 2; ++j) + indexpairs[i][j] = 0; + } + + 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); + for (j = i + 1; j < nHive; ++j) + { + Labj << Lab1(j, 0), Lab1(j, 1), Lab1(j, 2); + ind++; + ColConv.SymmetricaldECMC(Labi, Labj, dECMC[ind]); + indexpairs[ind][0] = i; + indexpairs[ind][1] = j; + } + } + double maxdE = dECMC[0]; + int maxInd = 0; + for (int i = 1; i < vecSize; ++i) + { + if ((maxdE < dECMC[i]) && (dECMC[i] < 5)) + { + maxdE = dECMC[i]; + maxInd = i; + } + } + indDataMax[0] = indexpairs[maxInd][0]; + indDataMax[1] = indexpairs[maxInd][1]; + if (dECMC != NULL) + { + delete[]dECMC; + dECMC = NULL; + } + + if (indexpairs != NULL) + { + for (int i = 0; i < vecSize; ++i) + delete[] indexpairs[i]; + delete[] indexpairs; + indexpairs = NULL; + } + return; +} + +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. + + 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_TotalNumberofInks; ++j) + OVolumeHive(index, j) = VolumeHive(i, j); + + OGamutRegion[index] = GamutRegion[i]; + } +} + + +void Tango::ColorLib::ColorConverter::fillVolume(OutputCoordinates *&outputCoords, VectorXd Volume) +{ + int i = 0; + OutputLiquid** outputLiquids = (OutputLiquid**)malloc(sizeof(OutputLiquid*) * m_TotalNumberofInks); + for (i = 0; i < m_TotalNumberofInks; ++i) + { + outputLiquids[i] = (OutputLiquid*)malloc(sizeof(OutputLiquid)); + output_liquid__init(outputLiquids[i]); + switch (m_InkNames[i]) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + case LIQUID_TYPE__LightCyan: + case LIQUID_TYPE__LightMagenta: + case LIQUID_TYPE__LightYellow: + { + outputLiquids[i]->has_volume = true; + outputLiquids[i]->has_liquidtype = true; + outputLiquids[i]->liquidtype = (LiquidType)(m_InkNames[i]); + outputLiquids[i]->volume = Volume(i); + break; + } + default: + throw std::exception("could not fill all volumes"); + } + } + outputCoords->outputliquids = outputLiquids; + outputCoords->n_outputliquids = m_TotalNumberofInks; + return; +} + +void Tango::ColorLib::ColorConverter::fillRGB(OutputCoordinates *outputCoords, VectorXd RGBOut) +{ + outputCoords->has_red = true; + outputCoords->red = (int32_t)std::round(RGBOut(0)); + outputCoords->has_green = true; + outputCoords->green = (int32_t)std::round(RGBOut(1)); + outputCoords->has_blue = true; + 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) +{ + SetStripWhitepoint(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + bool has_forwarddata = conversionInput->has_forwarddata; + uint8_t *data = conversionInput->forwarddata.data; + int nprocessranges = conversionInput->n_processranges; + if (nprocessranges <= 0) + throw std::exception("number of process ranges is zero or less"); + + m_colortable->InitColorTables(has_forwarddata, data, nprocessranges); + SetNumberofInks(m_colortable->GetnA2BnSepOut()); +} + +void Tango::ColorLib::ColorConverter::readColorTransformations(OutOfGamutInput* Input) +{ + SetStripWhitepoint(Input->threadl, Input->threada, Input->threadb); + bool has_forwarddata = Input->has_forwarddata; + uint8_t *data = Input->forwarddata.data; + int nprocessranges = Input->n_processranges; + if (nprocessranges <= 0) + throw std::exception("number of process ranges is zero or less"); + + m_colortable->InitColorTables(has_forwarddata, data, nprocessranges); + SetNumberofInks(m_colortable->GetnA2BnSepOut()); +} + +void Tango::ColorLib::ColorConverter::readColorTransformations(RecommendedProcessTableInput* conversionInput) +{ + SetStripWhitepoint(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + bool has_forwarddata = conversionInput->has_forwarddata; + uint8_t *data = conversionInput->forwarddata.data; + int nprocessranges = conversionInput->n_processranges; + if (nprocessranges <= 0) + throw std::exception("number of process ranges is zero or less"); + + m_colortable->InitColorTables(has_forwarddata, data, nprocessranges); + SetNumberofInks(m_colortable->GetnA2BnSepOut()); +} + +void Tango::ColorLib::ColorConverter::SetStripWhitepoint(double threadl, double threada, double threadb) +{ + //Read thread white. Thread White is given in CIELab Space + if ((threadl <= 0 || threadl > 100) || (threada < -127 || threada>128) || (threadb < -127 || threadb>128)) + throw std::exception("White Point Lab exceeds limits"); + else + m_whitepointLab.Set(threadl, threada, 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()); +} + + + +void Tango::ColorLib::ColorConverter::readCalibrationTables(InputLiquid **inputliquid, int n_inputliquid) +{ + SetNumberofInks((int)(n_inputliquid)); + + // Verify Data + for (int i = 0; i < m_nInks; ++i) + { + if (inputliquid[i]->maxnanoliterpercentimeter <= 0) + { + throw std::exception("Liquid Factor is zero or negative!"); + return; + } + + } + // Verify x and y are monotonic for each ink channel + bool IsValid = false; + CalibrationData *calibdata; + for (int i = 0; i < m_nInks; ++i) + { + calibdata = inputliquid[i]->calibrationdata; + IsValid = CheckMonotonicity(calibdata); + if (IsValid = false) + { + throw std::exception("Calibration Data is not monotonic"); + return; + } + } + + if (m_CalibCurves == NULL) + m_CalibCurves = new CalibData[m_nInks]; + + for (int i = 0; i < m_nInks; ++i) + { + InputLiquid* InkType = inputliquid[i]; + m_CalibCurves[i].SetCalibName((int)(InkType->calibrationdata->liquidtype)); + m_CalibCurves[i].SetMaxNlPerCM(inputliquid[i]->maxnanoliterpercentimeter); + + switch (InkType->calibrationdata->liquidtype) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + { + // calibration data. + CalibrationData* calibrationData = InkType->calibrationdata; + SetCalibData(calibrationData, i, &m_CalibCurves[i]); + m_CalibCurves[i].InitInterpolations(); + break; + } + default: + { + throw std::exception("could not fill all calibration tables"); + return; + } + } + } + return; +} + +void Tango::ColorLib::ColorConverter::SetCalibMode() +{ + double *maxVal = new double[m_nInks]; + m_maxCalX = new double[m_nInks]; + for (int i= 0; in_calibrationpoints < 2) + { + char msg[100]; + strcpy_s(msg, 100, "Not enough Calibration points in table "); + throw std::exception(msg); + return; + } + //check data validity + + tmpCurve->SetCalibCurveSize((int)(calibrationData->n_calibrationpoints)); + //Iterate over calibration points.. + double *pointsx = new double[calibrationData->n_calibrationpoints]; + double *pointsy = new double[calibrationData->n_calibrationpoints]; + + for (size_t j = 0; j < calibrationData->n_calibrationpoints; ++j) + { + //Calibration Point + pointsx[j] = calibrationData->calibrationpoints[j]->x; + pointsy[j] = calibrationData->calibrationpoints[j]->y; + } + tmpCurve->SetXCoords(pointsx); + tmpCurve->SetYCoords(pointsy); + if (pointsx != NULL) + { + delete[] pointsx; + pointsx = NULL; + } + + if (pointsy != NULL) + { + delete[] pointsy; + pointsy = NULL; + } + return; +} + +bool Tango::ColorLib::ColorConverter::CheckMonotonicity(CalibrationData *calibdata) +{ + //Check Monotonicity of Smooth Lab Channel + bool retvalue = true; + if (calibdata->n_calibrationpoints < 2) + { + throw std::exception("Not enough Calibration points in table "); + retvalue = false; + return(retvalue); + } + double diffx, diffy; + double *xval = new double[calibdata->n_calibrationpoints]; + double *yval = new double[calibdata->n_calibrationpoints]; + for (int i = 0; i < (int)calibdata->n_calibrationpoints; ++i) + { + xval[i] = calibdata->calibrationpoints[i]->x; + yval[i] = calibdata->calibrationpoints[i]->y; + } + + diffy = yval[calibdata->n_calibrationpoints - 1] - yval[0]; + diffx = xval[calibdata->n_calibrationpoints - 1] - xval[0]; + int CFx = 1; + if (diffx < 0) + CFx = -1; + int CFy = 1; + if (diffy < 0) + CFy = -1; + + for (int i = 0; i < (int)calibdata->n_calibrationpoints - 1; ++i) + { + diffx = CFx * (xval[i + 1] - xval[i]); + if (diffx <= 0.0) + { + throw std::exception("non-monotonic x-axis "); + retvalue = false; + return(retvalue); + } + diffy = CFx * (yval[i + 1] - yval[i]); + if (diffy <= 0.0) + { + throw std::exception("non-monotonic y-axis "); + retvalue = false; + return(retvalue); + } + } + return retvalue; +} + +void Tango::ColorLib::ColorConverter::ConvertLabColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + // 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. Convert Lab to Inks (B2A tables), Inks to Volume + //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 *LabOnGamut = new double[3]; + + LabIn[0] = inputcoordinates->l; //Absolute Colorimetric + LabIn[1] = inputcoordinates->a; + LabIn[2] = 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 *LabInFinal2 = new double[3]; + + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //LabInFinal2 is in Relative Colorimetric Space + LimitLab(LabInFinal2); + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + + //convert to Inks + double *InkOutP = new double[m_nInks]; + m_colortable->m_B2ATransform->evalLab2InkP(LabInFinal2, InkOutP, GamutRegion); //InkOutP is in units of 16 bits + //Convert Inks to Lab to get the Gamut Mapped Lab + +//Convert InkOutP to linear in the m_GamutRegionMaxLim[0] range + //Color Tables are encoded in 16 bits which are equivalent to [0-100] + //The same is true for linear curves + //Therefore the factorization by normfactor has to be done after the calculation of the linear curves + //Linear Curves in the color table are defined in the full range (Sylko [0-200]%) + //We apply the linear curves to the full range + // InkOutP is in the full range of the color table + if(m_CalibMode ==1) + ApplyCTLinearCurves(InkOutP, InkOutP); + else + { + double *tmpval = m_colortable->GetNormFactor(); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; + } + InkOut = DoubleToVector(InkOutP, m_nInks); + +double *LabOutFinal = new double[3]; + //double *LabOutFinal = DBG_NEW double[3]; + 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_Strip, m_WP); + + LabOut = DoubleToVector(LabOutFinal, 3); + CConvertD65.SetReferenceWhite(D65); + //Convert to RGB + double *RGBOutP = new double[3]; + + //Use Relative colorimetric to get RGB + CConvertD65.LabtoRGB(LabOnGamut, RGBOutP); + RGBOut = DoubleToVector(RGBOutP, 3); + if (LabOnGamut != NULL) + { + delete[] LabOnGamut; + LabOnGamut = NULL; + } + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (LabInFinal2 != NULL) + { + delete[]LabInFinal2; + LabInFinal2 = NULL; + } + if (LabOutFinal != NULL) + { + delete[]LabOutFinal; + LabOutFinal = NULL; + } + + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } +} + + +void Tango::ColorLib::ColorConverter::ConvertRGBColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + // Basic assumption: if data is given in RGB space, RGB is assumed to be in Strip Color Coordinates, + //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, but will be shown in Relative Colorimetric to the user + //The workflow is a follows: + //1. Convert RGB to Lab (Whitepoint is D65, same as tables) + //1-a. Convert Lab to Relative Colorimetric + //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 Color Table whitepoints + //5. Use the Relative Colorimetric Lab to obtain RGB + + RGBOut(0) = inputcoordinates->red; + RGBOut(1) = inputcoordinates->green; + RGBOut(2) = inputcoordinates->blue; + //convert to Lab + ColorConvert CConvertD65(D65, D65); //Destination, source + + double *LabIn = new double[3]; + double *LabInFinal1 = new double[3]; + double RGBOutP[3]; + + VectorToDouble(RGBOut, RGBOutP); + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Absolute Colorimetric, D65 + //Convert LabIn to Relative Colorimetric - Feb 2021 + double *LabInFinal2 = new double[3]; + LimitLab(LabIn); + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); + //Is In Gamut? +// double *LabInFinal = new double[3]; + double *LabOnGamut = new double[3]; + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + + //convert to inks + + double *InkOutP = new double[m_nInks]; + //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; + //LabInFinal is in Relative Colorimetric, just like the Color Tables + m_colortable->m_B2ATransform->evalLab2InkP(LabInFinal2, InkOutP, GamutRegion); //InkOutP is inthe [0-100] interval + + //Convert to Lab to get the actual in Gamut Lab + //Convert InkOut to Linear via initial calibration Tables + //Initial calibration tables are the ones that were included in the color table + // if m_CalibMode = 0, do not convert via calibration tables + if(m_CalibMode ==1) + ApplyCTLinearCurves(InkOutP, InkOutP); + else + { + double *tmpval = m_colortable->GetNormFactor(); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; + } + InkOut = DoubleToVector(InkOutP, m_nInks); + + //Convert to CT thread, LabOnGamut is in Relative Colorimetric Space + CConvertD65.ChangeWP(LabOnGamut, LabInFinal1, m_whitepointXYZ_Strip, m_WP); + LabOut = DoubleToVector( LabInFinal1, 3); + CConvertD65.SetReferenceWhite(D65); + double *RGBOutP1 = new double[3]; + CConvertD65.LabtoRGB(LabOnGamut, RGBOutP1); + RGBOut = DoubleToVector(RGBOutP1, 3); + + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (LabInFinal2 != NULL) + { + delete[] LabInFinal2; + LabInFinal2 = NULL; + } + if (LabInFinal1 != NULL) + { + delete[] LabInFinal1; + LabInFinal1 = NULL; + } + if (RGBOutP1 != NULL) + { + delete[] RGBOutP1; + RGBOutP1 = NULL; + } +/* if (LabInFinal != NULL) + { + delete[] LabInFinal; + LabInFinal = NULL; + }*/ +} + +void Tango::ColorLib::ColorConverter::Thread2ColorTableunits(VectorXd InkIn, VectorXd &InkOut) +{ + double Iconst = 0.0; + double lconstCT = 0.0; + for (int i = 0; i < m_nInks; ++i) + { + if (InkIn(i) > 100.0) + { + Iconst = m_maxNlPerCM(i) / 100.0; + lconstCT = m_CTmaxNlPerCM(i) / 100; + InkOut(i) = ((InkIn(i)*Iconst) - m_CalibOffset[i]) / m_CalibGain[i]; + //back to % + InkOut(i) /= lconstCT; + } + else + InkOut(i) = InkIn(i); + } +} + +void Tango::ColorLib::ColorConverter::ColorTable2Threadunits(VectorXd InkIn, VectorXd &InkOut) +{ + double Iconst = 0.0; + double lconstCT = 0.0; + for (int i = 0; i < m_nInks; ++i) + { + if (InkIn(i) > 100.0) + { + Iconst = m_CTmaxNlPerCM(i) / 100.0; + lconstCT = m_maxNlPerCM(i) / 100; + InkOut(i) = m_CalibGain[i] * (InkIn(i)*Iconst) + m_CalibOffset[i]; + //back to % + InkOut(i) /= lconstCT; + } + else + InkOut(i) = InkIn(i); + } +} + +void Tango::ColorLib::ColorConverter::ApplyCTLinearCurves(double *InkIn, double* InkOut) +{ + double *tmpNormFactor = m_colortable->GetNormFactor(); + if (m_CalibMode == 1) + { + for (int i = 0; i < m_nInks; ++i) + { + m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkIn[i] * 655.35, InkOut[i]); + InkOut[i] /= 655.35; + InkOut[i] *= tmpNormFactor[i]; + } + } + else + { + for (int i = 0; i < m_nInks; ++i) + InkOut[i] *= tmpNormFactor[i]; + } +} + +void Tango::ColorLib::ColorConverter::ApplyCTInvLinearCurves(double *InkIn, double* InkOut) +{ + double *tmpNormFactor = m_colortable->GetInverseNormFactor(); + if (m_CalibMode == 1) + { + for (int i = 0; i < m_nInks; ++i) + { + m_colortable->m_LinCurves->m_InvInterpCurves[i].Eval(InkIn[i] * 655.35*tmpNormFactor[i], InkOut[i]); + InkOut[i] /= 655.35; + InkOut[i] /= tmpNormFactor[i]; + } + } +} +//void Tango::ColorLib::ColorConverter::ConvertCMYKColorToLinearInks(InputCoordinates* inputcoordinates, +// VectorXd &InkOut, VectorXd &RGBOut, +// VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +//{ +// //no conversion +// //missing from structure light inks or special colors +// // just convert Lab for rgb display +// +// double *outData = new double[m_nInks]; +// //double *outData = DBG_NEW double[m_nA2BnSepIn]; +// size_t CountSep = 0; +// outData[0] = (double)(inputcoordinates->cyan); +// outData[1] = (double)(inputcoordinates->magenta); +// outData[2] = (double)(inputcoordinates->yellow); +// outData[3] = (double)(inputcoordinates->key); +// CountSep = 4; +// +// if (CountSep != m_nInks) +// { +// //mismatch between table and sent data +// throw std::exception("Mismatch between table and sent data"); +// return; +// } +// //Convert to RGB +// double *InkOutP = new double[m_nInks]; +// +// for (int i = 0; i < m_nInks; ++i) +// InkOutP[i] = outData[i]; +// double *LabOutP = new double[3]; +// +// m_colortable->m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion); +// InkOut = DoubleToVector(InkOutP, m_nInks); +// //LabOutP is in relative colorimetric +// ColorConvert CConvertD65(D65, D65); +// double *LabOutFinal1 = new double[3]; +// for (int i = 0; i < 3; ++i) +// LabOutFinal1[i] = LabOutP[i]; +// double *LabOutFinal2 = new double[3]; +// for (int i = 0; i < 3; ++i) +// LabOutFinal2[i] = LabOutP[i]; +// InGamut = true; +// //Check if white points match +// CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_Strip, m_WP); //To Absolute +// LabOut = DoubleToVector(LabOutFinal1, 3); +// CConvertD65.SetReferenceWhite(D65); +// //Get RGB +// double *RGBOutP = new double[3]; +// CConvertD65.LabtoRGB(LabOutP, RGBOutP); +// RGBOut = DoubleToVector(RGBOutP, 3); +// +// if (outData != NULL) +// { +// delete[] outData; +// outData = NULL; +// } +// if (LabOutP != NULL) +// { +// delete[] LabOutP; +// LabOutP = NULL; +// } +// if (InkOutP != NULL) +// { +// delete[] InkOutP; +// InkOutP = NULL; +// } +// if (RGBOutP != NULL) +// { +// delete[] RGBOutP; +// RGBOutP = NULL; +// } +// if (LabOutFinal1 != NULL) +// { +// delete[] LabOutFinal1; +// LabOutFinal1 = NULL; +// } +// if (LabOutFinal2 != NULL) +// { +// delete[] LabOutFinal2; +// LabOutFinal2 = NULL; +// } +//} +void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut) +{ + size_t nInks = 0; + + C_RGB_XYZ_Lab DataLab; + SURROUND sur = m_Conv02->getSurround(); + CAM02CS CS = m_Conv02->getCAM02CS(); + switch (colorspace) + { + case (COLOR_SPACE__RGB): + { + ConvertRGBColorToLinearInks(inputcoordinates, + InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS); + break; + } + case (COLOR_SPACE__LAB): + { + ConvertLabColorToLinearInks(inputcoordinates, + InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS); + break; + } + + //case(COLOR_SPACE__CMYK): + //{ + // ConvertCMYKColorToLinearInks(inputcoordinates, + // InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS); + + // break; + //} + //case(COLOR_SPACE__Catalog): + //{ + // int32_t inData; + // if (inputcoordinates->has_pantoncode) + // inData = inputcoordinates->pantoncode; + // else + // { + // //mismatch between color space and data + // throw std::exception("Mismatch between color space and data"); + // return; + // } + // break; + //} + + default: + { + throw std::exception(" Unsupported Color Space"); + break; + } + } + //all data is now in linear ink format + return; +} + + +void Tango::ColorLib::ColorConverter::ConvertToNLInks(VectorXd InkIn, VectorXd &InkOut) +{ + //Assumes Calibration curves are defined for the whole range in % + for (int i = 0; i < m_nInks; ++i) + m_CalibCurves[i].m_InvLinearInterp->Eval(InkIn(i), InkOut(i)); + return; +} + +void Tango::ColorLib::ColorConverter::ConvertToLinearInks(VectorXd InkIn, VectorXd &InkOut) +{ + for (int i = 0; i < m_nInks; ++i) + { + m_CalibCurves[i].m_LinearInterp->Eval(InkIn(i), InkOut(i)); + } + + return; +} + +void Tango::ColorLib::ColorConverter::VolumeToNLInkP(VectorXd Volume, VectorXd &NLInkP) +{ + //Volume is in %. In order to be compatible with NL to volume it has to be tranlated to nl/cm + VectorXd InkP(m_TotalNumberofInks); + int MaxInd = -1; + double InkMax = -1.; + double InkSum = 0.; + //Convert volume to Volume without Light Inks + VectorXd VolumeNoLI((int)(m_nInks)); + if (m_UseLightInks) + { + //Convert Light Ink Volumes to Ink Volumes + for (int i = 0; i < m_nInks; ++i) + VolumeNoLI(i) = Volume(i); + + for (int i = 4; i < m_nVolumes; ++i) + { + if ((Volume(i) > 0) & (Volume(i - 4) == 0)) + { + VolumeNoLI(i - 4) = Volume(i) / DilutionFactor; + } + } + } + else + { + for (int i = 0; i < m_nInks; ++i) + VolumeNoLI(i) = Volume(i); + } + for (int i = 0; i < m_nInks; ++i) + { + InkP(i) = VolumeNoLI(i)* m_currentMaxNLPerCM(i) / 100; //Volume is in %, InkP is in [nl/cm] + if (InkMax < InkP(i)) + { + InkMax = InkP(i); + MaxInd = i; + } + InkSum += InkP(i); + } + NLInkP(MaxInd) = 100 * InkSum / m_currentMaxNLPerCM(MaxInd); //Back to % + //Limit inks to max Ink Percentage // Added October 14, 2021 + NLInkP(MaxInd) = std::min(m_maxCalX[MaxInd], NLInkP(MaxInd)); + if (InkSum == 0.0) + { + for (int i = 0; i < m_nVolumes; ++i) + NLInkP(i) = 0.0; + return; + } + + //Prepare Matrix to get the remainder values + MatrixXd MatNLI(m_nVolumes - 1, m_nVolumes - 1); + VectorXd RHSide(m_nVolumes - 1); + MatrixXd DiagMat(m_nVolumes - 1, m_nVolumes - 1); + DiagMat.setZero(); + int ind = -1; + for (int i = 0; i < m_nVolumes; ++i) + { + if (i != MaxInd) + { + ind += 1; + RHSide(ind) = InkP(i); + DiagMat(ind, ind) = -InkSum; + } + } + for (int i = 0; i < m_nVolumes - 1; ++i) + { + for (int j = 0; j < m_nVolumes - 1; ++j) + { + MatNLI(i, j) = RHSide(i) + DiagMat(i, j); + } + RHSide(i) *= (-InkSum); + } + //Solve System of Linear Equations + MatrixXd MatNLIInv(m_nVolumes - 1, m_nVolumes - 1); + MatNLIInv = MatNLI.inverse(); + VectorXd Result = MatNLIInv * RHSide; + + //rearrange solution + ind = -1; + for (int i = 0; i < m_nVolumes; ++i) + { + if (i != MaxInd) + { + ind += 1; + NLInkP(i) = 100 * Result(ind) / m_currentMaxNLPerCM(i); //Back to % + //Limit inks to max Ink Percentage // Added October 14, 2021 + NLInkP(i) = std::min(m_maxCalX[i], NLInkP(i)); + } + } + return; +} + +void Tango::ColorLib::ColorConverter::NLInkPToVolume(VectorXd NLInk, VectorXd &Volume) +{ + //Max Ink Component + double MaxInk = -1.; + VectorXd InkNorm(m_nInks); + double InkSum = 0; + int i = 0; + for (i = 0; i < m_nInks; ++i) + { + MaxInk = std::max(MaxInk, NLInk(i)); + InkSum += NLInk(i); + } + + if (MaxInk == 0) + for (i = 0; i < m_nInks; ++i) + Volume(i) = 0.0; + else + { + for (i = 0; i < m_nInks; ++i) + { + 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 VolumeRound(m_nInks); + double ROUNDINGTol = pow(10, ROUNDINGDigits); + + double maxInk = -1; + int maxInd = -1; + for (int i = 0; i < m_nInks; ++i) + { + VolumeRound(i) = std::floor(Volume(i)*ROUNDINGTol) / ROUNDINGTol; + if (VolumeRound(i) > maxInk) + { + maxInk = VolumeRound(i); + maxInd = i; + } + RsumNorm += VolumeRound(i); + } + int nGR = m_colortable->GetnGamutRegions(); + double ddCorr = 0; + if (RsumNorm > m_CurrentProcessRangesMax[m_nProcessRanges - 1]) + { + ddCorr = RsumNorm - m_CurrentProcessRangesMax[m_nProcessRanges - 1] ; + VolumeRound(maxInd) = VolumeRound(maxInd) - ddCorr; + VolumeRound(maxInd) = std::floor(VolumeRound(maxInd)*ROUNDINGTol) / ROUNDINGTol; + } + for (int i = 0; i < m_nInks; ++i) + Volume(i) = VolumeRound(i);*/ +} + + +void Tango::ColorLib::ColorConverter::SetMaxNLperCM(double maxNlPerCM, int i) +{ + m_maxNlPerCM(i) = maxNlPerCM; +} + +void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(InputCoordinates *inputcoordinates, int n_processRanges, + int colorspace, VectorXd &VolumeNoLI, VectorXd &RGBOut, VectorXd &LabOut, int &GamutRegion, bool &InGamut) +{ + //July 29 2020 + //Limit inks based on m_maxNlpercm + //Inks are limited in their nonlinear form + VectorXd NLInkP((int)(m_nInks)); + VectorXd InkOut((int)(m_nInks)); + VectorXd Volume((int)(m_TotalNumberofInks)); + VectorXd FinalVolumeNoLI(m_nInks); + + //Convert to Nonlinear Inks + double SumVol_Ink = 0.0; + //Get Gamut Region + for (int i = 0; i < m_TotalNumberofInks; ++i) + Volume(i) = inputcoordinates->inputliquids[i]->volume; + + + if (m_UseLightInks) + { + //Convert Light Ink Volumes to Ink Volumes + for (int i = 0; i < m_nInks; ++i) + VolumeNoLI(i) = Volume(i); + + for (int i = 4; i < m_TotalNumberofInks; ++i) + { + if ((Volume(i) > 0) & (Volume(i - 4) == 0)) + { + VolumeNoLI(i - 4) = inputcoordinates->inputliquids[i]->volume / DilutionFactor; + } + } + } + else + { + for (int i = 0; i < m_nInks; ++i) + VolumeNoLI(i) = Volume(i); + } + //Catalog and Volumes have different conversion factors + //Verify Volume is within the allowed limits + double *InkOutP = new double[m_nInks]; + double *LinInkP = new double[m_nInks]; + double *Ink4RGB = new double[m_nInks]; + VectorXd Ink4Vol(m_nInks); + + if (colorspace == COLOR_SPACE__Catalog) + { + for (int i = 0; i < m_nInks; ++i) // % to nl/cm + VolumeNoLI(i) *= (m_CTmaxNlPerCM(i) / 100); + m_currentMaxNLPerCM = m_CTmaxNlPerCM; + for (int iP = 0; iP < m_nProcessRanges; ++iP) + { + m_CurrentProcessRangesMax[iP] = m_GamutRegionMaxLim[iP]; + m_CurrentProcessRangesMin[iP] = m_GamutRegionMinLim[iP]; + } + GamutRegion = GetGamutRegion(VolumeNoLI, m_GamutRegionMaxLim); //Volume is in Color Table Units + int CTUnits = 1; + //Catalogue Volume Values should have InGamut = true + GetClosestInk(VolumeNoLI, GamutRegion, VolumeNoLI, CTUnits, InGamut); //Input VolumeNoLI is in [nl/cm] Output VolumeNoLI is in [%] + for (int i = 0; i < m_nInks; ++i) + FinalVolumeNoLI(i) = VolumeNoLI(i); + + VolumeToNLInkP(VolumeNoLI, NLInkP); //NLInkP is in % + VectorToDouble(NLInkP, InkOutP); + // NLcmtoPercentage(VolumeNoLI, VolumeNoLI); + + //Non Linear Inks are in Color Table space, convert to reflect the thread characteristics + // Inks are in their natural coordinates + // Inks need to be converted to thread units, RGB is calculated from initial inks + + if(m_CalibMode ==1) + { + //Convert to [0-100] before applying the Linear Curves + double *tmpval = m_colortable->GetInverseNormFactor(); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; //scaled to real units, still in % + ApplyCTLinearCurves(InkOutP, LinInkP); //Full Range in Color Table Units % + ColorTable2Threadunits(DoubleToVector(LinInkP, m_nInks), InkOut); //Full Range in Thread units % + ConvertToNLInks(InkOut,InkOut); //ful range in Thread units % + } + else + ColorTable2Threadunits(DoubleToVector(InkOutP, m_nInks), InkOut); // Full Range in % + + Ink4Vol = InkOut; + } + else if (colorspace == COLOR_SPACE__Volume) + { + //Volume is in Thread Space, need to convert to Color Table space to get RGB + for (int i = 0; i < m_nInks; ++i) // % to nl/cm in Thread Space + VolumeNoLI(i) *= (m_maxNlPerCM(i) / 100); + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_CurrentProcessRangesMax[i] = m_ProcessRangesMaxP[i]; + m_CurrentProcessRangesMin[i] = m_ProcessRangesMinP[i]; + } + GamutRegion = GetGamutRegion(VolumeNoLI, m_CurrentProcessRangesMax); + int CTUnits = 0; + GetClosestInk(VolumeNoLI, GamutRegion, VolumeNoLI, CTUnits, InGamut); //VolumenoLi Input is in [nl/cm], VolumeNoLI Output is in [%] in thread space + VolumeToNLInkP(VolumeNoLI, NLInkP); //NLInkP is in % Full Range + //save the above volume as the final one, then calculate RGB coordinates + for (int i = 0; i < m_nInks; ++i) + FinalVolumeNoLI(i) = VolumeNoLI(i); + VectorToDouble(NLInkP, InkOutP); + Ink4Vol = NLInkP; + //NLInkP are the final Volume values, the transformations are applied to get the right RGB + if (m_CalibMode == 1) + { + VectorXd InkLinV(m_nInks); + ConvertToLinearInks(NLInkP, InkLinV); //Use Calib tables //full range Thread Units % + Thread2ColorTableunits(InkLinV, InkLinV); //full range Color Table Units % + //Linear Inks are in their natural coordinates % + VectorToDouble(InkLinV, InkOutP); + //for (int i = 0; i < m_nInks; ++i) + // InkOutP[i] *= m_colortable->GetInverseNormFactor(); //[0-100] + ApplyCTInvLinearCurves(InkOutP, InkOutP); //full range % in Color Table Space // //Inks are now nonlinear + } + else + { + Thread2ColorTableunits(NLInkP, InkOut); //full range color table units + VectorToDouble(InkOut, InkOutP); //full range color table units + } + } + + for (int i = 0; i < m_nInks; ++i) + Ink4RGB[i] = InkOutP[i]; + //July 29 2020 + //Inks are limited in their nonlinear form + //Ink4Vol is in Thread units + + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int j = 0; j < m_nProcessRanges; ++j) + { + m_CurrentProcessRangesMax[j] = m_ProcessRangesMaxP[j]; + m_CurrentProcessRangesMin[j] = m_ProcessRangesMinP[j]; + } + LimitInks(Ink4Vol, InkOutP); //in [nl/cm] nonlinear inks // Color table Space + NLInkPToVolume(DoubleToVector(InkOutP, m_nInks), VolumeNoLI); //VolumeNoLI in [nl/cm] + GamutRegion = GetGamutRegion(VolumeNoLI, m_ProcessRangesMaxP); + NLcmtoPercentage(VolumeNoLI, VolumeNoLI); //VolumeNoLI in % + + //Convert to RGB + //GamutRegion = 0; + //Convert to Lab + double *LabOutP = new double[3]; + //InkOutP has to be normalized to match the transform units + + double *tmpval = m_colortable->GetInverseNormFactor(); + if (m_colortable->GetTableSubVersion() > 0) + { + for (int i = 0; i < m_nInks; ++i) + Ink4RGB[i] *= tmpval[i]; //[0-100] range, same as Color Table + + ApplyCTLinearCurves(Ink4RGB, Ink4RGB); //Use Color Table Curves //full range % Linear + tmpval = m_colortable->GetInverseNormFactor(); + for (int i = 0; i < m_nInks; ++i) // Forward Model in [0-1] interval + { + Ink4RGB[i] *= tmpval[i]; //[0-100] range, same as Color Table + Ink4RGB[i] /= 100.0; + } + m_forwardmodel->CalcFM(Ink4RGB, LabOutP); + } + else + { + for (int i = 0; i < m_nInks; ++i) + Ink4RGB[i] *= tmpval[i]; //[0-100] range, same as Color Table + m_colortable->m_A2BTransform->evalInkP2Lab(Ink4RGB, LabOutP, GamutRegion); + + } + + //LabOutP is in Relative Colorimetric + ColorConvert CConvertD65(D65, D65); +// double *LabOutFinal1 = new double[3]; + double *LabOutFinal = new double[3]; + + CConvertD65.ChangeWP(LabOutP, LabOutFinal, m_whitepointXYZ_Strip, m_WP); //To Absolute +/* for (int i = 0; i < 3; ++i) + m_LabOutFinal[i] = LabOutFinal1[i]; */ + + LabOut = DoubleToVector(LabOutFinal, 3); + + CConvertD65.SetReferenceWhite(D65); + double *RGBOutP = new double[3]; + + CConvertD65.LabtoRGB(LabOutP, RGBOutP); + + for (int i = 0; i < 3; ++i) + { + RGBOut(i) = RGBOutP[i]; + } + + + for (int i = 0; i < m_nInks; ++i) + VolumeNoLI(i) = FinalVolumeNoLI(i); + if (InkOutP != NULL) + { + delete[]InkOutP; + InkOutP = NULL; + } + if (LinInkP != NULL) + { + delete[]LinInkP; + LinInkP = NULL; + } + if (LabOutP != NULL) + { + delete[] LabOutP; + LabOutP = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } +/* if (LabOutFinal1 != NULL) + { + delete[] LabOutFinal1; + LabOutFinal1 = NULL; + }*/ + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } + if (Ink4RGB != NULL) + { + delete[] Ink4RGB; + Ink4RGB = NULL; + } + return; + +} + +void Tango::ColorLib::ColorConverter::VectorToDouble(VectorXd VecIn, double * doubOut) +{ + int nSize = VecIn.size(); + for (int i = 0; i < nSize; ++i) + doubOut[i] = VecIn(i); +} + + +VectorXd Tango::ColorLib::ColorConverter::DoubleToVector(double *doub, int nSize) +{ + VectorXd Vec(nSize); + for (int i = 0; i < nSize; ++i) + Vec(i) = doub[i]; + 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) +{ + + ConversionInput* conversionInput = NULL; + InputLiquid** original_input_liquids = NULL; + int original_input_liquids_count = 0; + + try + { + //Get Input + int numofInks = 0; + int numLightInks = 0; + conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); + //Filter and arrange colors (Should change from 3 to 4 if black ink is included) + size_t retValue = InitConvertLiquids(conversionInput, original_input_liquids, numofInks, numLightInks); + + //Initialize Output... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + conversion_output__init(conversionOutput); + + size_t n_elements = 0; + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + + // Read Color Transformations + if (m_colortable == NULL) + m_colortable = new ColorTable(); + readColorTransformations(conversionInput); + + //Set Process Ranges + if (conversionInput->n_processranges <= 0) + throw std::exception("number of process ranges is zero"); + else + m_nProcessRanges = conversionInput->n_processranges; + + double *tmpVal; + /* if (m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetNormGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = tmpVal[i]; */ + + if (m_GamutRegionMaxLim == NULL) + m_GamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_GamutRegionMaxLim[i] = tmpVal[i]; + + if (m_GamutRegionMinLim == NULL) + m_GamutRegionMinLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetGamutRegionMinLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_GamutRegionMinLim[i] = tmpVal[i]; + + //read calibration tables and store them in m_CalibCurves + InputLiquid **inputliquids = conversionInput->inputcoordinates->inputliquids; + // int n_inputliquids = conversionInput->inputcoordinates->n_inputliquids; + int n_inputliquids = numofInks - numLightInks; + readCalibrationTables(inputliquids, n_inputliquids); + + //Define Parameters for Direct Inversion + if(m_colortable->GetTableSubVersion()>0) + { + C_RGB_XYZ_Lab whitepoint_CT = m_colortable->GetWhitePoint_CT(); + m_forwardmodel = m_colortable->GetForwardModel(); + ColorConvert CConvertD65(D65, D65); + C_RGB_XYZ_Lab relWP_CT; + CConvertD65.ChangeWP(whitepoint_CT, relWP_CT, m_WP, m_whitepointXYZ_Strip); + m_forwardmodel->SetFreeTerm(relWP_CT); + m_ObjFunction = new ObjectiveFunction(m_forwardmodel); + PrepareObjectiveFunctionPars(); + m_Minimize = new LevMar(m_ObjFunction); + m_Minimize->Init(); + m_Minimize->SetMaxIterations(50); + m_Minimize->SetTolerance(0.01); + } + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if (m_Conv02 == NULL) + 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); + + // Compare Strip White point to Color Table White Point + //CompareWhitePoints(); + + if (n_inputliquids != m_nInks) + throw std::exception("Number of available inks does not match ink tables\0"); + + //Tables have been filled + //Set Process Ranges + for (int i = 0; i < m_nProcessRanges; ++i) + { + if (conversionInput->processranges[i]->maxinkuptake <= 0) + throw std::exception("Process Range is zero\0"); + } + double diff = 0; + for (int i = 1; i < m_nProcessRanges; ++i) + { + diff = conversionInput->processranges[i]->maxinkuptake - conversionInput->processranges[i - 1]->maxinkuptake; + if (diff < 0) + throw std::exception("Process Ranges are not monotonic\0"); + } + if (m_ProcessRangesMaxP == NULL) + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMaxP[i] = conversionInput->processranges[i]->maxinkuptake; + } + if (m_ProcessRangesMinP == NULL) + m_ProcessRangesMinP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMinP[i] = conversionInput->processranges[i]->mininkuptake; + } + + if (m_CurrentProcessRangesMax == NULL) + m_CurrentProcessRangesMax = new double[m_nProcessRanges]; + if (m_CurrentProcessRangesMin == NULL) + m_CurrentProcessRangesMin = new double[m_nProcessRanges]; + + //define Low Volume threshold and Light Inks Threshold + m_LightInksThr = conversionInput->vmax; + m_LowVolumeThreshold = m_LightInksThr / DilutionFactor; + m_LowVolHalf = m_LowVolumeThreshold / 2; + //SetLowVolThr_nlcm(); + + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + VectorXd VolumeOut(m_nInks); + //set maxNlPerCM + VectorXd NlperCM(m_nInks); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nInks; ++i) + SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); + m_CTmaxNlPerCM = NlperCM; + double *tmpLF = new double[m_nInks]; + tmpLF = m_colortable->GetCTLiquidFactors(); + for (int i = 0; i < m_nInks; ++i) + m_CTmaxNlPerCM(i) = tmpLF[i]; + if (tmpLF != NULL) + { + delete[] tmpLF; + tmpLF = NULL; + } + + // Set Calibration mode 0 up tp 100%, 1 with High Volume Calib + SetCalibMode(); + //Calculate normalization per ink + SetCalibFactorization(); + m_nVolumes = m_nInks; + int GamutRegion = 0; + //Convert input data to linear inks + ColorSpace colorspace = conversionInput->colorspace; + InputCoordinates *IC = conversionInput->inputcoordinates; + VectorXd VolumeLI(m_TotalNumberofInks); + + if (conversionInput->colorspace == COLOR_SPACE__Volume) + { + ConvertVolumeToRGBDisplay(IC, conversionInput->n_processranges, colorspace, Volume, RGBOut, LabOut, GamutRegion, InGamut); + + } + else if (conversionInput->colorspace == COLOR_SPACE__Catalog) + { + IC->inputliquids[0]->volume = IC->cyan; + IC->inputliquids[1]->volume = IC->magenta; + IC->inputliquids[2]->volume = IC->yellow; + IC->inputliquids[3]->volume = IC->key; + for (int i_hv = 0; i_hv < 4; ++i_hv) + IC->inputliquids[i_hv]->has_volume = true; + + ConvertVolumeToRGBDisplay(IC, conversionInput->n_processranges, colorspace, Volume, RGBOut, LabOut, GamutRegion, InGamut); + } + else + { + if (m_colortable->GetTableSubVersion() > 0) + { + DirectInversion(IC, colorspace, InkOut, RGBOut, Volume, LabOut, + GamutRegion, InGamut, sur, CS); + PercentagetoNLcm(Volume, Volume); //Volume is in Color Table Units + int CTUnits = 1; + GetClosestInk(Volume, GamutRegion, Volume, CTUnits, InGamut); //Input Volume is in [nl/cm] Output Volume is in [%] + ConfineVolumes(Volume); + } + else + { + ConvertColorToLinearInks(conversionInput->inputcoordinates, conversionInput->colorspace, InkOut, RGBOut, + LabOut, GamutRegion, InGamut); + //Inks are in Linear Space , convert to nonlinear by using Calibration Tables, + //data is in full range of color table % + //convert data to the thread range in % + ColorTable2Threadunits(InkOut, InkOut); + int CTUnits = 0; + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_CurrentProcessRangesMax[i] = m_ProcessRangesMaxP[i]; + m_CurrentProcessRangesMin[i] = m_ProcessRangesMinP[i]; + } + if (m_CalibMode == 1) + { + ConvertToNLInks(InkOut, NLInkOut); + LimitNLInks2Volume(NLInkOut, GamutRegion, Volume, CTUnits, InGamut); + } + else + LimitNLInks2Volume(InkOut, GamutRegion, Volume, CTUnits, InGamut); + } + } + //Split Volume into inks and Light Inks + if (m_UseLightInks) + { + SplitVolume(Volume, VolumeLI, GamutRegion); + } + else + { + for (int i = 0; i < m_nInks; ++i) + VolumeLI(i) = Volume(i); + for (int i = m_nInks; i < m_TotalNumberofInks; ++i) + VolumeLI(i) = 0.0; + } + OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(outputCoords); + fillRGB(outputCoords, RGBOut); + fillLab(outputCoords, LabOut); + outputCoords->has_processparameterstableindex = true; + outputCoords->processparameterstableindex = GamutRegion; + fillVolume(outputCoords, VolumeLI); + conversionOutput->has_outofgamut = true; + conversionOutput->outofgamut = !(InGamut); + conversionOutput->singlecoordinates = outputCoords; + + if (conversionInput->generatehive) + { + //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_TotalNumberofInks); + MatrixXd VolumeHive(MatHive, m_TotalNumberofInks); + 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++) + { + 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_TotalNumberofInks; ++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_TotalNumberofInks; + } + 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_TotalNumberofInks; + 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); + +#pragma region Free Conversion Input & Output + + conversionInput->inputcoordinates->inputliquids = original_input_liquids; + conversionInput->inputcoordinates->n_inputliquids = original_input_liquids_count; + + conversion_input__free_unpacked(conversionInput, NULL); + + conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + return (size); + } + catch (const std::exception& e) + { + //Notify Error... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + conversion_output__init(conversionOutput); + + conversionOutput->has_haserror = true; + conversionOutput->haserror = true; + + const char* what = e.what(); + int nWhat = strlen(what); + conversionOutput->errormessage = (char*)malloc(nWhat); + //conversionOutput->errormessage = new char[nWhat]; + for (int i = 0; i < nWhat; ++i) + conversionOutput->errormessage[i] = what[i]; + //strcpy_s(conversionOutput->errormessage, nWhat, what); + + output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(conversionOutput)); + int size = conversion_output__pack(conversionOutput, output_buffer); + +#pragma region Free Conversion Input & Output + + conversionInput->inputcoordinates->inputliquids = original_input_liquids; + conversionInput->inputcoordinates->n_inputliquids = original_input_liquids_count; + + conversion_input__free_unpacked(conversionInput, NULL); + conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + return (size); + } +} + +void Tango::ColorLib::ColorConverter::CountNumberofInks(GradientConversionInput* conversionInput, int &numInks, int &numLightInks) +{ + int nLiquids = conversionInput->n_inputliquids; + // int numberofInks = 0; + //Cyan + int nCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Cyan) + nCyan++; + } + if (nCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Magenta) + nMagenta++; + } + if (nMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Yellow) + nYellow++; + } + if (nYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nBlack = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Black) + nBlack++; + } + if (nBlack > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__LightCyan) + nLightCyan++; + } + if (nLightCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__LightMagenta) + nLightMagenta++; + } + if (nLightMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__LightYellow) + nLightYellow++; + } + if (nLightYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + numInks = nCyan + nMagenta + nYellow + nBlack + nLightCyan + nLightMagenta + nLightYellow; + numLightInks = nLightCyan + nLightMagenta + nLightYellow;; + return; +} + +void Tango::ColorLib::ColorConverter::CountNumberofInks(OutOfGamutInput* conversionInput, int &numInks, int &numLightInks) +{ + int nLiquids = conversionInput->inputcoordinates->n_inputliquids; + // int numberofInks = 0; + //Cyan + int nCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Cyan) + nCyan++; + } + if (nCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Magenta) + nMagenta++; + } + if (nMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Yellow) + nYellow++; + } + if (nYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nBlack = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Black) + nBlack++; + } + if (nBlack > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__LightCyan) + nLightCyan++; + } + if (nLightCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__LightMagenta) + nLightMagenta++; + } + if (nLightMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__LightYellow) + nLightYellow++; + } + if (nLightYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + numInks = nCyan + nMagenta + nYellow + nBlack + nLightCyan + nLightMagenta + nLightYellow; + numLightInks = nLightCyan + nLightMagenta + nLightYellow;; + return; +} + +void Tango::ColorLib::ColorConverter::CountNumberofInks(RecommendedProcessTableInput* conversionInput, int &numInks, int &numLightInks) +{ + int nLiquids = conversionInput->n_inputliquids; + // int numberofInks = 0; + //Cyan + int nCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Cyan) + nCyan++; + } + if (nCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Magenta) + nMagenta++; + } + if (nMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Yellow) + nYellow++; + } + if (nYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nBlack = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__Black) + nBlack++; + } + if (nBlack > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__LightCyan) + nLightCyan++; + } + if (nLightCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__LightMagenta) + nLightMagenta++; + } + if (nLightMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputliquids[i]->liquidtype == LIQUID_TYPE__LightYellow) + nLightYellow++; + } + if (nLightYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + numInks = nCyan + nMagenta + nYellow + nBlack + nLightCyan + nLightMagenta + nLightYellow; + numLightInks = nLightCyan + nLightMagenta + nLightYellow;; + return; +} + +void Tango::ColorLib::ColorConverter::CountNumberofInks(ConversionInput* conversionInput, int &numInks, int &numLightInks) +{ + int nLiquids = conversionInput->inputcoordinates->n_inputliquids; + std::map< LiquidType, int> liquidsToCountMap; + std::map< LiquidType, int> lightLiquidsToCountMap; + numInks = -1; + numLightInks = -1; + for (int i = 0; i < nLiquids; ++i) + { + LiquidType liquidType = conversionInput->inputcoordinates->inputliquids[i]->liquidtype; + if (liquidType == LiquidType::LIQUID_TYPE__LightCyan || liquidType == LiquidType::LIQUID_TYPE__LightMagenta || liquidType == LiquidType::LIQUID_TYPE__LightYellow) + { + if (lightLiquidsToCountMap.find(liquidType) == lightLiquidsToCountMap.end()) + { + lightLiquidsToCountMap[liquidType] = 1; + } + else { + return; + } + } + else if(liquidType == LiquidType::LIQUID_TYPE__Cyan || liquidType == LiquidType::LIQUID_TYPE__Magenta || liquidType == LiquidType::LIQUID_TYPE__Yellow || liquidType == LiquidType::LIQUID_TYPE__Black) + { + if (liquidsToCountMap.find(liquidType) == liquidsToCountMap.end()) + { + liquidsToCountMap[liquidType] = 1; + } + else { + return; + } + } + } + numInks = liquidsToCountMap.size() + lightLiquidsToCountMap.size(); + numLightInks = lightLiquidsToCountMap.size(); + /*int nCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Cyan) + nCyan++; + } + if (nCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Magenta) + nMagenta++; + } + if (nMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Yellow) + nYellow++; + } + if (nYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nBlack = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Black) + nBlack++; + } + if (nBlack > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightCyan = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__LightCyan) + nLightCyan++; + } + if (nLightCyan > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__LightMagenta) + nLightMagenta++; + } + if (nLightMagenta > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + int nLightYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__LightYellow) + nLightYellow++; + } + if (nLightYellow > 1) + { + numInks = -1; + numLightInks = -1; + return; + } + numInks = nCyan + nMagenta + nYellow + nBlack + nLightCyan + nLightMagenta + nLightYellow; + numLightInks = nLightCyan + nLightMagenta + nLightYellow;;*/ + return; +} + +bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord) +{ + 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_colortable->m_GBD->getCenter(); + VectorXd JInLab(3); + JInLab << InLab[0], InLab[1], InLab[2]; + VectorXd JLab = m_Conv02->LabToJab(JInLab, sur); + ctr[0] = -JLab(0) + center.Get_x(); + ctr[1] = -JLab(1) + center.Get_y(); + ctr[2] = -JLab(2) + center.Get_z(); + double *dJLab = new double[3]; + //double *dJLab = DBG_NEW double[3]; + VectorToDouble(JLab, dJLab); + bool intersect = false; + m_colortable->m_GBD->TriangleRayIntersection(dJLab, ctr, intersect, xCoord); + if (intersect) + { + VectorXd V1(3); + VectorXd V2(3); + + V1 << JLab[0], JLab[1], JLab[2]; + V2 << xCoord[0], xCoord[1], xCoord[2]; + V1 = m_Conv02->Jab_2_Lab(V1, CS); + V2 = m_Conv02->Jab_2_Lab(V2, CS); + 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; + xCoord = NULL; + } + if (dJLab != NULL) + { + delete[]dJLab; + dJLab = NULL; + } + return(InGamut); +} + + + + +void Tango::ColorLib::ColorConverter::read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput) +{ + /* + 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 number of Shift Bits + 12 Number of gamut regions + 13 - n CLUT values, uint16 + + 13 - n output tables, uint8 + */ + if (data_size < 32) + { + throw std::exception(" LUT size missmatch"); + return; + } + int bytesread = 0; + // Check for signature + uint8_t *buff = &conversionInput->forwarddata.data[offset]; + Transf->InitData(buff, data_size); + return; +} + + + + + + + +/*void Tango::ColorLib::ColorConverter::CompareWhitePoints() +{ + ColorConvert ColConv(D65, D65); + C_RGB_XYZ_Lab Lab_CT; + C_RGB_XYZ_Lab Lab_Strip; + Lab_CT = ColConv.XYZToLab(m_whitepointXYZ_CT); + Lab_Strip = ColConv.XYZToLab(m_whitepointXYZ_Strip); + VectorXd VLab_CT(3); + VectorXd VLab_Strip(3); + VLab_CT(0) = Lab_CT.Get_x(); + VLab_CT(1) = Lab_CT.Get_y(); + VLab_CT(2) = Lab_CT.Get_z(); + VLab_Strip(0) = Lab_Strip.Get_x(); + VLab_Strip(1) = Lab_Strip.Get_y(); + VLab_Strip(2) = Lab_Strip.Get_z(); + double dECMC; + ColConv.SymmetricaldECMC(VLab_CT, VLab_Strip, dECMC); + if (dECMC > WPTol) + m_AdaptWP = true; + if (m_whitepointXYZ_Strip.Get_x() <= 0 || m_whitepointXYZ_Strip.Get_y() <= 0 || m_whitepointXYZ_Strip.Get_z()<=0) + m_AdaptWP = false; + return; +} */ /* not used*/ + +//size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +//{ +// //Unpack conversion input... +// ConversionInput* conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); +// +// //Initialize Output... +// ConversionOutput conversionOutput = CONVERSION_OUTPUT__INIT; +// +// //The request is for RGB to Volume... +// if (conversionInput->colorspace == COLOR_SPACE__RGB) +// { +// //Get RGB values... +// int r = conversionInput->inputcoordinates->red; +// int g = conversionInput->inputcoordinates->green; +// int b = conversionInput->inputcoordinates->blue; +// +// //iterate over input liquids... +// for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) +// { +// InputLiquid* inputLiquid = conversionInput->inputcoordinates->inputliquids[i]; +// +// //Get cyan liquid for example... +// if (inputLiquid->liquidtype == LIQUID_TYPE__Cyan) +// { +// //Get liquid max nl per cm. +// double maxNlPerCM = inputLiquid->maxnanoliterpercentimeter; +// +// //Get liquid calibration data. +// CalibrationData* calibrationData = inputLiquid->calibrationdata; +// +// //Iterate over calibration points.. +// for (size_t j = 0; j < calibrationData->n_calibrationpoints; j++) +// { +// //Calibration Point +// CalibrationPoint* point = calibrationData->calibrationpoints[j]; +// +// double x = point->x; +// double y = point->y; +// } +// } +// } +// +// //Set conversion output with proper volumes... +// +// //Set Cyan liquid volume... +// OutputLiquid cyanLiquid = OUTPUT_LIQUID__INIT; +// cyanLiquid.has_volume = true; +// cyanLiquid.has_liquidtype = true; +// cyanLiquid.liquidtype = LIQUID_TYPE__Cyan; +// cyanLiquid.volume = 20; +// +// //Set Magenta liquid volume... +// OutputLiquid magentaLiquid = OUTPUT_LIQUID__INIT; +// magentaLiquid.has_volume = true; +// magentaLiquid.has_liquidtype = true; +// magentaLiquid.liquidtype = LIQUID_TYPE__Magenta; +// magentaLiquid.volume = 30; +// +// OutputLiquid** outputLiquids = (OutputLiquid**)malloc(sizeof(OutputLiquid*) * 2); +// +// //Add cyan and magenta to output liquids array. +// outputLiquids[0] = &cyanLiquid; +// outputLiquids[1] = &magentaLiquid; +// +// OutputCoordinates outCoords; +// outCoords.outputliquids = outputLiquids; +// +// conversionOutput.singlecoordinates = &outCoords; +// } +// +// +// +// //The request is for volumes to RGB... +// else if (conversionInput->colorspace == COLOR_SPACE__Volume) +// { +// //iterate over input liquids... +// for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) +// { +// InputLiquid* inputLiquid = conversionInput->inputcoordinates->inputliquids[i]; +// +// //Get cyan liquid for example... +// if (inputLiquid->liquidtype == LIQUID_TYPE__Cyan) +// { +// //Get liquid max nl per cm. +// double maxNlPerCM = inputLiquid->maxnanoliterpercentimeter; +// +// //Get liquid volume. +// double volume = inputLiquid->volume; +// +// //Get liquid calibration data. +// CalibrationData* calibrationData = inputLiquid->calibrationdata; +// +// //Iterate over calibration points.. +// for (size_t j = 0; j < calibrationData->n_calibrationpoints; j++) +// { +// //Calibration Point +// CalibrationPoint* point = calibrationData->calibrationpoints[j]; +// +// double x = point->x; +// double y = point->y; +// } +// } +// else if (inputLiquid->liquidtype == LIQUID_TYPE__Magenta) +// { +// //Same as above... +// } +// } +// +// //Set conversion output (single) with proper RGB values... +// OutputCoordinates outputCoords = OUTPUT_COORDINATES__INIT; +// outputCoords.has_red = true; +// outputCoords.has_green = true; +// outputCoords.has_blue = true; +// outputCoords.red = 50; +// outputCoords.green = 100; +// outputCoords.blue = 150; +// +// conversionOutput.singlecoordinates = &outputCoords; +// +// //Set conversion output (hive) with proper RGB values... +// +// int hiveCellCount = 10; +// +// OutputCoordinates** hiveCoordinates = (OutputCoordinates**)malloc(sizeof(OutputCoordinates*) * hiveCellCount); +// +// for (size_t i = 0; i < hiveCellCount; i++) +// { +// OutputCoordinates cellCoords = OUTPUT_COORDINATES__INIT; +// cellCoords.has_red = true; +// cellCoords.has_green = true; +// cellCoords.has_blue = true; +// cellCoords.red = 10; +// cellCoords.green = 20; +// cellCoords.blue = 30; +// +// hiveCoordinates[i] = &cellCoords; +// } +// +// conversionOutput.hivecoordinates = hiveCoordinates; +// } +// +// //Pack output... +// output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(&conversionOutput)); +// +// 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) +{ + + //Get Input + ConversionInput* conversionInput = (ConversionInput*)malloc(sizeof(ConversionInput)); + + conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); + + + + //Filter and arrange colors (Should change from 3 to 4 if black ink is included) + /*int expected_liquids = 3; + + 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; + } + } + + conversionInput->inputcoordinates->inputliquids = filteredInputLiquids; + conversionInput->inputcoordinates->n_inputliquids = expected_liquids; + //Filter and arrange colors + + */ + + //Initialize Output... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + if (conversionOutput != NULL) + conversion_output__init(conversionOutput); + else + return(0); + + // 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 = 0; + int numLightInks = 0; + if (m_colortable == NULL) + m_colortable = new ColorTable(); + + + CountNumberofInks(conversionInput, numofInks, numLightInks); + readColorTransformations(conversionInput); + + //read calibration tables and store them in m_CalibCurves + int n_inputliquids = numofInks - numLightInks; + InputLiquid **inputliquid = conversionInput->inputcoordinates->inputliquids; + //Read CMYK Calibration Tables only. Light Inks have no calibration tables + + readCalibrationTables(inputliquid, n_inputliquids); + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if (m_Conv02 == NULL) + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + + if ((numofInks - numLightInks) != m_nInks) + throw std::exception("Number of available inks does not match ink tables"); + + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + + C_RGB_XYZ_Lab DataLab; + 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 = new double[3]; + double *RGBOutP = new double[3]; + VectorToDouble(RGBOut, RGBOutP); + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Absolute Colorimetric, D65 + double *LabInFinal2 = new double[3]; + LimitLab(LabIn); + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); + //Is In Gamut? + InGamut = IsInGamut(LabInFinal2, sur, CS, LabInFinal2); + LimitLab(LabInFinal2); + + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + if(LabInFinal2 != NULL) + { + delete[] LabInFinal2; + LabInFinal2 = 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 + + 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 *LabInFinal2 = new double[3]; + //double *LabInFinal2 = DBG_NEW double[3]; + // CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //to Relative + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //to Relative + InGamut = IsInGamut(LabInFinal2, sur, CS, LabInFinal2); + LimitLab(LabInFinal2); + + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (LabInFinal2 != NULL) + { + delete[]LabInFinal2; + LabInFinal2 = NULL; + } + break; + } + case(COLOR_SPACE__CMYK): + case(COLOR_SPACE__Volume): + case(COLOR_SPACE__Catalog): + {//no conversion + //missing from structure light inks or special colors + // just convert Lab for rgb display + InGamut = true; + } + default: + { + throw std::exception(" Unsupported Color Space"); + return(0); + } + } + + //Pack data + OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(outputCoords); + conversionOutput->has_outofgamut = true; + conversionOutput->outofgamut = !(InGamut); + conversionOutput->singlecoordinates = outputCoords; + + //Pack output... + output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(conversionOutput)); + int size = conversion_output__pack(conversionOutput, output_buffer); + +#pragma region Free Conversion Input & Output + + //conversionInput->inputcoordinates->inputliquids = original_input_liquids; + //conversionInput->inputcoordinates->n_inputliquids = original_input_liquids_count; + + conversion_input__free_unpacked(conversionInput, NULL); + + conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + return (size); +} + + +size_t Tango::ColorLib::ColorConverter::GenerateGradient(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +{ + GradientConversionInput* conversionInput = NULL; + GradientConversionOutput *conversionOutput = NULL; + InputLiquid** original_input_liquids = NULL; + int original_input_liquids_count = 0; + try + { + //Get Input... + GradientConversionInput* conversionInput = (GradientConversionInput*)malloc(sizeof(GradientConversionInput)); + conversionInput = gradient_conversion_input__unpack(NULL, input_buffer_size, input_buffer); + //Initialize Output... + GradientConversionOutput *conversionOutput = (GradientConversionOutput*)malloc(sizeof(GradientConversionOutput)); + gradient_conversion_output__init(conversionOutput); + + conversionOutput->haserror = false; + conversionOutput->has_haserror = false; + //Get segment length... + double segmentLength = conversionInput->segmentlength; + if (m_colortable == NULL) + m_colortable = new ColorTable(); + PrepareGradient(conversionInput, conversionOutput); + + //Pack output... + output_buffer = (uint8_t*)malloc(gradient_conversion_output__get_packed_size(conversionOutput)); + int size = gradient_conversion_output__pack(conversionOutput, output_buffer); + + //RELEASE MEMORY HERE !!! +#pragma region Free Conversion Input & Output + + gradient_conversion_input__free_unpacked(conversionInput, NULL); + + gradient_conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + 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(); + int nWhat = strlen(what); + conversionOutput->errormessage = (char*)malloc(nWhat); + //conversionOutput->errormessage = new char[nWhat]; + for (int i = 0; i < nWhat; ++i) + conversionOutput->errormessage[i] = what[i]; + + output_buffer = (uint8_t*)malloc(gradient_conversion_output__get_packed_size(conversionOutput)); + int size = gradient_conversion_output__pack(conversionOutput, output_buffer); + +#pragma region Free Conversion Input & Output + if (conversionInput != NULL) + { + conversionInput->inputliquids = original_input_liquids; + conversionInput->n_inputliquids = original_input_liquids_count; + + gradient_conversion_input__free_unpacked(conversionInput, NULL); + } + gradient_conversion_output__free_unpacked(conversionOutput, NULL); + + +#pragma endregion + + return (size); + } +} + +void Tango::ColorLib::ColorConverter::fillGradientStops(GradientConversionInput *conversionInput) +{ + C_RGB_XYZ_Lab RGB; + C_RGB_XYZ_Lab Lab; + for (int i = 0; i < m_nGradStops; ++i) + { + switch (conversionInput->stops[i]->colorspace) + { + case COLOR_SPACE__RGB: //Case RGB + RGB = C_RGB_XYZ_Lab(conversionInput->stops[i]->red, conversionInput->stops[i]->green, conversionInput->stops[i]->blue); + m_GradStops[i].Set_RGB(RGB); + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__RGB); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + break; + case COLOR_SPACE__LAB: //Case LAB + Lab = C_RGB_XYZ_Lab(conversionInput->stops[i]->l, conversionInput->stops[i]->a, conversionInput->stops[i]->b); + m_GradStops[i].Set_Lab(Lab); + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__LAB); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + break; + case COLOR_SPACE__Catalog: + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__Catalog); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + m_GradStops[i].SetCatalogInkValues(conversionInput->stops[i]->cyan, 0); + m_GradStops[i].SetCatalogInkValues(conversionInput->stops[i]->magenta, 1); + m_GradStops[i].SetCatalogInkValues(conversionInput->stops[i]->yellow,2); + m_GradStops[i].SetCatalogInkValues(conversionInput->stops[i]->key, 3); + break; + case COLOR_SPACE__Volume: //Case Volume // No Light Inks implementation for Volume + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__Volume); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + for (int j = 0; j < m_TotalNumberofInks; j++) + { + LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j]; + + switch (liquidVolume->liquidtype) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + case LIQUID_TYPE__LightCyan: + case LIQUID_TYPE__LightMagenta: + case LIQUID_TYPE__LightYellow: + { + m_GradStops[i].SetVolumeValue(liquidVolume->volume, j); + break; + } + default: + throw std::exception("could not fill all volumes"); + } + } + break; + } + } +} + + +void Tango::ColorLib::ColorConverter::findStops(Gradient &GradStop1, Gradient &GradStop2, double dEThr, int ninterstops, + int &nOut, double **VecRGBOut, double **VecLabOut, double *posOut) +{ + ColorConvert CConvertD65(D65, D65); + C_RGB_XYZ_Lab RGBStart = GradStop1.Get_RGB(); + C_RGB_XYZ_Lab RGBEnd = GradStop2.Get_RGB(); + C_RGB_XYZ_Lab LowLab(0, -128, -128); + C_RGB_XYZ_Lab HighLab(100, 127, 127); + C_RGB_XYZ_Lab LowRGB(0, 0, 0); + C_RGB_XYZ_Lab HighRGB(255, 255, 255); + C_RGB_XYZ_Lab LabStart = GradStop1.Get_Lab(); + C_RGB_XYZ_Lab LabEnd = GradStop2.Get_Lab(); + int nsubdiv = 101; + C_RGB_XYZ_Lab dRGB((RGBEnd.Get_x() - RGBStart.Get_x()) / (nsubdiv - 1), (RGBEnd.Get_y() - RGBStart.Get_y()) / (nsubdiv - 1), + (RGBEnd.Get_z() - RGBStart.Get_z()) / (nsubdiv - 1)); + C_RGB_XYZ_Lab dLab((LabEnd.Get_x() - LabStart.Get_x()) / (nsubdiv - 1), (LabEnd.Get_y() - LabStart.Get_y()) / (nsubdiv - 1), + (LabEnd.Get_z() - LabStart.Get_z()) / (nsubdiv - 1)); + + C_RGB_XYZ_Lab *VecLabOut_tmp = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab *VecRGBOut_tmp = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab *VecLabOut_fin = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab *VecRGBOut_fin = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab RGBTmp; + C_RGB_XYZ_Lab LabTmp; + // make a vector of RGB values with 100 subdivisions + // make a matching Lab vector; + + VecRGBOut_tmp[0] = C_RGB_XYZ_Lab(RGBStart); + VecLabOut_tmp[0] = C_RGB_XYZ_Lab(GradStop1.Get_Lab()); + int Stop1Index = 0; + int Stop2Index = nsubdiv; + if ((!GradStop1.Get_InRGBLimits()) && (!GradStop2.Get_InRGBLimits())) + { + //use Lab Coords + for (int i = 1; i < nsubdiv; ++i) + { + VecLabOut_tmp[i].Set(VecLabOut_tmp[i - 1].Get_x() + dLab.Get_x(), + VecLabOut_tmp[i - 1].Get_y() + dLab.Get_y(), + VecLabOut_tmp[i - 1].Get_z() + dLab.Get_z()); + VecRGBOut_tmp[i] = m_Conv02->LabtoRGB(VecLabOut_tmp[i]); + } + Stop1Index = nsubdiv; + Stop2Index = 0; + } + else + { + if (!GradStop1.Get_InRGBLimits()) + { + bool retValue = false; + int i_index = 0; + LabTmp.Set(GradStop1.Get_Lab().Get_x() + i_index * dLab.Get_x(), + GradStop1.Get_Lab().Get_y() + i_index * dLab.Get_y(), + GradStop1.Get_Lab().Get_z() + i_index * dLab.Get_z()); + while ((!retValue) & (i_index < nsubdiv)) + { + retValue = CheckLabInRGBGamut(LabTmp); + i_index++; + LabTmp.Set(GradStop1.Get_Lab().Get_x() + i_index * dLab.Get_x(), + GradStop1.Get_Lab().Get_y() + i_index * dLab.Get_y(), + GradStop1.Get_Lab().Get_z() + i_index * dLab.Get_z()); + } + Stop1Index = i_index; + } + + if (!GradStop2.Get_InRGBLimits()) + { + bool retValue = false; + int i_index = 0; + LabTmp.Set(GradStop2.Get_Lab().Get_x() - i_index * dLab.Get_x(), + GradStop2.Get_Lab().Get_y() - i_index * dLab.Get_y(), + GradStop2.Get_Lab().Get_z() - i_index * dLab.Get_z()); + while ((!retValue) & (i_index < nsubdiv)) + { + retValue = CheckLabInRGBGamut(LabTmp); + i_index++; + LabTmp.Set(GradStop2.Get_Lab().Get_x() - i_index * dLab.Get_x(), + GradStop2.Get_Lab().Get_y() - i_index * dLab.Get_y(), + GradStop2.Get_Lab().Get_z() - i_index * dLab.Get_z()); + } + Stop2Index -= (i_index - 1); + } + //Base vector on Lab + for (int i = 1; i < Stop1Index; ++i) + { + VecLabOut_tmp[i].Set(VecLabOut_tmp[i - 1].Get_x() + dLab.Get_x(), + VecLabOut_tmp[i - 1].Get_y() + dLab.Get_y(), + VecLabOut_tmp[i - 1].Get_z() + dLab.Get_z()); + VecRGBOut_tmp[i] = m_Conv02->LabtoRGB(VecLabOut_tmp[i]); + } + //recalculate dRGB + int SI1 = Stop1Index; + int SI2 = Stop2Index; + C_RGB_XYZ_Lab LabStop1(LabStart.Get_x() + SI1 * dLab.Get_x(), + LabStart.Get_y() + SI1 * dLab.Get_y(), LabStart.Get_z() + SI1 * dLab.Get_z()); + C_RGB_XYZ_Lab LabStop2(LabStart.Get_x() + (SI2 - 1) * dLab.Get_x(), + LabStart.Get_y() + (SI2 - 1) * dLab.Get_y(), LabStart.Get_z() + (SI2 - 1) * dLab.Get_z()); + C_RGB_XYZ_Lab RGBStop1 = m_Conv02->LabtoRGB(LabStop1); + C_RGB_XYZ_Lab RGBStop2 = m_Conv02->LabtoRGB(LabStop2); + int nelems = Stop2Index - Stop1Index; + dRGB = C_RGB_XYZ_Lab((RGBStop2.Get_x() - RGBStop1.Get_x()) / (nelems - 1), (RGBStop2.Get_y() - RGBStop1.Get_y()) / (nelems - 1), + (RGBStop2.Get_z() - RGBStop1.Get_z()) / (nelems - 1)); + + int STi = 0; + for (int i = 0; i < nelems; ++i) + { + STi = Stop1Index + i; + VecRGBOut_tmp[STi].Set(RGBStop1.Get_x() + i * dRGB.Get_x(), + RGBStop1.Get_y() + i * dRGB.Get_y(), + RGBStop1.Get_z() + i * dRGB.Get_z()); + VecLabOut_tmp[STi] = CConvertD65.RGBtoLab(VecRGBOut_tmp[STi]); + VecLabOut_tmp[STi].Clamp(LowLab, HighLab); + } + for (int i = Stop2Index; i < nsubdiv; ++i) + { + VecLabOut_tmp[i].Set(VecLabOut_tmp[i - 1].Get_x() + dLab.Get_x(), + VecLabOut_tmp[i - 1].Get_y() + dLab.Get_y(), + VecLabOut_tmp[i - 1].Get_z() + dLab.Get_z()); + VecRGBOut_tmp[i] = m_Conv02->LabtoRGB(VecLabOut_tmp[i]); + } + } + int indGrad = 0; + int *pos = new int[ninterstops]; + int i1 = 1; + int j1 = 1; + VecLabOut_fin[indGrad] = VecLabOut_tmp[0]; + VecRGBOut_fin[indGrad] = VecRGBOut_tmp[0]; + pos[indGrad] = 0; + double dE = 0.0; + double dEOld = 0.0; + while ((i1 < nsubdiv) & (indGrad < ninterstops - 1)) + { + dEOld = dE; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[i1], dE); + j1 = i1; + while (dE < dEThr && i1 < nsubdiv && j1 < nsubdiv) + { + j1++; + dEOld = dE; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[j1], dE); + } + if (j1 > i1) + { + j1--; + indGrad++; + VecRGBOut_fin[indGrad] = VecRGBOut_tmp[j1]; + VecLabOut_fin[indGrad] = VecLabOut_tmp[j1]; + pos[indGrad] = j1; + dE = dEOld; + i1 = j1 + 1; + } + else + { + dEOld = dE; + if((i1 Stop2Index)) + { + while (dE >= dEThr && i1 < nsubdiv) + { + //get intermediate point + LabTmp.Set((VecLabOut_tmp[i1].Get_x() + VecLabOut_fin[indGrad].Get_x()) / 2.0, + (VecLabOut_tmp[i1].Get_y() + VecLabOut_fin[indGrad].Get_y()) / 2.0, + (VecLabOut_tmp[i1].Get_z() + VecLabOut_fin[indGrad].Get_z()) / 2.0); + RGBTmp = CConvertD65.LabtoRGB(LabTmp); // Lab is in Relative Colorimetric + LabTmp.Clamp(LowLab, HighLab); + //move vectors down by one + for (int i = nsubdiv - 1; i >= i1; --i) + { + VecRGBOut_tmp[i + 1] = VecRGBOut_tmp[i]; + VecLabOut_tmp[i + 1] = VecLabOut_tmp[i]; + } + VecRGBOut_tmp[i1] = RGBTmp; + VecLabOut_tmp[i1] = LabTmp; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[i1], dE); + nsubdiv++; + if(i1 < Stop1Index) + { + Stop1Index++; + Stop2Index++; + } + } + } + else + { + while (dE >= dEThr && i1 < nsubdiv) + { + //get intermediate point + RGBTmp.Set((VecRGBOut_tmp[i1].Get_x() + VecRGBOut_fin[indGrad].Get_x()) / 2.0, + (VecRGBOut_tmp[i1].Get_y() + VecRGBOut_fin[indGrad].Get_y()) / 2.0, + (VecRGBOut_tmp[i1].Get_z() + VecRGBOut_fin[indGrad].Get_z()) / 2.0); + LabTmp = CConvertD65.RGBtoLab(RGBTmp); // Lab is in Relative Colorimetric + LabTmp.Clamp(LowLab, HighLab); + //move vectors down by one + for (int i = nsubdiv - 1; i >= i1; --i) + { + VecRGBOut_tmp[i + 1] = VecRGBOut_tmp[i]; + VecLabOut_tmp[i + 1] = VecLabOut_tmp[i]; + } + VecRGBOut_tmp[i1] = RGBTmp; + VecLabOut_tmp[i1] = LabTmp; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[i1], dE); + nsubdiv++; + Stop2Index++; + } + } + indGrad++; + + VecRGBOut_fin[indGrad] = VecRGBOut_tmp[j1]; + VecLabOut_fin[indGrad] = VecLabOut_tmp[j1]; + pos[indGrad] = j1; + i1 = j1 + 1; + } + } + if (indGrad < ninterstops) + nOut = indGrad + 1; + else + { + throw std::exception("Number of subdivisions exceeds allocation"); + if (VecLabOut_tmp != NULL) + { + delete[] VecLabOut_tmp; + VecLabOut_tmp = NULL; + } + if (VecRGBOut_tmp != NULL) + { + delete[] VecRGBOut_tmp; + VecRGBOut_tmp = NULL; + } + if (VecLabOut_fin != NULL) + { + delete[] VecLabOut_fin; + VecLabOut_fin = NULL; + } + if (VecRGBOut_fin != NULL) + { + delete[] VecRGBOut_fin; + VecRGBOut_fin = NULL; + } + if (pos != NULL) + { + delete[] pos; + pos = NULL; + } + } + + for (int i = 0; i < nOut; ++i) + { + VecLabOut[i][0] = VecLabOut_fin[i].Get_x(); + VecLabOut[i][1] = VecLabOut_fin[i].Get_y(); + VecLabOut[i][2] = VecLabOut_fin[i].Get_z(); + VecRGBOut[i][0] = VecRGBOut_fin[i].Get_x(); + VecRGBOut[i][1] = VecRGBOut_fin[i].Get_y(); + VecRGBOut[i][2] = VecRGBOut_fin[i].Get_z(); + posOut[i] = pos[i]; + } + //free allocs + if (VecLabOut_tmp != NULL) + { + delete[] VecLabOut_tmp; + VecLabOut_tmp = NULL; + } + if (VecRGBOut_tmp != NULL) + { + delete[] VecRGBOut_tmp; + VecRGBOut_tmp = NULL; + } + if (VecLabOut_fin != NULL) + { + delete[] VecLabOut_fin; + VecLabOut_fin = NULL; + } + if (VecRGBOut_fin != NULL) + { + delete[] VecRGBOut_fin; + VecRGBOut_fin = NULL; + } + if (pos != NULL) + { + delete[] pos; + pos = NULL; + } +} + +void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &Volume, int &GamutRegion, bool same_regions) +{ + size_t nInks = 0; + + C_RGB_XYZ_Lab DataLab; + VectorXd InkOut(m_nInks); + double *normFactor = new double[m_nInks]; + if (!same_regions) + normFactor = m_colortable->GetNormFactor(); + else + { + for (int iInks = 0; iInks < m_nInks; ++iInks) + normFactor[iInks] = 1.0; + } + ColorConvert CConvertD65(D65, D65); //Destination, source + if (colorspace == COLOR_SPACE__RGB) + { + //Convert RGB to Volume, no need to calculate RGBOut and LabOut + //Data is in Relative Colorimetric color space + //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, but will be shown in Relative Colorimetric to the user + + //convert to Lab + double *LabIn = new double[3]; + double *RGBOutP = new double[3]; + RGBOutP[0] = inputcoordinates->red; + RGBOutP[1] = inputcoordinates->green; + RGBOutP[2] = inputcoordinates->blue; + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 + LimitLab(LabIn); + + //convert to inks + int GamutRegion; + double *InkOutP = new double[m_nInks]; + if (same_regions) + { + m_colortable->m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits + InkOut = DoubleToVector(InkOutP, m_nInks); + ColorTable2Threadunits(InkOut, InkOut); + //LimitNLInks2VolumeThr(InkOut, GamutRegion, Volume); + } + else + { + m_colortable->m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval + if (m_CalibMode == 1) + { + VectorXd NLInkOut(m_nInks); + ApplyCTLinearCurves(InkOutP, InkOutP); //Full range Color Table Units + InkOut = DoubleToVector(InkOutP, m_nInks); + ColorTable2Threadunits(InkOut, InkOut); //Full Range Thread Units + ConvertToNLInks(InkOut, InkOut); + //LimitNLInks2Volume(NLInkOut, GamutRegion, Volume); + } + else + { + double *tmpval = m_colortable->GetNormFactor(); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; //Full Range + ColorTable2Threadunits(DoubleToVector(InkOutP, m_nInks) , InkOut); //Full Range + //LimitNLInks2VolumeThr(InkOut, GamutRegion, Volume); + } + } + + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + } + else if (colorspace == COLOR_SPACE__LAB) + { + // Basic assumption: Lab data is in relative colorimetric. No Need to convert + + double *LabIn = new double[3]; + LabIn[0] = inputcoordinates->l; //Relative Colorimetric + LabIn[1] = inputcoordinates->a; + LabIn[2] = inputcoordinates->b; + + //convert to Inks + int GamutRegion; + double *InkOutP = new double[m_nInks]; + if (same_regions) + { + m_colortable->m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval + //for (int i = 0; i < m_nInks; ++i) + // InkOutP[i] *= m_colortable->GetNormFactor(); //Full Range Color Table Units + InkOut = DoubleToVector(InkOutP, m_nInks); + ColorTable2Threadunits(InkOut, InkOut); //Full Range Thread Units + } + else + { + m_colortable->m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval + InkOut = DoubleToVector(InkOutP, m_nInks); + if (m_CalibMode == 1) + { + ApplyCTLinearCurves(InkOutP, InkOutP); //full range Color Table Units + ColorTable2Threadunits(InkOut, InkOut); //full range Thread Units + ConvertToNLInks(InkOut, InkOut); + } + else + { + double *tmpval = m_colortable->GetNormFactor(); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; //Full Range Color Table units + ColorTable2Threadunits(DoubleToVector(InkOutP, m_nInks), InkOut); //full range Thread Units + } + } + + + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + } + else + { + throw std::exception("Unsupported Color Space"); + return; + } + + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_CurrentProcessRangesMax[i] = m_ProcessRangesMaxP[i]; + m_CurrentProcessRangesMin[i] = m_ProcessRangesMinP[i]; + } + LimitNLInks2VolumeThr(InkOut, GamutRegion, Volume); + return; +} + + +void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* conversionInput, GradientConversionOutput *conversionOutput) +{ + //fill input stops... + //All calculations are done in Relative Colorimetric Color Space + m_nGradStops = conversionInput->n_stops; + int numofInks = 0; + int numLightInks = 0; + CountNumberofInks(conversionInput, numofInks, numLightInks); + if (numofInks < 0) + throw std::exception("Duplicate inks"); + m_UseLightInks = false; //Gradients do not use light inks + m_TotalNumberofInks = numofInks; + m_nInks = numofInks - numLightInks; + m_nVolumes = m_TotalNumberofInks; + if (m_GradStops == NULL) + m_GradStops = new Gradient[m_nGradStops]; + for (int i = 0; i < m_nGradStops; ++i) + m_GradStops[i].SetVolumeSize(m_TotalNumberofInks); + + InputCoordinates **inputcoordinates = (InputCoordinates**)malloc(sizeof(InputCoordinates*)*m_nGradStops); + for (int i = 0; i < m_nGradStops; ++i) + { + inputcoordinates[i] = (InputCoordinates*)malloc(sizeof(InputCoordinates)); + input_coordinates__init(inputcoordinates[i]); + } + + fillGradientStops(conversionInput); + GradInput2InputCoords(conversionInput, inputcoordinates); + + //Global Parameters of gradient + SetStripWhitepoint(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + bool has_forwarddata = conversionInput->has_forwarddata; + uint8_t *data = conversionInput->forwarddata.data; + m_nProcessRanges = conversionInput->n_processranges; + m_colortable->InitColorTables(has_forwarddata, data, m_nProcessRanges); + SetNumberofInks(m_colortable->GetnA2BnSepIn()); + double *tmpVal; +/* if (m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetNormGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = tmpVal[i]; */ + + if (m_GamutRegionMaxLim == NULL) + m_GamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_GamutRegionMaxLim[i] = tmpVal[i]; + + //define Low Volume threshold and Light Inks Threshold + m_LightInksThr = 5; //Define as part of conversion input!!!!!!!!!!!!!!!!!!!!!!!!! + m_LowVolumeThreshold = m_LightInksThr / DilutionFactor; + m_LowVolHalf = m_LowVolumeThreshold / 2; + //int n_inputliquids = conversionInput->n_inputliquids; + InputLiquid **inputliquid = conversionInput->inputliquids; + readCalibrationTables(inputliquid, m_nInks); + if (m_colortable->GetTableVersion() <= 1) + { + throw std::exception("Color Table Version does not support gradients\0"); + } + + //finished reading tables and data + //prepare data to construct the gradient + //gradient is calculated in RGB space, thinned out or expanded based on dE criteria + // returns a vector of volumes and offsets + //gradient stops in different gamut region will use regular transformation + //if all stops in gamut region 0 the color Table will be suited to this gamut region + + //prepare input + //if Color Space = lab, fill rgb and calculate volume + volume region + //if color space = rgb, fill lab and calculate volume + volume region + //if color space = Volume, fill lab and RGB, calculate volume region + + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if (m_Conv02 == NULL) + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + + // Compare Strip White point to Color Table White Point + //CompareWhitePoints(); + ColorConvert CConvertD65(D65, D65); //Destination, source + + if (m_ProcessRangesMaxP == NULL) + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMaxP[i] = conversionInput->processranges[i]->maxinkuptake; + } + if (m_ProcessRangesMinP == NULL) + m_ProcessRangesMinP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMinP[i] = conversionInput->processranges[i]->mininkuptake; + } + if (m_CurrentProcessRangesMax == NULL) + m_CurrentProcessRangesMax = new double[m_nProcessRanges]; + if (m_CurrentProcessRangesMin == NULL) + m_CurrentProcessRangesMin = new double[m_nProcessRanges]; + + //SetLowVolThr_nlcm(); + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + VectorXd VolumeOut(m_nInks); + //set maxNlPerCM + VectorXd NlperCM(m_nInks); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nInks; ++i) + SetMaxNLperCM(conversionInput->inputliquids[i]->maxnanoliterpercentimeter, i); + double *tmpLF = new double[m_nInks]; + tmpLF = m_colortable->GetCTLiquidFactors(); + m_CTmaxNlPerCM = NlperCM; + for (int i = 0; i < m_nInks; ++i) + m_CTmaxNlPerCM(i) = tmpLF[i]; + if (tmpLF != NULL) + { + delete[] tmpLF; + tmpLF = NULL; + } + + if (m_GamutRegionMaxLim == NULL) + m_GamutRegionMaxLim = new double[m_nInks]; + if (m_GamutRegionMinLim == NULL) + m_GamutRegionMinLim = new double[m_nInks]; + + // Set Calibration mode 0 up tp 100%, 1 with High Volume Calib + SetCalibMode(); + //Calculate normalization per ink + SetCalibFactorization(); + + //m_nVolumes = m_nB2AnSepOut; + int GamutRegion = 0; +/* for (int i = 0; i < m_nGradStops; ++i) + { + inputcoordinates[i]->n_inputliquids = m_nInks; + inputcoordinates[i]->inputliquids = (InputLiquid**)malloc(sizeof(InputLiquid*) *m_nInks); + for (int j = 0; j < m_nInks; j++) + { + inputcoordinates[i]->inputliquids[j] = (InputLiquid*)malloc(sizeof(InputLiquid)); + input_liquid__init(inputcoordinates[i]->inputliquids[j]); + } + }*/ + ProcessGradientStops(inputcoordinates); + + //are all stops in the same region? + int maxreg = -10; + int minreg = 10; + for (int i = 0; i < m_nGradStops; ++i) + { + GamutRegion = m_GradStops[i].Get_GamutRegion(); + maxreg = std::max(maxreg, GamutRegion); + minreg = std::min(minreg, GamutRegion); + } + //Choose Gamut Region for Gradient calculation + + bool same_regions = true; + if ((maxreg != minreg) | (maxreg > 0)) + same_regions = false; + double dEThr = 0.8; + //find intermediate points + int ninterstops = 300; + double **VecRGBOut = new double*[ninterstops]; + double **VecLabOut = new double*[ninterstops]; + double *posOut = new double[ninterstops]; + for (int i = 0; i < ninterstops; ++i) + { + VecLabOut[i] = new double[3]; + VecRGBOut[i] = new double[3]; + } + int nOut = 0; + + int nmaxstops = ninterstops * m_nGradStops; + + //Allocate temporary storage for all stops and positions + double **AllRGBOut_tmp = new double*[nmaxstops]; + double **AllLabOut_tmp = new double*[nmaxstops]; + double *AllPos_tmp = new double[nmaxstops]; + for (int i = 0; i < nmaxstops; ++i) + { + AllRGBOut_tmp[i] = new double[3]; + AllLabOut_tmp[i] = new double[3]; + } + AllRGBOut_tmp[0][0] = m_GradStops[0].Get_RGB().Get_x(); + AllRGBOut_tmp[0][1] = m_GradStops[0].Get_RGB().Get_y(); + AllRGBOut_tmp[0][2] = m_GradStops[0].Get_RGB().Get_z(); + AllLabOut_tmp[0][0] = m_GradStops[0].Get_Lab().Get_x(); + AllLabOut_tmp[0][1] = m_GradStops[0].Get_Lab().Get_y(); + AllLabOut_tmp[0][2] = m_GradStops[0].Get_Lab().Get_z(); + AllPos_tmp[0] = m_GradStops[0].Get_Offset(); + int ncountStops = 0; + int nPosStops = 0; + double dOffset = 0; + GradOffset OffsetType = EqSpaced; + + for (int iStop = 0; iStop < m_nGradStops - 1; ++iStop) + { + findStops(m_GradStops[iStop], m_GradStops[iStop + 1], dEThr, ninterstops, nOut, VecRGBOut, VecLabOut, posOut); + switch (OffsetType) + { + case EqSpaced: + if (iStop == m_nGradStops - 2) + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset())*GradientEndThr / (nOut - 1); + else + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset()) / (nOut - 1); + for (int jPos = 1; jPos < nOut; ++jPos) + { + nPosStops++; + AllPos_tmp[nPosStops] = m_GradStops[iStop].Get_Offset() + dOffset * jPos; + } + break; + case dESpaced: + if (iStop == m_nGradStops - 2) + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset())*GradientEndThr / posOut[nOut - 1]; + else + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset()) / posOut[nOut - 1]; + for (int jPos = 1; jPos < nOut; ++jPos) + { + nPosStops++; + AllPos_tmp[nPosStops] = m_GradStops[iStop].Get_Offset() + dOffset * posOut[jPos]; + } + break; + } + //store the stops in temporary vector + for (int iCount = 1; iCount < nOut; ++iCount) + { + ncountStops++; + for (int jCS = 0; jCS < 3; ++jCS) + { + VecRGBOut[iCount][jCS] = std::min(std::max(VecRGBOut[iCount][jCS], 0.0), 255.0); + AllRGBOut_tmp[ncountStops][jCS] = VecRGBOut[iCount][jCS]; + AllLabOut_tmp[ncountStops][jCS] = VecLabOut[iCount][jCS]; + } + } + } + //add last point + ncountStops++; + VecRGBOut[nOut][0] = std::min(std::max(m_GradStops[m_nGradStops - 1].Get_RGB().Get_x(), 0.0), 255.0); + VecRGBOut[nOut][1] = std::min(std::max(m_GradStops[m_nGradStops - 1].Get_RGB().Get_y(), 0.0), 255.0); + VecRGBOut[nOut][2] = std::min(std::max(m_GradStops[m_nGradStops - 1].Get_RGB().Get_z(), 0.0), 255.0); + VecLabOut[nOut][0] = m_GradStops[m_nGradStops - 1].Get_Lab().Get_x(); + VecLabOut[nOut][1] = m_GradStops[m_nGradStops - 1].Get_Lab().Get_y(); + VecLabOut[nOut][2] = m_GradStops[m_nGradStops - 1].Get_Lab().Get_z(); + AllPos_tmp[ncountStops] = 1.0; + for (int jCS = 0; jCS < 3; ++jCS) + { + AllRGBOut_tmp[ncountStops][jCS] = VecRGBOut[nOut][jCS]; + AllLabOut_tmp[ncountStops][jCS] = VecLabOut[nOut][jCS]; + } + + if (VecRGBOut != NULL) + { + for (int i = 0; i < ninterstops; ++i) + delete[]VecRGBOut[i]; + delete[]VecRGBOut; + } + if (VecLabOut != NULL) + { + for (int i = 0; i < ninterstops; ++i) + delete[]VecLabOut[i]; + delete[]VecLabOut; + VecLabOut = NULL; + } + if (posOut != NULL) + { + delete[]posOut; + posOut = NULL; + } + + //Store Gradient intermediate data in Input Coordinates type structure. + //Simplify calculations, we only need the ink values, input values are in RGB color space + // Use table according to Gamut Regions, all stops in region 0, use 100%table otherwise use regular table, decrease dyeing speed. + + int nTotalStops = ncountStops + 1; + InputCoordinates **SubStops = (InputCoordinates**)malloc(sizeof(InputCoordinates*)*(nTotalStops)); + + //Calculate and store + for (int iTStops = 0; iTStops < nTotalStops; ++iTStops) + { + SubStops[iTStops] = (InputCoordinates*)malloc(sizeof(InputCoordinates)); + input_coordinates__init(SubStops[iTStops]); + SubStops[iTStops]->l = AllLabOut_tmp[iTStops][0]; + SubStops[iTStops]->a = AllLabOut_tmp[iTStops][1]; + SubStops[iTStops]->b = AllLabOut_tmp[iTStops][2]; + SubStops[iTStops]->red = (int)round(AllRGBOut_tmp[iTStops][0]); + SubStops[iTStops]->green = (int)round(AllRGBOut_tmp[iTStops][1]); + SubStops[iTStops]->blue = (int)round(AllRGBOut_tmp[iTStops][2]); + } + + GradientOutputStop** outputStops = (GradientOutputStop**)malloc(sizeof(GradientOutputStop*) * nTotalStops); + conversionOutput->stops = outputStops; + conversionOutput->n_stops = nTotalStops; + + ColorSpace SubStopsCS = COLOR_SPACE__LAB; + //double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + + //Low Volume Threshold will be applied at the end of the sequence + //This is to avoid smoothing to reduce the ink % below the LowVolume threshold + //In order to keep continuity the simple Low Volume threshold will be applied. + + VectorXd VolumeStop(m_nInks); + MatrixXd MatVolume(nTotalStops, m_nInks); + for (int iS = 0; iS < nTotalStops; ++iS) + { + GradientOutputStop *stop = (GradientOutputStop*)malloc(sizeof(GradientOutputStop)); + gradient_output_stop__init(stop); + ConvertGradStoptoVolume(SubStops[iS], SubStopsCS, + VolumeStop, GamutRegion, same_regions); + //start filling Output + fillStop(stop, VolumeStop, GamutRegion, AllPos_tmp[iS]); + MatVolume.row(iS) = VolumeStop; + outputStops[iS] = stop; + } + //Smooth Volumes + VectorXd VIn(nTotalStops); + VectorXd VOut(nTotalStops); + + int FilterWidth = 7; + for (int iSep = 0; iSep < m_nInks; ++iSep) + { + for (int jStop = 0; jStop < nTotalStops; ++jStop) + VIn(jStop) = MatVolume(jStop, iSep); + SmoothCurveData(VIn, VOut, FilterWidth); + for (int jS = 0; jS < nTotalStops; ++jS) + outputStops[jS]->outputliquids[iSep]->volume = VOut(jS); + } + + //Temp Output + for (int i = 0; i < nTotalStops; ++i) + { + for (int j = 0; j < m_nInks; ++j) + VolumeStop(j) = outputStops[i]->outputliquids[j]->volume; + LimitLowVolumeP(VolumeStop, GamutRegion, VolumeStop); + for (int j = 0; j < m_nInks; ++j) + outputStops[i]->outputliquids[j]->volume = VolumeStop(j); + } + for (int i = 0; i < nTotalStops; ++i) + { + fprintf(stdout, "%d\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%d\t%d\t%d\n", i, + outputStops[i]->offset, outputStops[i]->outputliquids[0]->volume, + outputStops[i]->outputliquids[1]->volume, outputStops[i]->outputliquids[2]->volume, outputStops[i]->outputliquids[3]->volume, + SubStops[i]->l, SubStops[i]->a, SubStops[i]->b, SubStops[i]->red, SubStops[i]->green, SubStops[i]->blue); + } + //release memory + if (AllLabOut_tmp != NULL) + { + for (int i = 0; i < nmaxstops; ++i) + delete[] AllLabOut_tmp[i]; + delete[] AllLabOut_tmp; + AllLabOut_tmp = NULL; + } + if (AllRGBOut_tmp != NULL) + { + for (int i = 0; i < nmaxstops; ++i) + delete[] AllRGBOut_tmp[i]; + delete[] AllRGBOut_tmp; + AllRGBOut_tmp = NULL; + } + if (AllPos_tmp != NULL) + { + delete[] AllPos_tmp; + AllPos_tmp = NULL; + } + + + for (int i = 0; i < m_nGradStops; ++i) + { + input_coordinates__free_unpacked(inputcoordinates[i], NULL); + } + + free(inputcoordinates); + inputcoordinates = NULL; + for (int i = 0; i < nTotalStops; ++i) + { + + input_coordinates__free_unpacked(SubStops[i], NULL); + } + + free(SubStops); + SubStops = NULL; + +} + + + + +void Tango::ColorLib::ColorConverter::fillStop(GradientOutputStop *&stop, VectorXd Volume, int GamutRegion, double Position) +{ + OutputLiquid** outputLiquids = (OutputLiquid**)malloc(sizeof(OutputLiquid*) * m_nVolumes); + for (int i = 0; i < m_nInks; ++i) + { + outputLiquids[i] = (OutputLiquid*)malloc(sizeof(OutputLiquid)); + output_liquid__init(outputLiquids[i]); + switch (m_CalibCurves[i].getInkName()) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + { + outputLiquids[i]->has_volume = true; + outputLiquids[i]->has_liquidtype = true; + outputLiquids[i]->liquidtype = (LiquidType)(m_CalibCurves[i].getInkName()); + outputLiquids[i]->volume = Volume(i); + break; + } + } + } + if (m_nVolumes > m_nInks) + { + for (int i = m_nInks+1; i < m_nVolumes; ++i) + { + outputLiquids[i] = (OutputLiquid*)malloc(sizeof(OutputLiquid)); + output_liquid__init(outputLiquids[i]); + switch (m_CalibCurves[i].getInkName()) + { + case LIQUID_TYPE__LightCyan: + case LIQUID_TYPE__LightMagenta: + case LIQUID_TYPE__LightYellow: + { + outputLiquids[i]->has_volume = true; + outputLiquids[i]->has_liquidtype = true; + outputLiquids[i]->liquidtype = (LiquidType)(m_CalibCurves[i].getInkName()); + outputLiquids[i]->volume = 0.0; + break; + } + default: + throw std::exception("could not fill all volumes"); + } + } + } + stop->outputliquids = outputLiquids; + stop->n_outputliquids = m_nVolumes; + stop->has_processparameterstableindex = true; + stop->processparameterstableindex = GamutRegion; + stop->has_offset = true; + stop->offset = Position; +} + +void Tango::ColorLib::ColorConverter::GradInput2InputCoords(GradientConversionInput *conversionInput, InputCoordinates **inputcoordinates) +{ + for (size_t i = 0; i < conversionInput->n_stops; i++) + { + switch (conversionInput->stops[i]->colorspace) + { + case COLOR_SPACE__RGB: //Case RGB + inputcoordinates[i]->red = conversionInput->stops[i]->red; + inputcoordinates[i]->green = conversionInput->stops[i]->green; + inputcoordinates[i]->blue = conversionInput->stops[i]->blue; + inputcoordinates[i]->has_red = true; + inputcoordinates[i]->has_green = true; + inputcoordinates[i]->has_blue = true; + break; + case COLOR_SPACE__LAB: //Case LAB + inputcoordinates[i]->l = conversionInput->stops[i]->l; + inputcoordinates[i]->a = conversionInput->stops[i]->a; + inputcoordinates[i]->b = conversionInput->stops[i]->b; + inputcoordinates[i]->has_l = true; + inputcoordinates[i]->has_a = true; + inputcoordinates[i]->has_b = true; + break; + case COLOR_SPACE__Catalog: + { + InputLiquid** InputLiquidsIC = (InputLiquid**)malloc(sizeof(InputLiquid*) *m_TotalNumberofInks); + for (int j = 0; j < m_TotalNumberofInks; j++) + { + InputLiquidsIC[j] = (InputLiquid*)malloc(sizeof(InputLiquid)); + input_liquid__init(InputLiquidsIC[j]); + } + + /*LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j];*/ + GradientInputStop *ColorStop = conversionInput->stops[i]; + InputLiquidsIC[0]->volume = ColorStop->cyan; + InputLiquidsIC[0]->liquidtype = LIQUID_TYPE__Cyan; + + InputLiquidsIC[1]->volume = ColorStop->magenta; + InputLiquidsIC[1]->liquidtype = LIQUID_TYPE__Magenta; + + InputLiquidsIC[2]->volume = ColorStop->yellow; + InputLiquidsIC[2]->liquidtype = LIQUID_TYPE__Yellow; + + InputLiquidsIC[3]->volume = ColorStop->key; + InputLiquidsIC[3]->liquidtype = LIQUID_TYPE__Black; + + inputcoordinates[i]->inputliquids = InputLiquidsIC; + inputcoordinates[i]->n_inputliquids = m_TotalNumberofInks; + break; + } + case COLOR_SPACE__Volume: //Case Volume + { + //int size= (int)conversionInput->stops[i]->n_liquidvolumes; + InputLiquid** InputLiquidsIC = (InputLiquid**)malloc(sizeof(InputLiquid*) *m_TotalNumberofInks); + for (int j = 0; j < m_TotalNumberofInks; j++) + { + InputLiquidsIC[j] = (InputLiquid*)malloc(sizeof(InputLiquid)); + input_liquid__init(InputLiquidsIC[j]); + } + for (size_t j = 0; j < (size_t)m_TotalNumberofInks; j++) + { + LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j]; + switch (liquidVolume->liquidtype) + { + case LIQUID_TYPE__Cyan: + // inputcoordinates[i]->inputliquids[0]->volume = liquidVolume->volume; + InputLiquidsIC[0]->volume = liquidVolume->volume; + InputLiquidsIC[0]->liquidtype = LIQUID_TYPE__Cyan; + break; + case LIQUID_TYPE__Magenta: + InputLiquidsIC[1]->volume = liquidVolume->volume; + InputLiquidsIC[1]->liquidtype = LIQUID_TYPE__Magenta; + break; + case LIQUID_TYPE__Yellow: + InputLiquidsIC[2]->volume = liquidVolume->volume; + InputLiquidsIC[2]->liquidtype = LIQUID_TYPE__Yellow; + break; + case LIQUID_TYPE__Black: + InputLiquidsIC[3]->volume = liquidVolume->volume; + InputLiquidsIC[3]->liquidtype = LIQUID_TYPE__Black; + break; + } + + } + inputcoordinates[i]->inputliquids = InputLiquidsIC; + inputcoordinates[i]->n_inputliquids = m_TotalNumberofInks; + break; + } + } + } +} + +void Tango::ColorLib::ColorConverter::RecommendedProcessTableInput2InputCoordinates + (RecommendedProcessTableInput *conversionInput, InputCoordinates **inputcoordinates) +{ + for (size_t i = 0; i < conversionInput->n_stops; i++) + { + switch (conversionInput->stops[i]->colorspace) + { + case COLOR_SPACE__RGB: //Case RGB + inputcoordinates[i]->red = conversionInput->stops[i]->red; + inputcoordinates[i]->green = conversionInput->stops[i]->green; + inputcoordinates[i]->blue = conversionInput->stops[i]->blue; + inputcoordinates[i]->has_red = true; + inputcoordinates[i]->has_green = true; + inputcoordinates[i]->has_blue = true; + break; + case COLOR_SPACE__LAB: //Case LAB + inputcoordinates[i]->l = conversionInput->stops[i]->l; + inputcoordinates[i]->a = conversionInput->stops[i]->a; + inputcoordinates[i]->b = conversionInput->stops[i]->b; + inputcoordinates[i]->has_l = true; + inputcoordinates[i]->has_a = true; + inputcoordinates[i]->has_b = true; + break; + case COLOR_SPACE__Catalog: + inputcoordinates[i]->cyan = conversionInput->stops[i]->cyan; + inputcoordinates[i]->magenta = conversionInput->stops[i]->magenta; + inputcoordinates[i]->yellow = conversionInput->stops[i]->yellow; + inputcoordinates[i]->key = conversionInput->stops[i]->key; + inputcoordinates[i]->has_cyan = conversionInput->stops[i]->has_cyan; + inputcoordinates[i]->has_magenta = conversionInput->stops[i]->has_magenta; + inputcoordinates[i]->has_yellow = conversionInput->stops[i]->has_yellow; + inputcoordinates[i]->has_key = conversionInput->stops[i]->has_key; + break; + case COLOR_SPACE__Volume: //Case Volume + //int size= (int)conversionInput->stops[i]->n_liquidvolumes; + InputLiquid** InputLiquidsIC = (InputLiquid**)malloc(sizeof(InputLiquid*) *m_TotalNumberofInks); + for (int j = 0; j < m_TotalNumberofInks; j++) + { + InputLiquidsIC[j] = (InputLiquid*)malloc(sizeof(InputLiquid)); + input_liquid__init(InputLiquidsIC[j]); + } + for (size_t j = 0; j < (size_t)m_TotalNumberofInks; j++) + { + LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j]; + switch (liquidVolume->liquidtype) + { + case LIQUID_TYPE__Cyan: + // inputcoordinates[i]->inputliquids[0]->volume = liquidVolume->volume; + InputLiquidsIC[0]->volume = liquidVolume->volume; + InputLiquidsIC[0]->liquidtype = LIQUID_TYPE__Cyan; + break; + case LIQUID_TYPE__Magenta: + InputLiquidsIC[1]->volume = liquidVolume->volume; + InputLiquidsIC[1]->liquidtype = LIQUID_TYPE__Magenta; + break; + case LIQUID_TYPE__Yellow: + InputLiquidsIC[2]->volume = liquidVolume->volume; + InputLiquidsIC[2]->liquidtype = LIQUID_TYPE__Yellow; + break; + case LIQUID_TYPE__Black: + InputLiquidsIC[3]->volume = liquidVolume->volume; + InputLiquidsIC[3]->liquidtype = LIQUID_TYPE__Black; + break; + } + + } + inputcoordinates[i]->inputliquids = InputLiquidsIC; + inputcoordinates[i]->n_inputliquids = m_TotalNumberofInks; + } + } +} + +void Tango::ColorLib::ColorConverter::LimitInks(VectorXd inInks, double *BoundedInks) +{ + //convert Ink % to [nl/cm] + //Bound Ink + for (int i = 0; i < m_nInks; ++i) + BoundedInks[i] = std::min(inInks(i)*m_currentMaxNLPerCM(i) / 100.0, m_CurrentProcessRangesMax[m_nProcessRanges - 1]); +} + +void Tango::ColorLib::ColorConverter::NLcmtoPercentage(VectorXd InVolume, VectorXd &OutVolume) +{ + int nInks = InVolume.size(); + for (int i = 0; i < m_nInks; ++i) + OutVolume(i) = 100 * InVolume(i) / m_currentMaxNLPerCM(i); + if (nInks > m_nInks) + for (int igt = m_nInks; igt < m_TotalNumberofInks; ++igt) + OutVolume(igt) = 100 * InVolume(igt) / m_currentMaxNLPerCM(igt - m_nInks); +} + +void Tango::ColorLib::ColorConverter::PercentagetoNLcm(VectorXd InVolume, VectorXd &OutVolume) +{ + int nInks = InVolume.size(); + for (int i = 0; i < m_nInks; ++i) + OutVolume(i) = m_currentMaxNLPerCM(i) * InVolume(i) / 100; + if (nInks > m_nInks) + for (int igt = m_nInks; igt < m_TotalNumberofInks; ++igt) + OutVolume(igt) = m_currentMaxNLPerCM(igt - m_nInks) * InVolume(igt) / 100; +} + +void Tango::ColorLib::ColorConverter::LimitLowVolumeP(VectorXd InVolume, int &GamutRegion, VectorXd &OutVolume) +{ + //convert Volume to nl2cm + for (int i = 0; i < m_nInks; ++i) + InVolume(i) *= (m_maxNlPerCM(i)/100.0); + LimitLowVolume(InVolume, GamutRegion, OutVolume); + NLcmtoPercentage(OutVolume, OutVolume); +} + +void Tango::ColorLib::ColorConverter::LimitLowVolume(VectorXd InVolume, int &GamutRegion, VectorXd &OutVolume) +{ + int indGR = 0; + for (int i = 1; i < m_nProcessRanges; ++i) + { + if (GamutRegion == i) + indGR = i; + } + //InVolume is in [nl/cm] + double TotalVolume = 0.0; + for (int i = 0; i < m_nInks; ++i) + TotalVolume += InVolume(i); + + double low = 0.0; + double high = 0.0; + + if (TotalVolume <= m_ProcessRangesMinP[0]) + { + //Calculate minVolumeThreshold based on m_ProcessRangesMinP[0] + high = m_LowVolumeThreshold * m_ProcessRangesMinP[0]/100.0; + } + else if (TotalVolume <= m_ProcessRangesMaxP[0]) + { + //Calculate minVolumeThreshold based on Total Volume + high = m_LowVolumeThreshold * TotalVolume/100.0; + } + else if (TotalVolume <= m_ProcessRangesMinP[1]) + { + //Calculate minVolumeThreshold based on m_ProcessRangesMinP[1] + high = m_LightInksThr * m_ProcessRangesMinP[1]/100.0; + } + else + { + high = m_LightInksThr * TotalVolume/100.0; + } + //Limit Volume based on Total Ink Volume + double sumVol = 0; + for (int i = 0; i < m_nInks; ++i) + { + if (InVolume(i) >= high) + OutVolume(i) = InVolume(i); + else if (InVolume(i) < (high / 2.0)) + OutVolume(i) = 0.0; + else + OutVolume(i) = high; + sumVol += OutVolume(i); + } + //recalculate GamutRegion + if (sumVol <= m_ProcessRangesMaxP[0]) + GamutRegion = 0; + else + { + for (int i = 1; i < indGR + 1; ++i) + { + if ((sumVol > m_ProcessRangesMaxP[i - 1]) & (sumVol <= m_ProcessRangesMaxP[i])) + GamutRegion = i; + } + } +} + + +int Tango::ColorLib::ColorConverter::GetGamutRegion(VectorXd Volume, double *GamutLimits) +{ // assumes Volume is in [nl/cm] + double TotalVolume = 0.0; + double Volnlcm = 0.0; + int GamutRegion = 0; + int nGR = m_colortable->GetnGamutRegions(); + for (int i = 0; i < m_nInks; ++i) + { + //Volnlcm = m_maxNlPerCM(i)*Volume(i)/100.0; + //TotalVolume += Volnlcm; + TotalVolume += Volume(i); + } + for (int i = 0; i < nGR - 1; ++i) + { + if (TotalVolume > GamutLimits[i]) + GamutRegion++; + } + return(GamutRegion); +} + +void Tango::ColorLib::ColorConverter::SmoothCurveData(VectorXd VIn, VectorXd &VOut, int FilterWidth) +{ + int Vlength = VIn.size(); + VectorXd tmpV(Vlength); + int NumIter = (int)(std::max(FilterWidth, 3) - 2); + //Smooth the data with repeated applications of a[1 1 1] filter + for (int i = 0; i < NumIter; ++i) + { + for (int j = 0; j < Vlength; ++j) + tmpV(j) = VIn(j); + for (int k = 1; k < Vlength - 1; ++k) + VIn(k) = (tmpV(k - 1) + tmpV(k) + tmpV(k + 1)) / 3; + } + for (int j = 0; j < Vlength; ++j) + VOut(j) = VIn(j); +} + +void Tango::ColorLib::ColorConverter::ProcessGradientStops(InputCoordinates **inputcoordinates) +{ + VectorXd Volume(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd InkOut(m_nInks); + VectorXd NLInkOut(m_nInks); + double * InkOutL = new double[m_nInks]; + double * LabOutV = new double[3]; + double * LabOutFinal = new double[3]; + + ColorConvert CConvertD65(D65, D65); + + bool InGamut = true; + int GamutRegion = 0; + for (int i = 0; i < m_nGradStops; ++i) + { + if (m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__Volume || m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__Catalog) + { //Convert volume to Lab + //Convert lab to rgb + ConvertVolumeToRGBDisplay(inputcoordinates[i], m_nProcessRanges, m_GradStops[i].Get_ColorSpace(), Volume, + RGBOut, LabOut, GamutRegion, InGamut); + VectorToDouble(LabOut, LabOutV); + CConvertD65.ChangeWP(LabOutV, LabOutV, m_WP, m_whitepointXYZ_Strip); //to Relative Colorimetric Space + C_RGB_XYZ_Lab Lab(LabOutV[0], LabOutV[1], LabOutV[2]); + C_RGB_XYZ_Lab RGB(RGBOut); // RGB was derived from relative colorimetric Lab Value + + //store data + m_GradStops[i].Set_Lab(Lab); + m_GradStops[i].Set_RGB(RGB); + m_GradStops[i].Set_GamutRegion(GamutRegion); + bool retValue = CheckLabInRGBGamut(Lab); + m_GradStops[i].SetInRGBLimits(retValue); + m_GradStops[i].SetInGamut(InGamut); + } + else + { + ConvertColorToLinearInks(inputcoordinates[i], m_GradStops[i].Get_ColorSpace(), InkOut, RGBOut, LabOut, GamutRegion, InGamut); + //Inks are in Linear Space , convert to nonlinear by using Calibration Tables, + VectorToDouble(LabOut, LabOutV); + CConvertD65.ChangeWP(LabOutV, LabOutV, m_WP, m_whitepointXYZ_Strip); //to Relative Colorimetric Space + C_RGB_XYZ_Lab Lab(LabOutV[0], LabOutV[1], LabOutV[2]); + C_RGB_XYZ_Lab RGB(RGBOut); + //convert data to the thread range in % + ColorTable2Threadunits(InkOut, InkOut); + int CTUnits = 0; + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int iP = 0; iP < m_nProcessRanges; ++iP) + { + m_CurrentProcessRangesMax[iP] = m_ProcessRangesMaxP[i]; + m_CurrentProcessRangesMin[iP] = m_ProcessRangesMinP[i]; + } + + if (m_CalibMode == 1) + { + ConvertToNLInks(InkOut, NLInkOut); + LimitNLInks2Volume(NLInkOut, GamutRegion, Volume, CTUnits, InGamut); + } + else + LimitNLInks2Volume(InkOut, GamutRegion, Volume, CTUnits, InGamut); + + //fill data + //fill volume + //allocate m_GradStops[i].Volume + for (int j = 0; j < m_nInks; ++j) + m_GradStops[i].SetVolumeValue(Volume(j), j); + m_GradStops[i].Set_GamutRegion(GamutRegion); + m_GradStops[i].SetInGamut(InGamut); + //LabOut and RGBOut might be different if the input was out of gamut + m_GradStops[i].Set_Lab(Lab); + m_GradStops[i].Set_RGB(RGB); + LabOutFinal[0] = Lab.Get_x(); + LabOutFinal[1] = Lab.Get_y(); + LabOutFinal[2] = Lab.Get_z(); + bool retValue = CheckLabInRGBGamut(DoubleToVector(LabOutFinal, 3)); + m_GradStops[i].SetInRGBLimits(retValue); + } + } + //free vectors + if (LabOutV != NULL) + { + delete[] LabOutV; + LabOutV = NULL; + } + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } + if (InkOutL != NULL) + { + delete[] InkOutL; + InkOutL = NULL; + } +} + +bool Tango::ColorLib::ColorConverter::CheckLabInRGBGamut(VectorXd Lab) +{ + bool retVal = false; + C_RGB_XYZ_Lab DataLab; + DataLab.Set(Lab); + retVal = CheckLabInRGBGamut(DataLab); + return(retVal); +} + +bool Tango::ColorLib::ColorConverter::CheckLabInRGBGamut(C_RGB_XYZ_Lab Lab) +{ + bool retVal = false; + //ColorConvert ColConv(D65, D65); + C_RGB_XYZ_Lab DataRGB1; + C_RGB_XYZ_Lab DataLab1; + //DataRGB1 limited to [0,255] + DataRGB1 = m_Conv02->LabtoRGB(Lab); + DataLab1 = m_Conv02->RGBtoLab(DataRGB1); + double dE = 0; + m_Conv02->dE76(DataLab1, Lab, dE); + if (dE < 0.01) + retVal = true; + return(retVal); +} + +//void Tango::ColorLib::ColorConverter::SetLowVolThr_nlcm() +//{ +// if (m_LowVolThr_nlcm == NULL) +// m_LowVolThr_nlcm = new double[m_nProcessRanges]; +// if (m_LowVolThrHalf_nlcm == NULL) +// m_LowVolThrHalf_nlcm = new double[m_nProcessRanges]; +// //fill thresholds +// for (int i = 0; i < m_nProcessRanges; ++i) +// { +// m_LowVolThr_nlcm[i] = m_LowVolumeThreshold * m_ProcessRangesMaxP[i]/100; +// m_LowVolThrHalf_nlcm[i] = m_LowVolHalf * m_ProcessRangesMaxP[i]/100; +// } +//} + +void Tango::ColorLib::ColorConverter::LimitNLInks2Volume(VectorXd NLInks, int &GamutRegion, VectorXd &Volume, int CTUnits, bool &InGamut) +{ + //VectorXd NLInkOut(m_nInks); + double *InkOutL = new double[m_nInks]; +// NLInks are in the full thread range + LimitInks(NLInks, InkOutL); // NLInks is in %, InkOutL in [nl/cm] + NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume); // InkOutL in [nl/cm] Volume in [nl/cm] + GamutRegion = GetGamutRegion(Volume, m_CurrentProcessRangesMax); //Volume in [nl/cm] + GetClosestInk(Volume, GamutRegion, Volume, CTUnits, InGamut); //Input Volume is in [nl/cm] Output Volume is in [%] + //NLcmtoPercentage(Volume, Volume); + ConfineVolumes(Volume); // Input Volume is in[%] Output Volume is in[%] + if (InkOutL != NULL) + { + delete[]InkOutL; + InkOutL = NULL; + } +} + +void Tango::ColorLib::ColorConverter::LimitNLInks2VolumeNoFix(VectorXd NLInks, int &GamutRegion, VectorXd &Volume) +{ + //VectorXd NLInkOut(m_nInks); + double *InkOutL = new double[m_nInks]; + // NLInks are in the full thread range + LimitInks(NLInks, InkOutL); // NLInks is in %, InkOutL in [nl/cm] + NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume); // InkOutL in [nl/cm] Volume in [nl/cm] + GamutRegion = GetGamutRegion(Volume, m_CurrentProcessRangesMax); //Volume in [nl/cm] + NLcmtoPercentage(Volume, Volume); //Volume is in % + if (InkOutL != NULL) + { + delete[]InkOutL; + InkOutL = NULL; + } +} + +void Tango::ColorLib::ColorConverter::ConfineVolumes(VectorXd &Volume) +{ + //Round Just Before exting + double TotalVolumeRound = 0; + VectorXd VolumeRound(m_nInks); + double ROUNDINGTol = pow(10, ROUNDINGDigits); + //correct the ink component with the highest volume + double maxInk = -1; + int maxInd = -1; + for (int i = 0; i < m_nInks; ++i) + { + VolumeRound(i) =std::round (Volume(i)*ROUNDINGTol*(m_currentMaxNLPerCM(i) / 100.0))/ ROUNDINGTol; + if (VolumeRound(i) > maxInk) + { + maxInk = VolumeRound(i); + maxInd = i; + } + TotalVolumeRound += VolumeRound(i); + } + int nGR = m_colortable->GetnGamutRegions(); + double ddCorr = 0; + if (TotalVolumeRound > m_CurrentProcessRangesMax[m_nProcessRanges - 1] ) + { + ddCorr = TotalVolumeRound - m_CurrentProcessRangesMax[m_nProcessRanges - 1] ; + VolumeRound(maxInd) = VolumeRound(maxInd) - ddCorr; + } + for (int i = 0; i < m_nInks; ++i) + Volume(i) =VolumeRound(i)*(100/ m_currentMaxNLPerCM(i)); +} + + +void Tango::ColorLib::ColorConverter::LimitNLInks2VolumeThr(VectorXd NLInks, int &GamutRegion, VectorXd &Volume) +{ + // VectorXd NLInkOut(m_nInks); + double *InkOutL = new double[m_nInks]; + LimitInks(NLInks, InkOutL); // InkOutL in [nl/cm] + NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume); // [nl/cm] + GamutRegion = GetGamutRegion(Volume, m_CurrentProcessRangesMax); + LimitLowVolume(Volume, GamutRegion, Volume); // [nl/cm] + NLcmtoPercentage(Volume, Volume); // output volume in % + ConfineVolumes(Volume); + if (InkOutL != NULL) + { + delete[]InkOutL; + InkOutL = NULL; + } +} + +void Tango::ColorLib::ColorConverter::GetClosestInk(VectorXd Volume, int &GamutRegion, VectorXd &BestVolume, int CTUnits, bool &InGamut) +{ + VectorXd LabOut(3); + NumConversions D2B; + double *diffVolume = new double[m_nInks]; + int *LVThrIndex = new int[m_nInks]; + int indCount = -1; + double low = 0.0; + double high = 0.0; + double TotalVolume = 0.0; + for (int i = 0; i < m_nInks; ++i) + TotalVolume += Volume(i); + DefineSplitLimits(low, high, TotalVolume); + for (int i = 0; i < m_nInks; ++i) + { + if (Volume(i) > 1.e-04) + diffVolume[i] = std::abs(Volume(i) - std::max(Volume(i), low)); + else + diffVolume[i] = 0; + if (diffVolume[i] > 1.0E-04) + { + indCount++; + LVThrIndex[indCount] = i; + } + } + + if (diffVolume != NULL) + { + delete[]diffVolume; + diffVolume = NULL; + } + + NLcmtoPercentage(Volume, Volume); + indCount++; + if (indCount > 0) + { + double LabTarget[3]; + InGamut = false; + ConvertVolumeToLabRel(Volume, LabOut, GamutRegion, CTUnits); + VectorToDouble(LabOut, LabTarget); + int pwr2LVThr = (int)pow(2, indCount); + double **VolumeComb = new double*[pwr2LVThr]; + for (int i = 0; i < pwr2LVThr; ++i) + { + VolumeComb[i] = new double[m_nInks]; + for (int j = 0; j < m_nInks; ++j) + VolumeComb[i][j] = Volume(j); + } + int **binPerm = new int*[pwr2LVThr]; + for (int i = 0; i < pwr2LVThr; ++i) + { + binPerm[i] = new int[indCount]; + for (int k = 0; k < indCount; ++k) + binPerm[i][k] = -1; + D2B.DecToBinary(i, binPerm[i], indCount); + } + double *dE = new double[pwr2LVThr]; + double mindE = 10000.0; + int indMindE = -1; + for (int i = 0; i < pwr2LVThr; ++i) + { + for (int j=0; jSymmetricaldECMC(LabOut, DoubleToVector(LabTarget, 3), dE[i]); + if (dE[i] < mindE) + { + mindE = dE[i]; + indMindE = i; + BestVolume = DoubleToVector(VolumeComb[i], m_nInks); + } + } + + if (binPerm != NULL) + { + for (int i = 0; i < pwr2LVThr; ++i) + delete[]binPerm[i]; + delete[]binPerm; + binPerm = NULL; + } + if (VolumeComb != NULL) + { + for (int i = 0; i < pwr2LVThr; ++i) + delete[]VolumeComb[i]; + delete[]VolumeComb; + VolumeComb = NULL; + } + if (dE != NULL) + { + delete[]dE; + dE = NULL; + } + } + else + BestVolume = Volume; + if (LVThrIndex != NULL) + { + delete[] LVThrIndex; + LVThrIndex = NULL; + } +} + +void Tango::ColorLib::ColorConverter::ConvertVolumeToLabRel(VectorXd &Volume, VectorXd &LabOut, int GamutRegion, + int CTUnits) +{ + VectorXd NLInkP(m_nInks); + VectorXd LInkP(m_nInks); + VectorXd InkOut((int)(m_nInks)); + + //Convert to Nonlinear Inks + double SumVol_Ink = 0.0; + //Volume is in [nl/cm] + VolumeToNLInkP(Volume, NLInkP); + double *InkOutP = new double[m_nInks]; + + //Limit inks based on m_maxNlpercm + //Inks are limited in their nonlinear form + + LimitInks(NLInkP, InkOutP); //InkOutP is in [nl/cm] + NLInkPToVolume(DoubleToVector(InkOutP, m_nInks), Volume); //Volume is in [nl/cm] + GamutRegion = GetGamutRegion(Volume, m_CurrentProcessRangesMax); + NLcmtoPercentage(Volume, Volume); //Volume is back to percentage + VolumeToNLInkP(Volume, NLInkP); + //Normalize NLInk to the Color Table Range + if(CTUnits ==0) + Thread2ColorTableunits(NLInkP, NLInkP); + + // Convert to Linear + + double *LabOutP = new double[3]; + + double *tmpval = m_colortable->GetInverseNormFactor(); + + if (m_colortable->GetTableSubVersion() > 0) + { + ConvertToLinearInks(NLInkP, LInkP); + VectorToDouble(LInkP, InkOutP); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; + for (int i = 0; i < m_nInks; ++i) // Forward Model in [0-1] interval + InkOutP[i] /= 100.0; + m_forwardmodel->CalcFM(InkOutP, LabOutP); + } + else + { + VectorToDouble(NLInkP, InkOutP); + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= tmpval[i]; + m_colortable->m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion); + } + //LabOutP is in Relative Colorimetric + ColorConvert CConvertD65(D65, D65); +// double *LabOutFinal1 = new double[3]; + double *LabOutFinal = new double[3]; + + CConvertD65.ChangeWP(LabOutP, LabOutFinal, m_whitepointXYZ_Strip, m_WP); //To Absolute +/* for (int i = 0; i < 3; ++i) + LabOutFinal[i] = LabOutFinal1[i];*/ + + LabOut = DoubleToVector(LabOutFinal, 3); + + if (InkOutP != NULL) + { + delete[]InkOutP; + InkOutP = NULL; + } + + if (LabOutP != NULL) + { + delete[] LabOutP; + LabOutP = NULL; + } + +/* if (LabOutFinal1 != NULL) + { + delete[] LabOutFinal1; + LabOutFinal1 = NULL; + } */ + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } + return; + +} + +void Tango::ColorLib::ColorConverter::SplitVolume(VectorXd Volume, VectorXd &VolumeLI, int &GamutRegion) +{ + //mark split candidates + int ind = 0; + VectorXd Vol_nlcm(m_nInks); + double InitTotalVolume = 0; + double low = 0; + double high = 0; + for (int i = 0; i < m_nInks; ++i) + { + Vol_nlcm(i) = Volume(i)*m_currentMaxNLPerCM(i) / 100; + VolumeLI(i) = Vol_nlcm(i); + InitTotalVolume += Vol_nlcm(i); + } + int indGR = 0; + //Find Gamut Region + for (int i = 1; i < m_nProcessRanges; ++i) + { + if (GamutRegion == i) + indGR = i; + } + //Set Limits + DefineSplitLimits(low, high, InitTotalVolume); + //Verify there are no inks below the split limits + //This might happen because of a previous rounding step that changes the low limit by a small amount + for (int i = 0; i < m_nInks; ++i) + { + if (Vol_nlcm(i) < (low / 2)) + Vol_nlcm(i) = 0.0; + else if ((Vol_nlcm(i) < low) & (Vol_nlcm(i) > (low / 2))) + Vol_nlcm(i) = low; + } + //Apply 1st Split + for (int i = 0; i < m_nInks - 1; ++i) + { + if ((Vol_nlcm(i) >= low) & (Vol_nlcm(i) <= high)) + { + VolumeLI(i + m_nInks) = DilutionFactor * Vol_nlcm(i); + VolumeLI(i) = 0.0; + } + else + { + VolumeLI(i) = Vol_nlcm(i); + VolumeLI(i + m_nInks) = 0; + } + } + double UpperLimit = m_CurrentProcessRangesMax[m_nProcessRanges - 1]; + double TotalVolume = 0.0; + + bool resplit = true; + VectorXd PrevVolume(m_TotalNumberofInks); + VectorXd VolumeNoLI(m_nInks); + for (int i = 0; i < m_nInks; ++i) + PrevVolume(i) = Vol_nlcm(i); + for (int i = m_nInks; i < m_TotalNumberofInks; ++i) + PrevVolume(i) = 0.0; + int PrevGamutRegion = GamutRegion; + double PrevHigh = high; + double PrevLow = low; + while (resplit == true) + { + for (int i = 0; i < m_TotalNumberofInks; ++i) + TotalVolume += VolumeLI(i); + if (TotalVolume > UpperLimit) + { + VolumeLI = PrevVolume; + GamutRegion = PrevGamutRegion; + resplit = false; + } + else if (TotalVolume > InitTotalVolume) + { + DefineSplitLimits(low, high, TotalVolume); + //recalculate Gamut Region + indGR = 0; + findGamutRegion(GamutRegion, TotalVolume); + if (((low - PrevLow) > 0) & ((high - PrevHigh) > 0)) + { + //set Previous Volume + for (int i = 0; i < m_TotalNumberofInks; ++i) + PrevVolume(i) = VolumeLI(i); + PrevGamutRegion = GamutRegion; + PrevLow = low; + PrevHigh = high; + InitTotalVolume = TotalVolume; + //go back to no light inks volumes + for (int i = 0; i < m_nInks - 1; ++i) + { + if ((VolumeLI(i) == 0) & (VolumeLI(i + m_nInks) > 0)) + { + VolumeNoLI(i) = VolumeLI(i + m_nInks) / DilutionFactor; + } + else + { + VolumeNoLI(i) = VolumeLI(i); + } + } + VolumeNoLI(m_nInks - 1) = VolumeLI(m_nInks - 1); + for (int i = 0; i < m_nInks; ++i) + { + if ((VolumeNoLI(i) < low) & (VolumeNoLI(i) > 0)) + VolumeNoLI(i) = low; + } + for (int i = 0; i < m_nInks - 1; ++i) + { + if ((VolumeNoLI(i) >= low) & (VolumeNoLI(i) <= high)) + { + VolumeLI(i + m_nInks) = DilutionFactor * VolumeNoLI(i); + VolumeLI(i) = 0.0; + } + else + { + VolumeLI(i + m_nInks) = 0; + } + } + VolumeLI(m_nInks - 1) = VolumeNoLI(m_nInks - 1); + //recalculate Gamut Region + for (int i = 0; i < m_TotalNumberofInks; ++i) + TotalVolume += VolumeLI(i); + resplit = true; + } + else + resplit = false; + } + else + resplit = false; + } + NLcmtoPercentage(VolumeLI, VolumeLI); +} + +void Tango::ColorLib::ColorConverter::DefineSplitLimits(double &low, double &high, double InitTotalVolume) +{ + //Set Limits + //1st Region + double lim1 = 0; + double lim2 = m_CurrentProcessRangesMax[0]; + double lim3 = m_CurrentProcessRangesMin[0]; + int ProcessRangeInd = 0; + //Regions 1 to n-1 + for (int iReg = 0; iReg < m_nProcessRanges - 1; ++iReg) + { + ProcessRangeInd = iReg; + if ((InitTotalVolume >= lim1) & (InitTotalVolume <= lim2)) + { + //Calculate Ink Split Based on m_ProcessRangesMinP[iReg] + low = m_LowVolumeThreshold * m_CurrentProcessRangesMin[iReg] / 100.0; + high = m_LightInksThr * m_CurrentProcessRangesMin[iReg] / 100.0; + } + else if ((InitTotalVolume <= lim3) & (InitTotalVolume > lim2)) + { + //Calculate Ink Split Based on Total Volume + low = m_LowVolumeThreshold * InitTotalVolume / 100.0; + high = m_LightInksThr * InitTotalVolume / 100.0; + } + lim1 = m_CurrentProcessRangesMax[iReg]; + lim2 = m_CurrentProcessRangesMin[iReg + 1]; + lim3 = m_CurrentProcessRangesMax[iReg + 1]; + } + //Last Region + if ((InitTotalVolume >= lim1) & (InitTotalVolume <= lim2)) + { + //Calculate Ink Split Based on m_ProcessRangesMinP[iReg] + low = m_LowVolumeThreshold * m_CurrentProcessRangesMin[ProcessRangeInd] / 100.0; + high = m_LightInksThr * m_CurrentProcessRangesMin[ProcessRangeInd] / 100.0; + } + else if (InitTotalVolume > lim2) + { + //Calculate Ink Split Based on Total Volume + low = m_LowVolumeThreshold * InitTotalVolume / 100.0; + high = m_LightInksThr * InitTotalVolume / 100.0; + } +} + +void Tango::ColorLib::ColorConverter::findGamutRegion(int &GamutRegion, double TotalVolume) +{ + if (TotalVolume <=m_CurrentProcessRangesMax[0]) + GamutRegion = 0; + else + { + for (int i = 1; i < m_nProcessRanges; ++i) + { + if ((TotalVolume > m_CurrentProcessRangesMax[i - 1]) & (TotalVolume <= m_CurrentProcessRangesMax[i])) + GamutRegion = i; + } + } +} + +size_t Tango::ColorLib::ColorConverter::GetRecommendedProcessParameters(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +{ + RecommendedProcessTableInput* Input = recommended_process_table_input__unpack(NULL, input_buffer_size, input_buffer); + + try + { + //Filter and arrange colors (Should change from 3 to 4 if black ink is included) + int numofInks = 0; + int numLightInks = 0; + CountNumberofInks(Input, numofInks, numLightInks); + if (numofInks < 0) + throw std::exception("Duplicate inks"); + m_UseLightInks = Input->uselightinks; + if ((numLightInks <= 0) & (m_UseLightInks == true)) + throw std::exception("Light Inks not defined"); + + int expected_liquids = numofInks; + m_TotalNumberofInks = numofInks; + int original_input_liquids_count = Input->n_inputliquids; + InputLiquid** original_input_liquids = Input->inputliquids; + if(m_InkNames == NULL) + m_InkNames = new LiquidType[m_TotalNumberofInks]; + InputLiquid** filteredInputLiquids = new InputLiquid*[m_TotalNumberofInks]; + + for (size_t i = 0; i < Input->n_inputliquids; i++) + { + InputLiquid* liquid = Input->inputliquids[i]; + + switch (liquid->liquidtype) + { + case LIQUID_TYPE__Cyan: + filteredInputLiquids[0] = liquid; + m_InkNames[0] = liquid->liquidtype; + break; + case LIQUID_TYPE__Magenta: + filteredInputLiquids[1] = liquid; + m_InkNames[1] = liquid->liquidtype; + break; + case LIQUID_TYPE__Yellow: + filteredInputLiquids[2] = liquid; + m_InkNames[2] = liquid->liquidtype; + break; + case LIQUID_TYPE__Black: + filteredInputLiquids[3] = liquid; + m_InkNames[3] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightCyan: + filteredInputLiquids[4] = liquid; + m_InkNames[4] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightMagenta: + filteredInputLiquids[5] = liquid; + m_InkNames[5] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightYellow: + filteredInputLiquids[6] = liquid; + m_InkNames[6] = liquid->liquidtype; + break; + } + } + + Input->inputliquids = filteredInputLiquids; + if (expected_liquids <= 0) + throw std::exception("expected_liquids is zero"); + else + Input->n_inputliquids = expected_liquids; + + //Filter and arrange colors + + size_t n_elements = 0; + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + + + if (m_colortable == NULL) + m_colortable = new ColorTable(); + readColorTransformations(Input); + if (Input->n_processranges <= 0) + throw std::exception("number of process ranges is zero"); + else + m_nProcessRanges = Input->n_processranges; + + double *tmpVal; + /* if (m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetNormGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = tmpVal[i]; */ + + if (m_GamutRegionMaxLim == NULL) + m_GamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_GamutRegionMaxLim[i] = tmpVal[i]; + + if (m_GamutRegionMinLim == NULL) + m_GamutRegionMinLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetGamutRegionMinLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_GamutRegionMinLim[i] = tmpVal[i]; + + //read calibration tables and store them in m_CalibCurves + InputLiquid **inputliquids = Input->inputliquids; + // int n_inputliquids = conversionInput->inputcoordinates->n_inputliquids; + int n_inputliquids = numofInks - numLightInks; + readCalibrationTables(inputliquids, n_inputliquids); + + if (m_colortable->GetTableSubVersion() > 0) + { + C_RGB_XYZ_Lab whitepoint_CT = m_colortable->GetWhitePoint_CT(); + m_forwardmodel = m_colortable->GetForwardModel(); + ColorConvert CConvertD65(D65, D65); + C_RGB_XYZ_Lab relWP_CT; + CConvertD65.ChangeWP(whitepoint_CT, relWP_CT, m_WP, m_whitepointXYZ_Strip); + m_forwardmodel->SetFreeTerm(relWP_CT); + m_ObjFunction = new ObjectiveFunction(m_forwardmodel); + PrepareObjectiveFunctionPars(); + m_Minimize = new LevMar(m_ObjFunction); + m_Minimize->Init(); + m_Minimize->SetMaxIterations(50); + m_Minimize->SetTolerance(0.01); + } + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if (m_Conv02 == NULL) + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + + if (n_inputliquids != m_nInks) + throw std::exception("Number of available inks does not match ink tables\0"); + + //Set Process Ranges + for (int i = 0; i < m_nProcessRanges; ++i) + { + if (Input->processranges[i]->maxinkuptake <= 0) + throw std::exception("Process Range is zero\0"); + } + double diff = 0; + for (int i = 1; i < m_nProcessRanges; ++i) + { + diff = Input->processranges[i]->maxinkuptake - Input->processranges[i - 1]->maxinkuptake; + if (diff < 0) + throw std::exception("Process Ranges are not monotonic\0"); + } + if (m_ProcessRangesMaxP == NULL) + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMaxP[i] = Input->processranges[i]->maxinkuptake; + } + if (m_ProcessRangesMinP == NULL) + m_ProcessRangesMinP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMinP[i] = Input->processranges[i]->mininkuptake; + } + + //SetLowVolThr_nlcm(); + + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + VectorXd Volume_nlcm(m_nInks); + VectorXd VolumeLi(m_TotalNumberofInks); + VectorXd VolumeOut(m_nInks); + //set maxNlPerCM + VectorXd NlperCM(m_nInks); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nInks; ++i) + SetMaxNLperCM(Input->inputliquids[i]->maxnanoliterpercentimeter, i); + + m_CTmaxNlPerCM = NlperCM; + double *tmpLF = new double[m_nInks]; + tmpLF = m_colortable->GetCTLiquidFactors(); + for (int i = 0; i < m_nInks; ++i) + m_CTmaxNlPerCM(i) = tmpLF[i]; + if (tmpLF != NULL) + { + delete[] tmpLF; + tmpLF = NULL; + } + + // Set Calibration mode 0 up tp 100%, 1 with High Volume Calib + SetCalibMode(); + //Calculate normalization per ink + SetCalibFactorization(); + + m_nVolumes = m_nInks; + + int nstops = Input->n_stops; + int *GamutRegion = new int[nstops]; + InputCoordinates **inputcoordinates = new InputCoordinates*[nstops]; + for (int i = 0; i < nstops; ++i) + { + inputcoordinates[i] = (InputCoordinates*)malloc(sizeof(InputCoordinates)); + input_coordinates__init(inputcoordinates[i]); + } + + RecommendedProcessTableInput2InputCoordinates(Input, inputcoordinates); + + //Convert input data to linear inks + ColorSpace colorspace; + + int32_t processparameterstableindex = 0; + if (m_CurrentProcessRangesMax == NULL) + m_CurrentProcessRangesMax = new double[m_nProcessRanges]; + if (m_CurrentProcessRangesMin == NULL) + m_CurrentProcessRangesMin = new double[m_nProcessRanges]; + + for (int istops = 0; istops < nstops; ++istops) + { + colorspace = Input->stops[istops]->colorspace; + if (Input->stops[istops]->colorspace == COLOR_SPACE__Volume) + { + //Assumption: Input is given without light inks + //The volumes are given in Thread units in % + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int iP = 0; iP < m_nProcessRanges; ++iP) + { + m_CurrentProcessRangesMax[iP] = m_ProcessRangesMaxP[iP]; + m_CurrentProcessRangesMin[iP] = m_ProcessRangesMinP[iP]; + } + for (int jV = 0; jV < m_nInks; ++jV) + { + Volume(jV) = inputcoordinates[istops]->inputliquids[jV]->volume; //volumes are in [%] + Volume_nlcm(jV) = m_maxNlPerCM(jV)*Volume(jV) / 100.0; //Volume_nlcm is in [nl/cm] + } + if (Input->uselightinks) + { //Convert to light inks + GamutRegion[istops] = GetGamutRegion(Volume_nlcm, m_CurrentProcessRangesMax);//Volume is in [nl/cm] + SplitVolume(Volume, VolumeLi, GamutRegion[istops]); //VolumeLi is in [%] + } + else + { + GamutRegion[istops] = GetGamutRegion(Volume_nlcm, m_CurrentProcessRangesMax);//Volume is in [nl/cm] + } + } + else if (Input->stops[istops]->colorspace == COLOR_SPACE__Catalog) + { + //The volumes are given in %, in Color Table Units, use Color Tables parameters to calculate gamut region + InputCoordinates *IC = inputcoordinates[istops]; + IC->n_inputliquids = m_nInks; + IC->inputliquids = (InputLiquid**)malloc(sizeof(InputLiquid*) *m_nInks); + for (int j = 0; j < m_nInks; j++) + { + IC->inputliquids[j] = (InputLiquid*)malloc(sizeof(InputLiquid)); + input_liquid__init(IC->inputliquids[j]); + } + IC->inputliquids[0]->volume = IC->cyan; + IC->inputliquids[0]->liquidtype = LIQUID_TYPE__Cyan; + IC->inputliquids[0]->has_volume =IC-> has_cyan; + IC->inputliquids[1]->volume = IC->magenta; + IC->inputliquids[1]->liquidtype =LIQUID_TYPE__Magenta; + IC->inputliquids[1]->has_volume =IC->has_magenta; + IC->inputliquids[2]->volume = IC->yellow; + IC->inputliquids[2]->liquidtype = LIQUID_TYPE__Yellow; + IC->inputliquids[2]->has_volume = IC->has_yellow; + IC->inputliquids[3]->volume = IC->key; + IC->inputliquids[3]->liquidtype = LIQUID_TYPE__Black; + IC->inputliquids[3]->has_volume = IC->has_key; + + for (int jV = 0; jV < m_nInks; ++jV) + { + Volume(jV) =IC->inputliquids[jV]->volume; + Volume_nlcm(jV) = m_maxNlPerCM(jV)*Volume(jV) / 100.0; //Volume_nlcm is in [nl/cm] + } + + m_currentMaxNLPerCM = m_CTmaxNlPerCM; + for (int iP = 0; iP < m_nProcessRanges; ++iP) + { + m_CurrentProcessRangesMax[iP] =m_GamutRegionMaxLim[iP]; + m_CurrentProcessRangesMin[iP] = m_GamutRegionMinLim[iP]; + } + if (Input->uselightinks) + { //Convert to light inks + GamutRegion[istops] = GetGamutRegion(Volume_nlcm, m_CurrentProcessRangesMax);//Volume_nlcm is in [nl/cm] + SplitVolume(Volume, VolumeLi, GamutRegion[istops]); //VolumeLi is in [%] + } + else + { + GamutRegion[istops] = GetGamutRegion(Volume_nlcm, m_GamutRegionMaxLim); //Volume_nlcm is in [nl/cm] + } + } + else + { //RGB or Lab + colorspace = Input->stops[istops]->colorspace; + + if (m_colortable->GetTableSubVersion() > 0) + { + DirectInversion(inputcoordinates[istops], colorspace, InkOut, RGBOut, Volume, LabOut, + GamutRegion[istops], InGamut, sur, CS); + PercentagetoNLcm(Volume, Volume); //Volume is in Color Table Units + int CTUnits = 1; + GetClosestInk(Volume, GamutRegion[istops], Volume, CTUnits, InGamut); //Input Volume is in [nl/cm] Output Volume is in [%] + ConfineVolumes(Volume); + } + else + { + ConvertColorToLinearInks(inputcoordinates[istops], colorspace, InkOut, RGBOut, + LabOut, GamutRegion[istops], InGamut); //full range Color Table Units + //Inks are in their initial state in % + //Inks are in Linear Space , convert to nonlinear by using Calibration Tables, + //convert data to the thread range in % + ColorTable2Threadunits(InkOut, InkOut); // InkOut is in thread units + int CTUnits = 0; + m_currentMaxNLPerCM = m_maxNlPerCM; + for (int iP = 0; iP < m_nProcessRanges; ++iP) + { + m_CurrentProcessRangesMax[iP] = m_ProcessRangesMaxP[iP]; + m_CurrentProcessRangesMin[iP] = m_ProcessRangesMinP[iP]; + } + if (m_CalibMode == 1) + { + ConvertToNLInks(InkOut, NLInkOut); + LimitNLInks2Volume(NLInkOut, GamutRegion[istops], Volume, CTUnits, InGamut); //Volume is in [%] + } + else + LimitNLInks2Volume(InkOut, GamutRegion[istops], Volume, CTUnits, InGamut); //Volume is in [%] + } + if (Input->uselightinks) + { //Convert to light inks + SplitVolume(Volume, VolumeLi, GamutRegion[istops]); + } + } + if (istops == 0 || processparameterstableindex < GamutRegion[istops]) + { + processparameterstableindex = GamutRegion[istops]; + } + } + delete[] GamutRegion; + GamutRegion = NULL; + // all gamut regions were evaluated, pack data + + //Initialize Output... + RecommendedProcessTableOutput *Output = (RecommendedProcessTableOutput*)malloc(sizeof(RecommendedProcessTableOutput)); + recommended_process_table_output__init(Output); + Output->has_processparameterstableindex = true; + Output->processparameterstableindex = processparameterstableindex; + output_buffer = (uint8_t*)malloc(recommended_process_table_output__get_packed_size(Output)); + int size = recommended_process_table_output__pack(Output, output_buffer); + +#pragma region Free Conversion Input & Output + Input->inputliquids = original_input_liquids;; + Input->n_inputliquids = original_input_liquids_count; + for (int i=0; ihas_haserror = true; + output->haserror = true; + + const char* what = e.what(); + int nWhat = strlen(what); + output->errormessage = (char*)malloc(nWhat); + for (int i = 0; i < nWhat; ++i) + output->errormessage[i] = what[i]; + + output_buffer = (uint8_t*)malloc(recommended_process_table_output__get_packed_size(output)); + int size = recommended_process_table_output__pack(output, output_buffer); + +#pragma region Free Conversion Input & Output + + recommended_process_table_input__free_unpacked(Input, NULL); + recommended_process_table_output__free_unpacked(output, NULL); + +#pragma endregion + + return (size); + } +} + +size_t Tango::ColorLib::ColorConverter::CheckOutOfGamut(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +{ + //Get Input + OutOfGamutInput* Input = out_of_gamut_input__unpack(NULL, input_buffer_size, input_buffer); + + try + { + 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 = 0; + int numLightInks = 0; + CountNumberofInks(Input, numofInks, numLightInks); + if (numofInks < 0) + throw std::exception("Duplicate inks"); + + int expected_liquids = numofInks; + m_TotalNumberofInks = numofInks; + original_input_liquids_count = Input->inputcoordinates->n_inputliquids; + original_input_liquids = Input->inputcoordinates->inputliquids; + if(m_InkNames == NULL) + m_InkNames = new LiquidType[m_TotalNumberofInks]; + InputLiquid** filteredInputLiquids = new InputLiquid*[m_TotalNumberofInks]; + + for (int i = 0; i < original_input_liquids_count; i++) + { + InputLiquid* liquid = Input->inputcoordinates->inputliquids[i]; + + switch (liquid->liquidtype) + { + case LIQUID_TYPE__Cyan: + filteredInputLiquids[0] = liquid; + m_InkNames[0] = liquid->liquidtype; + break; + case LIQUID_TYPE__Magenta: + filteredInputLiquids[1] = liquid; + m_InkNames[1] = liquid->liquidtype; + break; + case LIQUID_TYPE__Yellow: + filteredInputLiquids[2] = liquid; + m_InkNames[2] = liquid->liquidtype; + break; + case LIQUID_TYPE__Black: + filteredInputLiquids[3] = liquid; + m_InkNames[3] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightCyan: + filteredInputLiquids[4] = liquid; + m_InkNames[4] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightMagenta: + filteredInputLiquids[5] = liquid; + m_InkNames[5] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightYellow: + filteredInputLiquids[6] = liquid; + m_InkNames[6] = liquid->liquidtype; + break; + } + } + + Input->inputcoordinates->inputliquids = filteredInputLiquids; + if (expected_liquids <= 0) + throw std::exception("expected_liquids is zero"); + else + Input->inputcoordinates->n_inputliquids = expected_liquids; + + //Filter and arrange colors + size_t n_elements = 0; + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + + + if (m_colortable == NULL) + m_colortable = new ColorTable(); + readColorTransformations(Input); + if (Input->n_processranges <= 0) + throw std::exception("number of process ranges is zero"); + else + m_nProcessRanges = Input->n_processranges; + + double *tmpVal; + /*if (m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nProcessRanges]; + tmpVal = m_colortable->GetNormGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = tmpVal[i]; */ + + if (m_GamutRegionMaxLim == NULL) + m_GamutRegionMaxLim = new double[m_nProcessRanges]; + if (m_GamutRegionMinLim == NULL) + m_GamutRegionMinLim = new double[m_nProcessRanges]; + m_GamutRegionMinLim[0] = GamutMinReg0; + m_GamutRegionMinLim[1] = GamutMinReg1; + tmpVal = m_colortable->GetGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_GamutRegionMaxLim[i] = tmpVal[i]; + + //read calibration tables and store them in m_CalibCurves + InputLiquid **inputliquids = Input->inputcoordinates->inputliquids; + // int n_inputliquids = conversionInput->inputcoordinates->n_inputliquids; + int n_inputliquids = numofInks - numLightInks; + readCalibrationTables(inputliquids, n_inputliquids); + // Set Calibration mode 0 up tp 100%, 1 with High Volume Calib + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if (m_Conv02 == NULL) + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + + if (n_inputliquids != m_nInks) + throw std::exception("Number of available inks does not match ink tables\0"); + + //Tables have been filled + VectorXd RGBOut(3); + VectorXd LabOut(3); + ColorConvert CConvertD65(D65, D65); //Destination, source + //Convert input data to linear inks + if (Input->colorspace == COLOR_SPACE__Volume || Input->colorspace == COLOR_SPACE__Catalog) + { + InGamut = true; + } + else + { + double LabIn[3]; + switch (Input->colorspace) + { + case (COLOR_SPACE__RGB): + { + RGBOut(0) = Input->inputcoordinates->red; + RGBOut(1) = Input->inputcoordinates->green; + RGBOut(2) = Input->inputcoordinates->blue; + //convert to Lab + double RGBOutP[3]; + VectorToDouble(RGBOut, RGBOutP); + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 + LimitLab(LabIn); + //Is In Gamut? + double LabOnGamut[3]; + InGamut = IsInGamut(LabIn, sur, CS, LabOnGamut); + break; + } + case (COLOR_SPACE__LAB): + { + LabIn[0] = Input->inputcoordinates->l; //Absolute Colorimetric + LabIn[1] = Input->inputcoordinates->a; + LabIn[2] = Input->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 LabInFinal2[3]; + double LabOnGamut[3]; + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //LabInFinal2 is in Relative Colorimetric Space + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + break; + } + default: + { + throw std::exception(" Unsupported Color Space"); + break; + } + } + } + + //Initialize Output... + OutOfGamutOutput *Output = (OutOfGamutOutput*)malloc(sizeof(OutOfGamutOutput)); + out_of_gamut_output__init(Output); + Output->has_outofgamut = true; + Output->outofgamut = !(InGamut); + + output_buffer = (uint8_t*)malloc(out_of_gamut_output__get_packed_size(Output)); + int size = out_of_gamut_output__pack(Output, output_buffer); + +#pragma region Free Conversion Input & Output + + Input->inputcoordinates->inputliquids = original_input_liquids; + Input->inputcoordinates->n_inputliquids = original_input_liquids_count; + delete[] filteredInputLiquids; + filteredInputLiquids = NULL; + + out_of_gamut_input__free_unpacked(Input, NULL); + + out_of_gamut_output__free_unpacked(Output, NULL); + +#pragma endregion + + return (size); + } + catch (const std::exception& e) + { + //Notify Error... + OutOfGamutOutput *Output = (OutOfGamutOutput*)malloc(sizeof(OutOfGamutOutput)); + out_of_gamut_output__init(Output); + + Output->has_haserror = true; + Output->haserror = true; + + const char* what = e.what(); + int nWhat = strlen(what); + Output->errormessage = (char*)malloc(nWhat); + //conversionOutput->errormessage = new char[nWhat]; + for (int i = 0; i < nWhat; ++i) + Output->errormessage[i] = what[i]; + + output_buffer = (uint8_t*)malloc(out_of_gamut_output__get_packed_size(Output)); + int size = out_of_gamut_output__pack(Output, output_buffer); + +#pragma region Free Conversion Input & Output + + out_of_gamut_input__free_unpacked(Input, NULL); + out_of_gamut_output__free_unpacked(Output, NULL); + +#pragma endregion + + return (size); + } +} + +void Tango::ColorLib::ColorConverter::DirectInversion(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &InkOut, VectorXd &RGBOut, VectorXd &VolOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + //Split the calculation into RGB and Lab Color Space + int i = 0; + int k = 0; + double *LabIn = new double[3]; + double *RGBIn = new double[3]; + ColorConvert ColConv(D65, D65); + + if (colorspace == COLOR_SPACE__RGB) + { + RGBIn[0] = inputcoordinates->red; + RGBIn[1] = inputcoordinates->green; + RGBIn[2] = inputcoordinates->blue; + ColConv.RGBtoLab(RGBIn, LabIn); + } + else if (colorspace == COLOR_SPACE__LAB) + { + LabIn[0] = inputcoordinates->l; //Absolute Colorimetric + LabIn[1] = inputcoordinates->a; + LabIn[2] = inputcoordinates->b; + } + else + { + throw std::exception(" Unsupported Color Space"); + } + + DirectInversionCalc(LabIn, InkOut, RGBOut, VolOut, + LabOut, GamutRegion, InGamut, sur, CS); + + + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (RGBIn != NULL) + { + delete[] RGBIn; + RGBIn = NULL; + } + +} + +void Tango::ColorLib::ColorConverter::DirectInversionCalc(double *LabIn, VectorXd &InkOut, VectorXd &RGBOut, VectorXd &VolOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + //Declarations + ColorConvert ColConv(D65, D65); + int i, k; + int nfree = m_ObjFunction->GetNumFreeParams(); + double *InitCMY = new double[nfree]; + int nfixed = m_ObjFunction->GetNumFixedParams(); + int npars = nfree + nfixed; + if (npars != m_nInks) + throw std::exception("Number of parameters does not match number of inks"); + double *ValK = new double[nfixed]; + int nk = 100 + 1; + double dK = 1.0 / (double)(nk - 1); + for (i = 0; i < nfixed; ++i) + ValK[i] = 0; + double **SolVector = new double*[nk]; + double **finalLab = new double *[nk]; + double **Vol = new double*[nk]; + int *FeasibleSolutionsInd = new int[nk]; + int *VecGamutRegion = new int[nk]; + + VectorXd VolumeTmp(npars); + C_RGB_XYZ_Lab LabTmp; + double *dECMC = new double[nk]; + C_RGB_XYZ_Lab LabInVec; + VectorXd LabOutTmp(3); + LabInVec.Set(LabIn[0], LabIn[1], LabIn[2]); + C_RGB_XYZ_Lab LabOutVec; + m_currentMaxNLPerCM = m_maxNlPerCM; + for (i = 0; i < m_nProcessRanges; ++i) + { + m_CurrentProcessRangesMax[i] = m_ProcessRangesMaxP[i]; + m_CurrentProcessRangesMin[i] = m_ProcessRangesMinP[i]; + } + for (i = 0; i < nk; ++i) + { + SolVector[i] = new double[npars]; + finalLab[i] = new double[3]; + Vol[i] = new double[npars]; + } + double *LabInFinal2 = new double[3]; + double *LabOnGamut = new double[3]; + + ColConv.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //LabInFinal2 is in Relative Colorimetric Space + LimitLab(LabInFinal2); + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + + LabTmp.Set(LabOnGamut[0], LabOnGamut[1], LabOnGamut[2]); + m_ObjFunction->SetLabGoal(LabOnGamut); + + //convert to Inks + unsigned int nIterations; + + for (i = 0; i < nfree; ++i) + InitCMY[i] = 0.0; + for (i = 0; i < nfixed; ++i) + ValK[i] = 0.0; + m_Minimize->SetLabIn(LabOnGamut); + for (k = 0; k < nk; ++k) + { + ValK[0] = (double)k * dK; + m_Minimize->MinimizationAlgorithm(InitCMY, ValK, nIterations); //result is returned in InitCMY + LabOutTmp = DoubleToVector(LabOnGamut, 3); + LabOutTmp += DoubleToVector(m_Minimize->GetLabOut(), 3); + for (int i = 0; i < nfree; ++i) + SolVector[k][i] = std::min(std::max(100 * InitCMY[i], 0.0), 100.0); + SolVector[k][nfree] = std::min(std::max(100 * ValK[0], 0.0), 100.0); //Solution Vector is in linear units in the interval [0,100] + + for (int i = 0; i < 3; ++i) + finalLab[k][i] = LabOutTmp[i]; + LabOutVec.Set(LabOutTmp[0], LabOutTmp[1], LabOutTmp[2]); + + ColConv.dEcmc(LabTmp, LabOutVec, dECMC[k]); + //Result is in Linear Inks + //apply Nonlinear curves of Loaded thread + // in order to calculate volume + // Volume is used to calculate the feasible solutions + + InkOut = DoubleToVector(SolVector[k], m_nInks); + double *tmpval = m_colortable->GetNormFactor(); + for (int i = 0; i < m_nInks; ++i) + InkOut(i) *= tmpval[i]; + ColorTable2Threadunits(InkOut, InkOut); //in % + + if (m_CalibMode == 1) + { + ConvertToNLInks(InkOut, InkOut); // in % + LimitNLInks2VolumeNoFix(InkOut, GamutRegion, VolumeTmp); //VolumeTmp is in % + // NLInkPToVolume(InkOut, VolumeTmp); // in % + //LimitNLInks2Volume(InkOut, GamutRegion, VolumeTmp); + } + else + { + LimitNLInks2VolumeNoFix(InkOut, GamutRegion, VolumeTmp); + } + VecGamutRegion[k] = GamutRegion; + // NLInkPToVolume(InkOut, VolumeTmp); // in % + for (i = 0; i < npars; ++i) + Vol[k][i] = VolumeTmp(i); + VectorToDouble(InkOut, SolVector[k]); + } + + //find feasible solutions + int nfeas = -1; + + for (k = 0; k < nk; ++k) + { + bool FSInd = true; + for (i = 0; i < npars - 1; ++i) + FSInd = FSInd & ((Vol[k][i] < 0.01) | (Vol[k][i] > m_LowVolumeThreshold)); + FSInd = FSInd & ((Vol[k][npars - 1] < 0.01) | (Vol[k][npars - 1] > m_LightInksThr)); + FSInd = FSInd & (dECMC[k] < 0.5); + if (FSInd) + { + nfeas++; + FeasibleSolutionsInd[nfeas] = k; + } + } + double minVal = 1e+05; + int minInd = -1; + if (nfeas >= 0) + { + for (i = 0; i < nfeas + 1; ++i) + { + if (dECMC[FeasibleSolutionsInd[i]] < minVal) + { + minVal = dECMC[FeasibleSolutionsInd[i]]; + minInd = FeasibleSolutionsInd[i]; + } + } + } + else + { + for (i = 0; i < nk; ++i) + { + if (dECMC[i] < minVal) + { + minVal = dECMC[i]; + minInd = i; + } + } + } + + for (i = 0; i < npars; ++i) + { + InkOut(i) = SolVector[minInd][i]; + VolOut(i) = Vol[minInd][i]; + } + GamutRegion = VecGamutRegion[minInd]; + + double *LabOutFinal = new double[3]; + for (int i = 0; i < 3; ++i) + LabOutFinal[i] = finalLab[minInd][i]; + //LabOutFinal is in Relative Colorimetric + //Reverse the conversion process to bring back Lab to STRIP white point + ColConv.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_WP); + + ColConv.ChangeWP(LabOnGamut, LabOnGamut, m_whitepointXYZ_Strip, m_WP); + LabOut = DoubleToVector(LabOnGamut, 3); + + ColConv.SetReferenceWhite(D65); + //Convert to RGB + double *RGBOutP = new double[3]; + + //Use Relative colorimetric to get RGB + ColConv.LabtoRGB(finalLab[minInd], RGBOutP); + RGBOut = DoubleToVector(RGBOutP, 3); + + //Cleanup + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + + if (ValK != NULL) + { + delete[] ValK; + ValK = NULL; + } + + if (VecGamutRegion != NULL) + { + delete[] VecGamutRegion; + VecGamutRegion = NULL; + } + + if (SolVector != NULL) + { + for (i = 0; i < npars; ++i) + delete[] SolVector[i]; + delete[] SolVector; + SolVector = NULL; + } + + if (finalLab != NULL) + { + for (i = 0; i < 3; ++i) + delete[] finalLab[i]; + delete[] finalLab; + finalLab = NULL; + } + + if (Vol != NULL) + { + for (i = 0; i < npars; ++i) + delete[] Vol[i]; + delete[] Vol; + Vol = NULL; + } + + if (LabInFinal2 != NULL) + { + delete[] LabInFinal2; + LabInFinal2 = NULL; + } + + if (LabOnGamut != NULL) + { + delete[] LabOnGamut; + LabOnGamut = NULL; + } + + + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } + + if (FeasibleSolutionsInd != NULL) + { + delete[] FeasibleSolutionsInd; + FeasibleSolutionsInd = NULL; + } +} + + +void Tango::ColorLib::ColorConverter::PrepareObjectiveFunctionPars() +{ + int nFreeParams = 3; + int nFixedParams = 1; + unsigned int *FreeParamIndex = new unsigned int[nFreeParams]; + unsigned int *FixedParamIndex = new unsigned int [nFixedParams]; + FreeParamIndex[0] = 0; + FreeParamIndex[1] =1; + FreeParamIndex[2] = 2; + FixedParamIndex[0] = 3; + double *UpperBound = new double[nFreeParams]; + double *LowerBound = new double[nFreeParams]; + for (int i = 0; i < nFreeParams; ++i) + { + UpperBound[i] = 1.0; + LowerBound[i] = 0.0; + } + m_ObjFunction->SetParameters(nFreeParams, nFixedParams, FreeParamIndex, FixedParamIndex, UpperBound, LowerBound); +} + +size_t Tango::ColorLib::ColorConverter::InitConvertLiquids(ConversionInput *conversionInput, InputLiquid** original_input_liquids, + int &numofInks, int &numLightInks) +{ + //Filter and arrange colors (Should change from 3 to 4 if black ink is included) + + int original_input_liquids_count = 0; + CountNumberofInks(conversionInput, numofInks, numLightInks); + if (numofInks < 0) + throw std::exception("Duplicate inks"); + + m_UseLightInks = conversionInput->uselightinks; + if ((numLightInks <= 0) & (m_UseLightInks == true)) + throw std::exception("Light Inks not defined"); + + int expected_liquids = numofInks; + m_TotalNumberofInks = numofInks; + original_input_liquids_count = conversionInput->inputcoordinates->n_inputliquids; + original_input_liquids = conversionInput->inputcoordinates->inputliquids; + if (m_InkNames == NULL) + m_InkNames = new LiquidType[m_TotalNumberofInks]; + InputLiquid** filteredInputLiquids = (InputLiquid**)malloc(sizeof(InputLiquid*) * m_TotalNumberofInks); + + 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; + m_InkNames[0] = liquid->liquidtype; + break; + case LIQUID_TYPE__Magenta: + filteredInputLiquids[1] = liquid; + m_InkNames[1] = liquid->liquidtype; + break; + case LIQUID_TYPE__Yellow: + filteredInputLiquids[2] = liquid; + m_InkNames[2] = liquid->liquidtype; + break; + case LIQUID_TYPE__Black: + filteredInputLiquids[3] = liquid; + m_InkNames[3] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightCyan: + filteredInputLiquids[4] = liquid; + m_InkNames[4] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightMagenta: + filteredInputLiquids[5] = liquid; + m_InkNames[5] = liquid->liquidtype; + break; + case LIQUID_TYPE__LightYellow: + filteredInputLiquids[6] = liquid; + m_InkNames[6] = liquid->liquidtype; + break; + } + } + conversionInput->inputcoordinates->inputliquids = filteredInputLiquids; + if (expected_liquids <= 0) + throw std::exception("expected_liquids is zero"); + else + conversionInput->inputcoordinates->n_inputliquids = expected_liquids; + return((size_t)expected_liquids); +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.h new file mode 100644 index 000000000..01e05f545 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverter.h @@ -0,0 +1,228 @@ +#include +#include +#include "Dense" +#include "Core" +#include "C_RGB_XYZ_Lab.h" +#include "protobuf-c\protobuf-c.h" +#include "CalibData.h" +#include "ColorTransf.h" +#include "ColorConvert.h" +#include "ForwardModel.h" +#include "GBD.h" +#include "CT_Header.h" +#include "ConversionOutput.pb-c.h" +#include "CalibrationData.pb-c.h" +#include "ConversionInput.pb-c.h" +#include "GradientInputStop.pb-c.h" +#include "GradientOutputStop.pb-c.h" +#include "GradientConversionInput.pb-c.h" +#include "GradientConversionOutput.pb-c.h" +#include "OutOfGamutInput.pb-c.h" +#include "OutOfGamutOutput.pb-c.h" +#include "RecommendedProcessTableInput.pb-c.h" +#include "RecommendedProcessTableOutput.pb-c.h" +#include "ObjectiveFunction.h" +#include "LevMar.h" +#include "Interp.h" +#include "Curves.h" +#include "Gradient.h" +#include "ColorTable.h" +#include + +#pragma once +namespace Tango +{ +/* typedef struct + { + 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 struct + { + C_RGB_XYZ_Lab Lab; + C_RGB_XYZ_Lab RGB; + double *Volume; + bool InGamut; + int GamutRegion; + double offset; + ColorSpace colorspace; + }GradStruct;*/ + + /*typedef enum { + XYZ, + Lab, + CMY, + CMYK + }ColorSpaceH;*/ + + typedef enum { + EqSpaced, + dESpaced + }GradOffset; + + + + namespace ColorLib + { + class ColorConverter + { + public: + ColorConverter(); + ~ColorConverter(); + // size_t Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + void ConvertColorToLinearInks( InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &InkOut, VectorXd &RGBOut, VectorXd &LabOut, + int &GamutRegion, bool &InGamut); + void ConvertGradStoptoVolume(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &InkOut, int &GamutRegion, bool same_regions); + void ConvertVolumeToRGBDisplay(InputCoordinates *IC, int n_processRanges,int colorspace, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut); + void ConvertVolumeToLabRel(VectorXd &Volume, VectorXd &LabOut, int GamutRegion, int CTUnits); + + size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + size_t Tango::ColorLib::ColorConverter::GenerateGradient(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + size_t Tango::ColorLib::ColorConverter::GetRecommendedProcessParameters(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + size_t Tango::ColorLib::ColorConverter::CheckOutOfGamut(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + void Tango::ColorLib::ColorConverter::DirectInversion(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &InkOut, VectorXd &RGBOut, VectorXd &VolOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS); + void Tango::ColorLib::ColorConverter::DirectInversionCalc(double *LabIn, VectorXd &InkOut, VectorXd &RGBOut, VectorXd &VolOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS); + void ConvertToNLInks(VectorXd InkIn, VectorXd &InkOut); + void ConvertToLinearInks(VectorXd InkIn, VectorXd &InkOut); + void VolumeToNLInkP(VectorXd Volume, VectorXd &NLInkP); + void NLInkPToVolume(VectorXd NLInkP, VectorXd &Volume); + void SetMaxNLperCM(double maxNlPerCM, int i); + size_t P_IsInGamut(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + private: + ColorTable *m_colortable; + ColorConvert *m_Conv02; + LiquidType *m_InkNames; +// Interp *m_LinInterp; +// Interp *m_InvLinInterp; + C_RGB_XYZ_Lab m_whitepointLab; + C_RGB_XYZ_Lab m_whitepointXYZ_Strip; + double *m_NormGamutRegionMaxLim; + double *m_GamutRegionMaxLim; + double *m_GamutRegionMinLim; + double *m_ProcessRangesMaxP; + double *m_CurrentProcessRangesMax; + double *m_CurrentProcessRangesMin; + double *m_ProcessRangesMinP; + int m_nProcessRanges; + bool m_UseLightInks; + double m_LightInksThr; + double m_LowVolumeThreshold; + double m_LowVolHalf; + double m_NormFactor; + double m_InvnormFactor; + int m_TotalNumberofInks; + double *m_CalibGain; + double *m_CalibOffset; + double *m_maxCalX; + void LimitLab(double* LabIn); + int m_nGradStops; + Gradient *m_GradStops; + bool same_regions; + int m_CalibMode; +// bool m_AdaptWP; + CalibData *m_CalibCurves; + ForwardModel *m_forwardmodel; + int m_nInks; + int m_nVolumes; + //double *m_ProcessRangesMaxInkUptake; + //double *m_ProcessRangesMinInkUptake; + C_RGB_XYZ_Lab m_WP; + VectorXd m_maxNlPerCM; + VectorXd m_CTmaxNlPerCM; + VectorXd m_currentMaxNLPerCM; + ObjectiveFunction *m_ObjFunction; + LevMar *m_Minimize; + //double *m_LowVolThr_nlcm; + //double *m_LowVolThrHalf_nlcm; + size_t InitConvertLiquids(ConversionInput *conversionInput, InputLiquid** original_input_liquids, int &numofInks, int &numLightInks); + void readColorTransformations(ConversionInput* conversionInput); + void readColorTransformations(OutOfGamutInput* Input); + void readColorTransformations(RecommendedProcessTableInput *Input); +// void readColorTables(bool has_rddata, uint8_t *data, int nprocessranges); + void readCalibrationTables(InputLiquid **inputliquids, int n_inputliquids); + void SetCalibData(CalibrationData* calibrationData, int i, CalibData *tmpCurve); + void SetNumberofInks(int nInks) { m_nInks = nInks; }; + void SetNumberOfVolumes(int nVol) { m_nVolumes = nVol; }; + // 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 fillStop(GradientOutputStop *&stop, VectorXd Volume, int GamutRegion, double Position); + void fillGradientStops(GradientConversionInput *conversionInput); + 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); + void CountNumberofInks(ConversionInput* conversionInput, int &numInks, int &numLightInks); + void CountNumberofInks(GradientConversionInput* conversionInput, int &numInks, int &numLightInks); + void CountNumberofInks(OutOfGamutInput* conversionInput, int &numInks, int &numLightInks); + void CountNumberofInks(RecommendedProcessTableInput* conversionInput, int &numInks, int &numLightInks); + void SetStripWhitepoint(double threadl, double threada, double threadb); + void VectorToDouble(VectorXd Vec, double *doub); +// void VectorToDouble(VectorXd VecIn, std::vector &doubOut); + VectorXd DoubleToVector(double *doub, int nSize); + void CompareWhitePoints(); + bool IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord); +// CT_Header *read_header(uint8_t* data, int &bytesread); + void read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput); + void findStops(Gradient& m_GradStops1, Gradient& m_GradStops2, double dEThr, int ninterstops, int &nOut, + double **VecRGBOut, double **VecLabOut, double *posOut); + void RecommendedProcessTableInput2InputCoordinates(RecommendedProcessTableInput *Input, InputCoordinates **inputcoordinates); + void GradInput2InputCoords(GradientConversionInput *conversionInput, InputCoordinates **inputcoordinates); + void ProcessGradientStops(InputCoordinates **inputcoordinates); + void PrepareGradient(GradientConversionInput* conversionInput, GradientConversionOutput *conversionOutput); + void LimitInks(VectorXd inInks, double *BoundedInks); + void NLcmtoPercentage(VectorXd InVolume, VectorXd &OutVolume); + void PercentagetoNLcm(VectorXd InVolume, VectorXd &OutVolume); + int GetGamutRegion(VectorXd Volume, double *GamutLimits); + bool CheckLabInRGBGamut( VectorXd Lab); + bool CheckLabInRGBGamut( C_RGB_XYZ_Lab Lab); + void SmoothCurveData(VectorXd VIn, VectorXd &VOut, int FilterWidth); + void ConvertRGBColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS); + void ConvertLabColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS); + /*void ConvertCMYKColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS);*/ + void LimitLowVolume(VectorXd InVolume, int &GamutRegion, VectorXd &OutVolume); + void LimitLowVolumeP(VectorXd InVolume, int &GamutRegion, VectorXd &OutVolume); + void LimitNLInks2Volume(VectorXd NLInks, int &GamutRegion, VectorXd &OutVolume, int CTUnits, bool &InGamut); + void LimitNLInks2VolumeNoFix(VectorXd NLInks, int &GamutRegion, VectorXd &Volume); + void LimitNLInks2VolumeThr(VectorXd NLInks, int &GamutRegion, VectorXd &Volume); + void GetClosestInk(VectorXd Volume, int &GamutRegion, VectorXd &BestVolume, int CTUnits, bool &InGamut); + bool CheckMonotonicity(CalibrationData *calibdata); + void ConfineVolumes(VectorXd &Volume); + void SplitVolume(VectorXd Volume, VectorXd &VolumeLI, int &GamutRegion); + void DefineSplitLimits(double &low, double &high, double InitTotalVolume); + void findGamutRegion(int &GamutRegion, double TotalVolume); + void SetCalibMode(); + void SetCalibFactorization(); + void ApplyCTLinearCurves(double *InkIn, double* InkOut); + void ApplyCTInvLinearCurves(double *InkIn, double* InkOut); + void ColorTable2Threadunits(VectorXd InkIn, VectorXd &InkOut); + void Thread2ColorTableunits(VectorXd InkIn, VectorXd &InkOut); + void PrepareObjectiveFunctionPars(); + }; + } +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverterCLipRGB.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverterCLipRGB.cpp new file mode 100644 index 000000000..789e7f411 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ColorConverterCLipRGB.cpp @@ -0,0 +1,3219 @@ +#include "ColorConverter.h" +#include "ColorConvert.h" +#include "CalibrationPoint.pb-c.h" +#include "CalibrationData.pb-c.h" +#include "ColorSpace.pb-c.h" +#include "ConversionInput.pb-c.h" +#include "ConversionOutput.pb-c.h" +#include "InputCoordinates.pb-c.h" +#include "OutputCoordinates.pb-c.h" +#include "OutputLiquid.pb-c.h" +#include "InputLiquid.pb-c.h" +#include "LiquidType.pb-c.h" +#include +#include +#include "Dense" +#include "C_RGB_XYZ_Lab.h" +#include "ColorConvert.h" +#include "ColorTransf.h" +#include "NumConversions.h" +#include "Interp.h" +#include +#include +#include + +#include "GradientConversionInput.pb-c.h" +#include "GradientConversionOutput.pb-c.h" +#include "GradientInputStop.pb-c.h" +#include "GradientOutputStop.pb-c.h" +#include "LiquidVolume.pb-c.h" + +#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 + +#define dL 2.0 +#define dC 2.0 +#define dH6 EIGEN_PI / 3.0 +#define dH12 EIGEN_PI / 6.0 +#define LUMINANCE_PCS 159.16 +#define L_A LUMINANCE_PCS / 5.0 +#define Y_b 20.0 +#define eps 1e-06 +#define NegValue -1000 +#define WPTol 1.0 +#define dETol 2.0 +# define ROUNDINGDigits 2.0 +#define maxPerRegion 100.0 +#define LowVolumeThreshold 0.0 +#define LowVolHalf LowVolumeThreshold/2 +#define GradientEndThr 0.95 + + +Tango::ColorLib::ColorConverter::ColorConverter() : + m_CalibCurves(NULL), m_Conv02(NULL), +m_maxNlPerCM(NULL), +m_nInks(0), m_nVolumes(0), + m_GradStops(NULL), m_nGradStops(0), m_colortable(NULL), m_ProcessRangesMaxP(NULL), + m_nProcessRanges(0), m_NormGamutRegionMaxLim(NULL) +{ + m_whitepointLab.Set(-1, -1, -1); + m_whitepointXYZ_Strip.Set(-1, -1, -1); + m_WP.Set(-1, -1, -1); +} + +Tango::ColorLib::ColorConverter::~ColorConverter() +{ + if (m_Conv02 != NULL) + { + delete m_Conv02; + m_Conv02 = NULL; + } + if (m_CalibCurves != NULL) + { + delete[] m_CalibCurves; + m_CalibCurves = NULL; + } + if(m_GradStops != NULL) + { + delete [] m_GradStops; + m_GradStops = NULL; + } + if (m_colortable != NULL) + { + delete m_colortable; + m_colortable = NULL; + } + if (m_NormGamutRegionMaxLim != NULL) + { + delete[] m_NormGamutRegionMaxLim; + m_NormGamutRegionMaxLim = 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; + }*/ + //_CrtDumpMemoryLeaks(); +} + +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; + ColorConvert ColConv(D65, D65); + SURROUND sur = m_Conv02->getSurround(); + CAM02CS CS = m_Conv02->getCAM02CS(); + VectorXd LabV(3); + LabV = Lab; + + //LCH coordinates + double hue = 0.0; + 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(Lab(2), Lab(1)); + + double d1 = dC; + double de = 0; + MatrixXd Lab1(nHive, 3); + for (int i = 0; i < 6; ++i) + { + 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; + for (int i = 0; i < 12; ++i) + { + j1 = i + 6; + 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) + { + 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); + } + //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); + 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 = DBG_NEW double[3]; + double * LabInFinal2 = new double[3]; + double * LabOnGamut = new double[3]; + double *InkOutP = new double[m_nInks]; + bool InGamut = true; + for (int i = 0; i < nHive; ++i) + { + //Get Lab's inGamut + for (j = 0; j < 3; ++j) + Lab1P[j] = Lab1(i, j); + //Check if whitepoints match +/* 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 + ColConv.ChangeWP(Lab1P, Lab1P, m_WP, m_whitepointXYZ_Strip); //to Relative + m_colortable->m_B2ATransform->evalLab2InkP(Lab1P, InkOut, GamutRegion[i]); //InkOut is in units of 16 bits + for (int i = 0; i GetNormFactor(); + if (InkOut[i] <= m_NormGamutRegionMaxLim[0]) + { + m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOut[i] * 655.35, InkOut[i]); + InkOut[i] /= 655.35; + } + } + InGamut = IsInGamut(Lab1P, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + VectorXd NLInkOut(m_nInks); + ConvertToNLInks(DoubleToVector(InkOut, m_nInks), NLInkOut); + + //Limit inks based on m_maxNlpercm + //Inks are limited in their nonlinear form + //Output Volume is in % + LimitInks(NLInkOut, InkOutP); + NLInkPToVolume(DoubleToVector(InkOutP, m_nInks), Vol); + GamutRegion[i] = GetGamutRegion(Vol, m_ProcessRangesMaxP); + NLcmtoPercentage(Vol, Vol); + //m_A2BTransform->evalInkP2Lab(InkOut, Lab1P, GamutRegion[i]); + + //Convert to CT WP +// m_Conv02->ChangeWP(LabOnGamut, LabInFinal1, m_whitepointXYZ_CT, m_WP); //convert back to Absolute + m_Conv02->ChangeWP(LabOnGamut, LabInFinal1, m_whitepointXYZ_Strip, m_WP); //convert back to Absolute + LimitLab(LabInFinal1); //Absolute + + //Check if whitepoints match +/* if (m_AdaptWP) + { + //Convert to Strip whitepoint + m_Conv02->ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); + LimitLab(LabInFinal1); + }*/ + m_Conv02->SetReferenceWhite(D65); + 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); + + //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 < 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; + } + + //Organize hive into 5x5 matrix + //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 + 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; + InkOut = NULL; + } + if (GamutRegion != NULL) + { + delete[] GamutRegion; + GamutRegion = NULL; + } + if (Lab1P != NULL) + { + delete[] Lab1P; + Lab1P = NULL; + } + if (tmpRGB != NULL) + { + delete[] tmpRGB; + tmpRGB = NULL; + } + if (LabInFinal2 != NULL) + { + delete[]LabInFinal2; + LabInFinal2 = NULL; + } + if (LabInFinal1 != NULL) + { + delete[]LabInFinal1; + LabInFinal1 = NULL; + } + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + return; +} + +void Tango::ColorLib::ColorConverter::FindTriplet(VectorXd Lab, MatrixXd Lab1, int nHive, int*indDataMax) +{ + + int vecSize = nHive * (nHive - 1) / 2; + double *dECMC = new double[vecSize]; + //double *dECMC = DBG_NEW double[vecSize]; + int i, j; + for (i = 0; i < vecSize; ++i) + dECMC[i] = -1; + int **indexpairs = new int*[vecSize]; + //int **indexpairs = DBG_NEW int*[vecSize]; + for (i = 0; i < vecSize; ++i) + { + indexpairs[i] = 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); + for (j = i + 1; j < nHive; ++j) + { + Labj << Lab1(j, 0), Lab1(j, 1), Lab1(j, 2); + ind++; + ColConv.SymmetricaldECMC(Labi, Labj, dECMC[ind]); + indexpairs[ind][0] = i; + indexpairs[ind][1] = j; + } + } + double maxdE = dECMC[0]; + int maxInd = 0; + for (int i = 1; i < vecSize; ++i) + { + if ((maxdE < dECMC[i]) && (dECMC[i] < 5)) + { + maxdE = dECMC[i]; + maxInd = i; + } + } + indDataMax[0] = indexpairs[maxInd][0]; + indDataMax[1] = indexpairs[maxInd][1]; + if (dECMC != NULL) + { + delete[]dECMC; + dECMC = NULL; + } + + if (indexpairs != NULL) + { + for (int i = 0; i < vecSize; ++i) + delete[] indexpairs[i]; + delete[] indexpairs; + indexpairs = NULL; + } + return; +} + +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 + 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]; + } +} + + +void Tango::ColorLib::ColorConverter::fillVolume(OutputCoordinates *&outputCoords, VectorXd Volume) +{ + int i = 0; + OutputLiquid** outputLiquids = (OutputLiquid**)malloc(sizeof(OutputLiquid*) * m_nVolumes); + for (i = 0; i < m_nVolumes; ++i) + { + // *outputLiquids[0] = OUTPUT_LIQUID__INIT; + outputLiquids[i] = (OutputLiquid*)malloc(sizeof(OutputLiquid)); + output_liquid__init(outputLiquids[i]); + switch (m_CalibCurves[i].getInkName()) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + { + outputLiquids[i]->has_volume = true; + outputLiquids[i]->has_liquidtype = true; + outputLiquids[i]->liquidtype = (LiquidType)(m_CalibCurves[i].getInkName()); + outputLiquids[i]->volume = Volume(i); + break; + } + default: + throw std::exception("could not fill all volumes"); + } + } + outputCoords->outputliquids = outputLiquids; + outputCoords->n_outputliquids = m_nVolumes; + return; +} + +void Tango::ColorLib::ColorConverter::fillRGB(OutputCoordinates *outputCoords, VectorXd RGBOut) +{ + outputCoords->has_red = true; + outputCoords->red = (int32_t)std::round(RGBOut(0)); + outputCoords->has_green = true; + outputCoords->green = (int32_t)std::round(RGBOut(1)); + outputCoords->has_blue = true; + 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) +{ + SetStripWhitepoint(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + bool has_forwarddata = conversionInput->has_forwarddata; + uint8_t *data = conversionInput->forwarddata.data; + int nprocessranges = conversionInput->n_processranges; + m_colortable->InitColorTables(has_forwarddata, data, nprocessranges); + SetNumberofInks(m_colortable->GetnA2BnSepOut()); +} + +void Tango::ColorLib::ColorConverter::SetStripWhitepoint(double threadl, double threada, double threadb) +{ + //Read thread white. Thread White is given in CIELab Space + m_whitepointLab.Set(threadl, threada, 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()); +} + + + +void Tango::ColorLib::ColorConverter::readCalibrationTables(InputLiquid **inputliquid, int n_inputliquid) +{ + SetNumberofInks((int)(n_inputliquid)); + //CalibData *CalibCurves = new CalibData[m_nInks]; + if(m_CalibCurves == NULL) + m_CalibCurves = new CalibData[m_nInks]; + //m_CalibCurves = DBG_NEW CalibData[m_nInks]; + for (int i = 0; i < m_nInks; ++i) + { + InputLiquid* InkType = inputliquid[i]; + + m_CalibCurves[i].SetCalibName((int)(InkType->calibrationdata->liquidtype)); + + m_CalibCurves[i].SetMaxNlPerCM(inputliquid[i]->maxnanoliterpercentimeter); + switch (InkType->calibrationdata->liquidtype) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + { + // calibration data. + CalibrationData* calibrationData = InkType->calibrationdata; + SetCalibData(calibrationData, i, &m_CalibCurves[i]); + m_CalibCurves[i].InitInterpolations(); + break; + } + default: + { + throw std::exception("could not fill all calibration tables"); + return; + } + } + } + return; +} + + +void Tango::ColorLib::ColorConverter::SetCalibData(CalibrationData *calibrationData, int i, CalibData *tmpCurve) +{ + if (calibrationData->calibrationpoints <= 0) + { + char msg[100]; + int n = + strcpy_s(msg, 100, "No Calibration points in table "); + + throw std::exception(msg); + return; + } + + tmpCurve->SetCalibCurveSize((int)(calibrationData->n_calibrationpoints)); + //Iterate over calibration points.. + double *pointsx = new double[calibrationData->n_calibrationpoints]; + double *pointsy = new double[calibrationData->n_calibrationpoints]; + //double *pointsx = DBG_NEW double[calibrationData->n_calibrationpoints]; + //double *pointsy = DBG_NEW double[calibrationData->n_calibrationpoints]; + for (size_t j = 0; j < calibrationData->n_calibrationpoints; ++j) + { + //Calibration Point + pointsx[j] = calibrationData->calibrationpoints[j]->x; + pointsy[j] = calibrationData->calibrationpoints[j]->y; + } + tmpCurve->SetXCoords(pointsx); + tmpCurve->SetYCoords(pointsy); + if (pointsx != NULL) + { + delete[] pointsx; + pointsx = NULL; + } + + if (pointsy != NULL) + { + delete[] pointsy; + pointsy = NULL; + } + return; +} + +void Tango::ColorLib::ColorConverter:: ConvertLabColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + // 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. Convert Lab to Inks (B2A tables), Inks to Volume + //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] = inputcoordinates->l; //Absolute Colorimetric + LabIn[1] = inputcoordinates->a; + LabIn[2] = 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]; + //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 + 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); //LabInFinal2 is in Relative Colorimetric Space + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //LabInFinal2 is in Relative Colorimetric Space + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + + //convert to Inks + double *InkOutP = new double[m_nInks]; + //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; + m_colortable->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); +//Convert InkOutP to linear in the m_GamutRegionMaxLim[0] range + for (int i = 0; i < m_nInks; ++i) + { + InkOutP[i] *= m_colortable->GetNormFactor(); + if (InkOutP[i] <= m_NormGamutRegionMaxLim[0]) + { + m_colortable->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]; + 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); + CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_WP); +/* + if (m_AdaptWP) + { + 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 = DBG_NEW double[3]; + //Use Relative colorimetric to get RGB + CConvertD65.LabtoRGBNoClip(LabOnGamut, RGBOutP); + //CConvertD65.LabtoRGB(LabIn, RGBOutP); + RGBOut = DoubleToVector(RGBOutP, 3); + if (LabOnGamut != NULL) + { + delete[] LabOnGamut; + LabOnGamut = NULL; + } + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + /* if (LabInFinal1 != NULL) + { + delete[]LabInFinal1; + LabInFinal1 = NULL; + } + */ + if (LabInFinal2 != NULL) + { + delete[]LabInFinal2; + LabInFinal2 = NULL; + } + if (LabOutFinal != NULL) + { + delete[]LabOutFinal; + LabOutFinal = NULL; + } + + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } +} + + +void Tango::ColorLib::ColorConverter::ConvertRGBColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + // 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, but will be shown in Relative Colorimetric to the user + //The workflow is a follows: + //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 Color Table whitepoints + //5. Use the Relative Colorimetric Lab to obtain RGB + + RGBOut(0) = inputcoordinates->red; + RGBOut(1) = inputcoordinates->green; + RGBOut(2) = inputcoordinates->blue; + //convert to Lab + ColorConvert CConvertD65(D65, D65); //Destination, source + double *LabIn = new double[3]; + double *RGBOutP = new double[3]; + //double *LabIn = DBG_NEW double[3]; + //double *RGBOutP = DBG_NEW double[3]; + VectorToDouble(RGBOut, RGBOutP); + //RGB to Lab + 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 + + double *InkOutP = new double[m_nInks]; + //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; + //LabInFinal is in Relative Colorimetric, just like the Color Tables + m_colortable->m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is inthe [0-100] interval + + //Convert to Lab to get the actual in Gamut Lab + //double *LabInP = new double[3]; + //double *LabInP = DBG_NEW double[3]; + //m_A2BTransform->evalInkP2Lab(InkOutP, LabInP, GamutRegion); //Lab is in Relative Colorimetric + //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_nInks; ++i) + { + InkOutP[i] *= m_colortable->GetNormFactor(); + if (InkOutP[i] <= m_NormGamutRegionMaxLim[0]) + { + m_colortable->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); + CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_Strip, 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); + double *RGBOutP1 = new double[3]; + //double *RGBOutP1 = DBG_NEW double[3]; + CConvertD65.LabtoRGBNoClip(LabOnGamut, RGBOutP1); + //CConvertD65.LabtoRGB(LabInP, RGBOutP1); + RGBOut = DoubleToVector(RGBOutP1, 3); + if (LabOnGamut != NULL) + { + delete[] LabOnGamut; + LabOnGamut = NULL; + } + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + if (RGBOutP1 != NULL) + { + delete[] RGBOutP1; + RGBOutP1 = NULL; + } + if (LabInFinal != NULL) + { + delete[] LabInFinal; + LabInFinal = NULL; + } + } + +void Tango::ColorLib::ColorConverter::ConvertCMYKColorToLinearInks(InputCoordinates* inputcoordinates, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS) +{ + //no conversion + //missing from structure light inks or special colors + // just convert Lab for rgb display + + double *outData = new double[m_nInks]; + //double *outData = DBG_NEW double[m_nA2BnSepIn]; + size_t CountSep = 0; + outData[0] = (double)(inputcoordinates->cyan); + outData[1] = (double)(inputcoordinates->magenta); + outData[2] = (double)(inputcoordinates->yellow); + outData[3] = (double)(inputcoordinates->key); + CountSep = 4; + + if (CountSep != m_nInks) + { + //mismatch between table and sent data + throw std::exception("Mismatch between table and sent data"); + return; + } + //Convert to RGB + double *InkOutP = new double[m_nInks]; + //double *InkOutP = DBG_NEW double[m_nA2BnSepIn]; + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] = outData[i]; + double *LabOutP = new double[3]; + //double *LabOutP = DBG_NEW double[3]; + m_colortable->m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion); + InkOut = DoubleToVector(InkOutP, m_nInks); + //LabOut is in relative colorimetric + ColorConvert CConvertD65(D65, D65); + double *LabOutFinal1 = new double[3]; + //double *LabOutFinal1 = DBG_NEW double[3]; + for (int i = 0; i < 3; ++i) + LabOutFinal1[i] = LabOutP[i]; + double *LabOutFinal2 = new double[3]; + //double *LabOutFinal2 = DBG_NEW double[3]; + 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); //To Absolute + CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_Strip, m_WP); //To Absolute +/* if (m_AdaptWP) + { + CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal2, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); + 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(LabOutP, RGBOutP); + //CConvertD65.LabtoRGB(LabOutP, RGBOutP); + RGBOut = DoubleToVector(RGBOutP, 3); + + if (outData != NULL) + { + delete[] outData; + outData = NULL; + } + if (LabOutP != NULL) + { + delete[] LabOutP; + LabOutP = NULL; + } + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + if (LabOutFinal1 != NULL) + { + delete[] LabOutFinal1; + LabOutFinal1 = NULL; + } + if (LabOutFinal2 != NULL) + { + delete[] LabOutFinal2; + LabOutFinal2 = NULL; + } +} +void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion, bool &InGamut) +{ + size_t nInks = 0; + + C_RGB_XYZ_Lab DataLab; + SURROUND sur = m_Conv02->getSurround(); + CAM02CS CS = m_Conv02->getCAM02CS(); + switch (colorspace) + { + case (COLOR_SPACE__RGB): + { + ConvertRGBColorToLinearInks(inputcoordinates, + InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS); + break; + } + case (COLOR_SPACE__LAB): + { + ConvertLabColorToLinearInks(inputcoordinates, + InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS); + break; + } + + case(COLOR_SPACE__CMYK): + { + ConvertCMYKColorToLinearInks(inputcoordinates, + InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS); + + break; + } + case(COLOR_SPACE__Catalog): + { + int32_t inData; + if (inputcoordinates->has_pantoncode) + inData = 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: + { + throw std::exception(" Unsupported Color Space"); + break; + } + } + //all data is now in linear ink format + return; +} + + +void Tango::ColorLib::ColorConverter::ConvertToNLInks(VectorXd InkIn, VectorXd &InkOut) +{ + for (int i = 0; i < m_nVolumes; ++i) + { + if (InkIn(i) <= m_NormGamutRegionMaxLim[0]) + m_CalibCurves[i].m_InvLinearInterp->Eval(InkIn(i), InkOut(i)); + else + InkOut(i) = InkIn(i); + } + return; +} + +void Tango::ColorLib::ColorConverter::ConvertToLinearInks(VectorXd InkIn, VectorXd &InkOut) +{ + for (int i = 0; i < m_nVolumes; ++i) + { + m_CalibCurves[i].m_LinearInterp->Eval(InkIn(i), InkOut(i)); + } + + return; +} + +void Tango::ColorLib::ColorConverter::VolumeToNLInkP(VectorXd Volume, VectorXd &NLInkP) +{ + //Volume is in %. In order to be compatible with NL to volume it has to be tranlated to nl/cm + VectorXd InkP(m_nVolumes); + int MaxInd = -1; + double InkMax = -1.; + double InkSum = 0.; + for (int i = 0; i < m_nVolumes; ++i) + { + InkP(i) = Volume(i)* m_maxNlPerCM(i)/100; //Volume is in %, InkP is in [nl/cm] + if (InkMax < InkP(i)) + { + InkMax = InkP(i); + MaxInd = i; + } + InkSum += InkP(i); + } + NLInkP(MaxInd) =100* InkSum/ m_maxNlPerCM(MaxInd); //Back to % + if (InkSum == 0.0) + { + for (int i = 0; i < m_nVolumes; ++i) + NLInkP(i) = 0.0; + return; + } + + //Prepare Matrix to get the remainder values + MatrixXd MatNLI(m_nVolumes - 1, m_nVolumes - 1); + VectorXd RHSide(m_nVolumes - 1); + MatrixXd DiagMat(m_nVolumes - 1, m_nVolumes - 1); + DiagMat.setZero(); + int ind = -1; + for (int i = 0; i < m_nVolumes; ++i) + { + if (i != MaxInd) + { + ind += 1; + RHSide(ind) = InkP(i); + DiagMat(ind, ind) = -InkSum; + } + } + for (int i = 0; i < m_nVolumes - 1; ++i) + { + for (int j = 0; j < m_nVolumes - 1; ++j) + { + MatNLI(i, j) = RHSide(i) + DiagMat(i, j); + } + RHSide(i) *= (-InkSum); + } + //Solve System of Linear Equations + MatrixXd MatNLIInv(m_nVolumes - 1, m_nVolumes - 1); + MatNLIInv = MatNLI.inverse(); + VectorXd Result = MatNLIInv * RHSide; + //VectorXd Result = MatNLI.colPivHouseholderQr().solve(RHSide); + //rearrange solution + ind = -1; + for (int i = 0; i < m_nVolumes; ++i) + { + if (i != MaxInd) + { + ind += 1; + NLInkP(i) =100* Result(ind)/m_maxNlPerCM(i); //Back to % + } + } + return; +} + +void Tango::ColorLib::ColorConverter::NLInkPToVolume(VectorXd NLInk, VectorXd &Volume) +{ + //Max Ink Component + double MaxInk = -1.; + VectorXd InkNorm(m_nInks); + double InkSum = 0; + int i = 0; + for (i = 0; i < m_nInks; ++i) + { + MaxInk = std::max(MaxInk, NLInk(i)); + InkSum += NLInk(i); + } + + if (MaxInk == 0) + for (i = 0; i < m_nInks; ++i) + Volume(i) = 0.0; + else + { + for (i = 0; i < m_nInks; ++i) + { + 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); + double ROUNDINGTol = pow(10, ROUNDINGDigits); + + for (i = 0; i < m_nInks; ++i) + { + sumNorm += Volume(i); + RVolNorm(i) = round(Volume(i)*ROUNDINGTol) / ROUNDINGTol; + RsumNorm += RVolNorm(i); + } + if (RsumNorm > m_NormGamutRegionMaxLim[m_nProcessRanges - 1] || abs(sumNorm - RsumNorm) >= 1 / ROUNDINGTol) + { + VectorXd dd(m_nInks); + double maxdd = -1; + int maxInd = -1; + for (int i = 0; i < m_nInks; ++i) + { + dd(i) = Volume(i) - RVolNorm(i); + if (abs(dd(i)) > maxdd) + { + maxdd = abs(dd(i)); + maxInd = i; + } + } + int signdd = 0; + if (dd(maxInd) > 0) + signdd = 1; + else if (dd(maxInd) < 0) + signdd = -1; + else + signdd = 0; + RVolNorm(maxInd) = RVolNorm(maxInd) + signdd / ROUNDINGTol; + } + for (int i = 0; i < m_nInks; ++i) + Volume(i) = RVolNorm(i); + } + for (int i = 0; i < m_nInks; ++i) + { + if (Volume(i) < LowVolHalf) + Volume(i) = 0; + else if (Volume(i) >= LowVolHalf && Volume(i) <= LowVolumeThreshold) + Volume(i) = LowVolumeThreshold; + } + + /* int countBelowThresh=0; + int *indBelowThresh= new int[m_nInks]; + for (int i = 0; i < m_nInks; ++i) + { + if (Volume(i) < LowVolumeThreshold) + { + countBelowThresh++; + indBelowThresh[i] = i; + } + } + if (countBelowThresh == 0) + { + delete[] indBelowThresh; + indBelowThresh = NULL; + } + else + { + int pow2ThCount = pow(2, countBelowThresh); + double **THTable = new double*[pow2ThCount]; + for (int i = 0; i < pow2ThCount; ++i) + THTable[i] = new double[m_nInks]; + for (int j = 0; j < pow2ThCount; ++j) + for (int i = 0; i < m_nInks; ++i) + THTable[j][i] = Volume(i); + + int indC = -1; + for (int i = 0; i < m_nInks; ++i) + { + for (int j = 0; j < countBelowThresh; ++i) + { + indC = indC + 1; + THTable[indC][i] = 0; + indC = indC + 1; + THTable[indC][i] = LowVolumeThreshold; + } + } + //Calculate dE between NLInk and THTable converted to NLInk + //Choose the value with the smallest dE + VectorXd VolumeTh(m_nInks); + VectorXd NLInksTh(m_nInks); + for (int j = 0; j < pow2ThCount; ++j) + { + for (int j = 0; j < m_nInks; ++j) + VolumeTh(j) = THTable[j][i]; + VolumeToNLInkP(VolumeTh, NLInksTh); + + + } + + }*/ + + return; +} + +void Tango::ColorLib::ColorConverter::SetMaxNLperCM(double maxNlPerCM, int i) +{ + m_maxNlPerCM(i) = maxNlPerCM; +} + +void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(InputCoordinates *inputcoordinates, int n_processRanges, + int colorspace, VectorXd &Volume, VectorXd &RGBOut, VectorXd &LabOut, int &GamutRegion) +{ + SetNumberOfVolumes((int)(inputcoordinates->n_inputliquids)); + // 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) + { + LQ =inputcoordinates->inputliquids[i]->calibrationdata->liquidtype; + if (LQ == LIQUID_TYPE__Cyan || LQ == LIQUID_TYPE__Magenta || LQ == LIQUID_TYPE__Yellow || LQ == LIQUID_TYPE__Black) + { + //Get calibration data. + CalibrationData* calibrationData = inputcoordinates->inputliquids[i]->calibrationdata; + SetCalibData(calibrationData, i, &m_CalibCurves[i]); + SetMaxNLperCM(inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); + m_CalibCurves[i].SetCalibName((int)(inputcoordinates->inputliquids[i]->calibrationdata->liquidtype)); + } + else + std::exception("unsupported volume"); + } + } + + //July 29 2020 + //Limit inks based on m_maxNlpercm + //Inks are limited in their nonlinear form + VectorXd NLInkP((int)(m_nVolumes)); + VectorXd InkOut((int)(m_nVolumes)); + //Convert to Nonlinear Inks + double SumVol_Ink = 0.0; + //Get Gamut Region + for (int i = 0; i < m_nVolumes; ++i) + Volume(i) = inputcoordinates->inputliquids[i]->volume; //volume is given in % + + GamutRegion = GetGamutRegion(Volume, m_NormGamutRegionMaxLim); + VolumeToNLInkP(Volume, NLInkP); + //Limit Inks + double *InkOutP = new double[m_nInks]; + VectorToDouble(NLInkP, InkOutP); + //for (int i = 0; i < m_nA2BnSepIn; ++i) + // InkOutP[i] = NLInkP(i); + double *LinInkP = new double[m_nInks]; +//Reflect the Calibration Curves of the thread in Catalog Items + if (colorspace == COLOR_SPACE__Catalog) + { + for (int i = 0; i < m_nInks; ++i) + { + if (NLInkP(i) <= m_NormGamutRegionMaxLim[0]) + { + m_colortable->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_NormGamutRegionMaxLim[0]) + { + m_CalibCurves[i].m_InvLinearInterp->Eval(InkOutP[i], InkOutP[i]); + NLInkP(i) = InkOutP[i]; + } + } + //NLInkPToVolume(NLInkP, Volume); + } + + //July 29 2020 + //Limit inks based on m_maxNlpercm + //Inks are limited in their nonlinear form + //Output Volume is in % + LimitInks(NLInkP, InkOutP); + NLInkPToVolume(DoubleToVector(InkOutP, m_nInks), Volume); + GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP); + NLcmtoPercentage(Volume, Volume); + + //Convert to RGB + //GamutRegion = 0; + //Convert to Lab + + double *LabOutP = new double[3]; + //double *InkOutP = DBG_NEW double[m_nA2BnSepIn]; + //double *LabOutP = DBG_NEW double[m_nA2BnSepOut]; + //InkOutP has to be normalized to match the transform units + for (int i = 0; i < m_nInks; ++i) + InkOutP[i] *= m_colortable->GetInverseNormFactor(); + + m_colortable->m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion); + //LabOutP is in Relative Colorimetric + ColorConvert CConvertD65(D65, D65); + double *LabOutFinal1 = new double[3]; + //double *LabOutFinal1 = DBG_NEW double[3]; + double *LabOutFinal = new double[3]; + + //CConvertD65.ChangeWP(LabOutP, LabOutFinal1, m_whitepointXYZ_CT, m_WP); //To Absolute + CConvertD65.ChangeWP(LabOutP, LabOutFinal1, m_whitepointXYZ_Strip, 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); + } + */ + LabOut = DoubleToVector(LabOutFinal, 3); + + CConvertD65.SetReferenceWhite(D65); + double *RGBOutP = new double[3]; + //double *RGBOutP = DBG_NEW double[3]; + CConvertD65.LabtoRGB(LabOutP, RGBOutP); + + for (int i = 0; i < 3; ++i) + { + RGBOut(i) = RGBOutP[i]; + } + if (InkOutP != NULL) + { + delete[]InkOutP; + InkOutP = NULL; + } + if (LinInkP != NULL) + { + delete[]LinInkP; + LinInkP = NULL; + } + if (LabOutP != NULL) + { + delete[] LabOutP; + LabOutP = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + if (LabOutFinal1 != NULL) + { + delete[] LabOutFinal1; + LabOutFinal1 = NULL; + } + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } + return; + +} + +void Tango::ColorLib::ColorConverter::VectorToDouble(VectorXd VecIn, double * doubOut) +{ + int nSize = VecIn.size(); + for (int i = 0; i < nSize; ++i) + doubOut[i] = VecIn(i); +} + +VectorXd Tango::ColorLib::ColorConverter::DoubleToVector(double *doub, int nSize) +{ + VectorXd Vec(nSize); + for (int i = 0; i < nSize; ++i) + Vec(i) = doub[i]; + 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) +{ + + ConversionInput* conversionInput = NULL; + InputLiquid** original_input_liquids = NULL; + int original_input_liquids_count = 0; + + try + { + //Get Input + conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); + + //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); + if(m_colortable ==NULL) + m_colortable = new ColorTable(); + readColorTransformations(conversionInput); + m_nProcessRanges = conversionInput->n_processranges; + if(m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nProcessRanges]; + double *tmpVal = m_colortable->GetNormGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = tmpVal[i]; + //read calibration tables and store them in m_CalibCurves + InputLiquid **inputliquids = conversionInput->inputcoordinates->inputliquids; + int n_inputliquids = conversionInput->inputcoordinates->n_inputliquids; + readCalibrationTables(inputliquids, n_inputliquids); + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if(m_Conv02 ==NULL) + 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); + + // Compare Strip White point to Color Table White Point + //CompareWhitePoints(); + + if (numofInks != m_nInks) + throw std::exception("Number of available inks does not match ink tables\0"); + + //Tables have been filled + //Set Process Ranges + if(m_ProcessRangesMaxP == NULL) + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMaxP[i] = conversionInput->processranges[i]->maxinkuptake; + } + + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + VectorXd VolumeOut(m_nInks); + //set maxNlPerCM + VectorXd NlperCM(m_nInks); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nInks; ++i) + SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); + m_nVolumes = m_nInks; + int GamutRegion = 0; + //Convert input data to linear inks + if (conversionInput->colorspace == COLOR_SPACE__Volume || conversionInput->colorspace == COLOR_SPACE__Catalog) + { + InputCoordinates *IC = conversionInput->inputcoordinates; + int colorspace = conversionInput->colorspace; + ConvertVolumeToRGBDisplay(IC, conversionInput->n_processranges, colorspace, Volume, RGBOut, LabOut, GamutRegion); + InGamut = true; + } + else + { + ConvertColorToLinearInks(conversionInput->inputcoordinates, conversionInput->colorspace, 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); + + //Limit inks based on m_maxNlpercm + //Inks are limited in their nonlinear form + //Output Volume is in % + double *InkOutP = new double[m_nInks]; + LimitInks(NLInkOut, InkOutP); + NLInkPToVolume(DoubleToVector(InkOutP, m_nInks), Volume); + GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP); + NLcmtoPercentage(Volume, Volume); + //OutputCoordinates outputCoords = OUTPUT_COORDINATES__INIT; + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + + } + OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(outputCoords); + fillRGB(outputCoords, RGBOut); + fillLab(outputCoords, LabOut); + outputCoords->has_processparameterstableindex = true; + outputCoords->processparameterstableindex = GamutRegion; + fillVolume(outputCoords, Volume); + conversionOutput->has_outofgamut = true; + conversionOutput->outofgamut = !(InGamut); + conversionOutput->singlecoordinates = outputCoords; + + if (conversionInput->generatehive) + { + //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++) + { + 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); + +#pragma region Free Conversion Input & Output + + conversionInput->inputcoordinates->inputliquids = original_input_liquids; + conversionInput->inputcoordinates->n_inputliquids = original_input_liquids_count; + + conversion_input__free_unpacked(conversionInput, NULL); + + conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + return (size); + } + catch (const std::exception& e) + { + //Notify Error... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + conversion_output__init(conversionOutput); + + conversionOutput->has_haserror = true; + conversionOutput->haserror = true; + + const char* what = e.what(); + int nWhat = strlen(what); + conversionOutput->errormessage = (char*)malloc(nWhat); + //conversionOutput->errormessage = new char[nWhat]; + for (int i = 0; i < nWhat; ++i) + conversionOutput->errormessage[i] = what[i]; + //strcpy_s(conversionOutput->errormessage, nWhat, what); + + output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(conversionOutput)); + int size = conversion_output__pack(conversionOutput, output_buffer); + +#pragma region Free Conversion Input & Output + + conversionInput->inputcoordinates->inputliquids = original_input_liquids; + conversionInput->inputcoordinates->n_inputliquids = original_input_liquids_count; + + conversion_input__free_unpacked(conversionInput, NULL); + conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + return (size); + } +} + + + +/*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(); + yCoords = m_CalibCurves[i].getyCoords(); + int npts = m_CalibCurves[i].getSize(); + linearInterp[i].SetXCoords(xCoords); + linearInterp[i].SetYCoords(yCoords); + linearInterp[i].SetNPoints(npts); + InvLinearInterp[i].SetXCoords(yCoords); + InvLinearInterp[i].SetYCoords(xCoords); + InvLinearInterp[i].SetNPoints(npts); + } +}*/ + +int Tango::ColorLib::ColorConverter::CountNumberofInks(ConversionInput* conversionInput) +{ + int nLiquids = conversionInput->inputcoordinates->n_inputliquids; + int numberofInks = 0; + //Cyan + int nCyan = 0;; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Cyan) + nCyan++; + } + if (nCyan > 1) + { + numberofInks = -1; + return(numberofInks); + } + int nMagenta = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Magenta) + nMagenta++; + } + if (nMagenta > 1) + { + numberofInks = -1; + return(numberofInks); + } + int nYellow = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Yellow) + nYellow++; + } + if (nYellow > 1) + { + numberofInks = -1; + return(numberofInks); + } + int nBlack = 0; + for (int i = 0; i < nLiquids; ++i) + { + if (conversionInput->inputcoordinates->inputliquids[i]->liquidtype == LIQUID_TYPE__Black) + nBlack++; + } + if (nBlack > 1) + { + numberofInks = -1; + return(numberofInks); + } + numberofInks = nCyan + nMagenta + nYellow + nBlack; + return(numberofInks); +} + +bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord) +{ + 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_colortable->m_GBD->getCenter(); + VectorXd JInLab(3); + JInLab << InLab[0], InLab[1], InLab[2]; + VectorXd JLab = m_Conv02->LabToJab(JInLab, sur); + ctr[0] = -JLab(0) + center.Get_x(); + ctr[1] = -JLab(1) + center.Get_y(); + ctr[2] = -JLab(2) + center.Get_z(); + double *dJLab = new double[3]; + //double *dJLab = DBG_NEW double[3]; + VectorToDouble(JLab, dJLab); + bool intersect = false; + m_colortable->m_GBD->TriangleRayIntersection(dJLab, ctr, intersect, xCoord); + if (intersect) + { + VectorXd V1(3); + VectorXd V2(3); + V1 << JLab[0], JLab[1], JLab[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; + xCoord = NULL; + } + if (dJLab != NULL) + { + delete[]dJLab; + dJLab = NULL; + } + return(InGamut); +} + + + + +void Tango::ColorLib::ColorConverter::read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput) +{ + /* + 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 number of Shift Bits + 12 Number of gamut regions + 13 - n CLUT values, uint16 + + 13 - n output tables, uint8 + */ + if (data_size < 32) + { + throw std::exception(" LUT size missmatch"); + return; + } + int bytesread = 0; + // Check for signature + uint8_t *buff = &conversionInput->forwarddata.data[offset]; + Transf->InitData(buff, data_size); + return; +} + + + + + + + +/*void Tango::ColorLib::ColorConverter::CompareWhitePoints() +{ + ColorConvert ColConv(D65, D65); + C_RGB_XYZ_Lab Lab_CT; + C_RGB_XYZ_Lab Lab_Strip; + Lab_CT = ColConv.XYZToLab(m_whitepointXYZ_CT); + Lab_Strip = ColConv.XYZToLab(m_whitepointXYZ_Strip); + VectorXd VLab_CT(3); + VectorXd VLab_Strip(3); + VLab_CT(0) = Lab_CT.Get_x(); + VLab_CT(1) = Lab_CT.Get_y(); + VLab_CT(2) = Lab_CT.Get_z(); + VLab_Strip(0) = Lab_Strip.Get_x(); + VLab_Strip(1) = Lab_Strip.Get_y(); + VLab_Strip(2) = Lab_Strip.Get_z(); + double dECMC; + ColConv.SymmetricaldECMC(VLab_CT, VLab_Strip, dECMC); + if (dECMC > WPTol) + m_AdaptWP = true; + if (m_whitepointXYZ_Strip.Get_x() <= 0 || m_whitepointXYZ_Strip.Get_y() <= 0 || m_whitepointXYZ_Strip.Get_z()<=0) + m_AdaptWP = false; + return; +} */ /* not used*/ + +//size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +//{ +// //Unpack conversion input... +// ConversionInput* conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); +// +// //Initialize Output... +// ConversionOutput conversionOutput = CONVERSION_OUTPUT__INIT; +// +// //The request is for RGB to Volume... +// if (conversionInput->colorspace == COLOR_SPACE__RGB) +// { +// //Get RGB values... +// int r = conversionInput->inputcoordinates->red; +// int g = conversionInput->inputcoordinates->green; +// int b = conversionInput->inputcoordinates->blue; +// +// //iterate over input liquids... +// for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) +// { +// InputLiquid* inputLiquid = conversionInput->inputcoordinates->inputliquids[i]; +// +// //Get cyan liquid for example... +// if (inputLiquid->liquidtype == LIQUID_TYPE__Cyan) +// { +// //Get liquid max nl per cm. +// double maxNlPerCM = inputLiquid->maxnanoliterpercentimeter; +// +// //Get liquid calibration data. +// CalibrationData* calibrationData = inputLiquid->calibrationdata; +// +// //Iterate over calibration points.. +// for (size_t j = 0; j < calibrationData->n_calibrationpoints; j++) +// { +// //Calibration Point +// CalibrationPoint* point = calibrationData->calibrationpoints[j]; +// +// double x = point->x; +// double y = point->y; +// } +// } +// } +// +// //Set conversion output with proper volumes... +// +// //Set Cyan liquid volume... +// OutputLiquid cyanLiquid = OUTPUT_LIQUID__INIT; +// cyanLiquid.has_volume = true; +// cyanLiquid.has_liquidtype = true; +// cyanLiquid.liquidtype = LIQUID_TYPE__Cyan; +// cyanLiquid.volume = 20; +// +// //Set Magenta liquid volume... +// OutputLiquid magentaLiquid = OUTPUT_LIQUID__INIT; +// magentaLiquid.has_volume = true; +// magentaLiquid.has_liquidtype = true; +// magentaLiquid.liquidtype = LIQUID_TYPE__Magenta; +// magentaLiquid.volume = 30; +// +// OutputLiquid** outputLiquids = (OutputLiquid**)malloc(sizeof(OutputLiquid*) * 2); +// +// //Add cyan and magenta to output liquids array. +// outputLiquids[0] = &cyanLiquid; +// outputLiquids[1] = &magentaLiquid; +// +// OutputCoordinates outCoords; +// outCoords.outputliquids = outputLiquids; +// +// conversionOutput.singlecoordinates = &outCoords; +// } +// +// +// +// //The request is for volumes to RGB... +// else if (conversionInput->colorspace == COLOR_SPACE__Volume) +// { +// //iterate over input liquids... +// for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) +// { +// InputLiquid* inputLiquid = conversionInput->inputcoordinates->inputliquids[i]; +// +// //Get cyan liquid for example... +// if (inputLiquid->liquidtype == LIQUID_TYPE__Cyan) +// { +// //Get liquid max nl per cm. +// double maxNlPerCM = inputLiquid->maxnanoliterpercentimeter; +// +// //Get liquid volume. +// double volume = inputLiquid->volume; +// +// //Get liquid calibration data. +// CalibrationData* calibrationData = inputLiquid->calibrationdata; +// +// //Iterate over calibration points.. +// for (size_t j = 0; j < calibrationData->n_calibrationpoints; j++) +// { +// //Calibration Point +// CalibrationPoint* point = calibrationData->calibrationpoints[j]; +// +// double x = point->x; +// double y = point->y; +// } +// } +// else if (inputLiquid->liquidtype == LIQUID_TYPE__Magenta) +// { +// //Same as above... +// } +// } +// +// //Set conversion output (single) with proper RGB values... +// OutputCoordinates outputCoords = OUTPUT_COORDINATES__INIT; +// outputCoords.has_red = true; +// outputCoords.has_green = true; +// outputCoords.has_blue = true; +// outputCoords.red = 50; +// outputCoords.green = 100; +// outputCoords.blue = 150; +// +// conversionOutput.singlecoordinates = &outputCoords; +// +// //Set conversion output (hive) with proper RGB values... +// +// int hiveCellCount = 10; +// +// OutputCoordinates** hiveCoordinates = (OutputCoordinates**)malloc(sizeof(OutputCoordinates*) * hiveCellCount); +// +// for (size_t i = 0; i < hiveCellCount; i++) +// { +// OutputCoordinates cellCoords = OUTPUT_COORDINATES__INIT; +// cellCoords.has_red = true; +// cellCoords.has_green = true; +// cellCoords.has_blue = true; +// cellCoords.red = 10; +// cellCoords.green = 20; +// cellCoords.blue = 30; +// +// hiveCoordinates[i] = &cellCoords; +// } +// +// conversionOutput.hivecoordinates = hiveCoordinates; +// } +// +// //Pack output... +// output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(&conversionOutput)); +// +// 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) +{ + + //Get Input + ConversionInput* conversionInput = (ConversionInput*)malloc(sizeof(ConversionInput)); + + conversionInput = conversion_input__unpack(NULL, input_buffer_size, input_buffer); + + + + //Filter and arrange colors (Should change from 3 to 4 if black ink is included) + /*int expected_liquids = 3; + + 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; + } + } + + conversionInput->inputcoordinates->inputliquids = filteredInputLiquids; + conversionInput->inputcoordinates->n_inputliquids = expected_liquids; + //Filter and arrange colors + + */ + + //Initialize Output... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + if (conversionOutput != NULL) + conversion_output__init(conversionOutput); + else + return(0); + + // 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 + int n_inputliquids = conversionInput->inputcoordinates->n_inputliquids; + InputLiquid **inputliquid = conversionInput->inputcoordinates->inputliquids; + readCalibrationTables(inputliquid, n_inputliquids); + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if(m_Conv02 == NULL) + 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); + + // Compare Strip White point to Color Table White Point + //CompareWhitePoints(); + + if (numofInks != m_nInks) + throw std::exception("Number of available inks does not match ink tables"); + + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + + 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, CS, LabIn); + + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (RGBOutP != NULL) + { + 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 + + 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 + //We relate to the color table as a generic one in Relative Colorimetric Space + /* + 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 + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //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; + } + case(COLOR_SPACE__CMYK): + case(COLOR_SPACE__Volume): + case(COLOR_SPACE__Catalog): + {//no conversion + //missing from structure light inks or special colors + // just convert Lab for rgb display + InGamut = true; + } + //case(COLOR_SPACE__Catalog): + //{ + // 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)); + output_coordinates__init(outputCoords); + conversionOutput->has_outofgamut = true; + conversionOutput->outofgamut = !(InGamut); + conversionOutput->singlecoordinates = outputCoords; + + //Pack output... + output_buffer = (uint8_t*)malloc(conversion_output__get_packed_size(conversionOutput)); + int size = conversion_output__pack(conversionOutput, output_buffer); + +#pragma region Free Conversion Input & Output + + //conversionInput->inputcoordinates->inputliquids = original_input_liquids; + //conversionInput->inputcoordinates->n_inputliquids = original_input_liquids_count; + + conversion_input__free_unpacked(conversionInput, NULL); + + conversion_output__free_unpacked(conversionOutput, NULL); + +#pragma endregion + + return (size); +} + + +size_t Tango::ColorLib::ColorConverter::GenerateGradient(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer) +{ + //Get Input... + GradientConversionInput* conversionInput = (GradientConversionInput*)malloc(sizeof(GradientConversionInput)); + conversionInput = gradient_conversion_input__unpack(NULL, input_buffer_size, input_buffer); + //Initialize Output... + GradientConversionOutput *conversionOutput = (GradientConversionOutput*)malloc(sizeof(GradientConversionOutput)); + gradient_conversion_output__init(conversionOutput); + + conversionOutput->haserror = false; + conversionOutput->has_haserror = false; + //Get segment length... + double segmentLength = conversionInput->segmentlength; + if(m_colortable == NULL) + m_colortable = new ColorTable(); + PrepareGradient(conversionInput, conversionOutput); + //Get liquid types info... + /* InputLiquid* cyan = NULL; + InputLiquid* magenta = NULL; + InputLiquid* yellow = NULL; + InputLiquid* black = NULL; + + for (size_t i = 0; i < conversionInput->n_inputliquids; i++) + { + switch (conversionInput->inputliquids[i]->liquidtype) + { + case LIQUID_TYPE__Cyan: + cyan = conversionInput->inputliquids[i]; + break; + case LIQUID_TYPE__Magenta: + magenta = conversionInput->inputliquids[i]; + break; + case LIQUID_TYPE__Yellow: + yellow = conversionInput->inputliquids[i]; + break; + case LIQUID_TYPE__Black: + black = conversionInput->inputliquids[i]; + break; + } + }*/ + + //Pack output... + output_buffer = (uint8_t*)malloc(gradient_conversion_output__get_packed_size(conversionOutput)); + int size = gradient_conversion_output__pack(conversionOutput, output_buffer); + + //RELEASE MEMORY HERE !!! + #pragma region Free Conversion Input & Output + + gradient_conversion_input__free_unpacked(conversionInput, NULL); + + gradient_conversion_output__free_unpacked(conversionOutput, NULL); + + #pragma endregion + + return size; + +} + +void Tango::ColorLib::ColorConverter::fillGradientStops(GradientConversionInput *conversionInput) +{ + C_RGB_XYZ_Lab RGB; + C_RGB_XYZ_Lab Lab; + for (int i = 0; i < m_nGradStops; ++i) + { + switch (conversionInput->stops[i]->colorspace) + { + case COLOR_SPACE__RGB: //Case RGB + RGB = C_RGB_XYZ_Lab(conversionInput->stops[i]->red, conversionInput->stops[i]->green, conversionInput->stops[i]->blue); + m_GradStops[i].Set_RGB(RGB); + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__RGB); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + break; + case COLOR_SPACE__LAB: //Case LAB + Lab = C_RGB_XYZ_Lab(conversionInput->stops[i]->l, conversionInput->stops[i]->a, conversionInput->stops[i]->b); + m_GradStops[i].Set_Lab(Lab); + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__LAB); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + break; + case COLOR_SPACE__Volume: //Case Volume + m_GradStops[i].Set_ColorSpace(COLOR_SPACE__Volume); + m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset); + for (int j = 0; j < (int)conversionInput->stops[i]->n_liquidvolumes; j++) + { + LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j]; + + switch (liquidVolume->liquidtype) + { + case LIQUID_TYPE__Cyan: + m_GradStops[i].SetVolumeValue(liquidVolume->volume,0); + break; + case LIQUID_TYPE__Magenta: + m_GradStops[i].SetVolumeValue(liquidVolume->volume, 1); + break; + case LIQUID_TYPE__Yellow: + m_GradStops[i].SetVolumeValue(liquidVolume->volume, 2); + break; + case LIQUID_TYPE__Black: + m_GradStops[i].SetVolumeValue(liquidVolume->volume, 3); + break; + default: + throw std::exception("could not fill all volumes"); + } + } + break; + } + } +} + + +void Tango::ColorLib::ColorConverter::findStops(Gradient &GradStop1, Gradient &GradStop2, double dEThr, int ninterstops, + int &nOut, double **VecRGBOut, double **VecLabOut, double *posOut) +{ + ColorConvert CConvertD65(D65, D65); + C_RGB_XYZ_Lab RGBStart = GradStop1.Get_RGB(); + C_RGB_XYZ_Lab RGBEnd = GradStop2.Get_RGB(); + C_RGB_XYZ_Lab LowLab(0, -128, -128); + C_RGB_XYZ_Lab HighLab(100, 127, 127); + C_RGB_XYZ_Lab LowRGB(0, 0, 0); + C_RGB_XYZ_Lab HighRGB(255, 255, 255); + C_RGB_XYZ_Lab LabStart = GradStop1.Get_Lab(); + C_RGB_XYZ_Lab LabEnd = GradStop2.Get_Lab(); + int nsubdiv = 101; + C_RGB_XYZ_Lab dRGB((RGBEnd.Get_x() - RGBStart.Get_x()) / (nsubdiv-1), (RGBEnd.Get_y() - RGBStart.Get_y()) / (nsubdiv-1), + (RGBEnd.Get_z() - RGBStart.Get_z()) / (nsubdiv-1)); + C_RGB_XYZ_Lab dLab((LabEnd.Get_x() - LabStart.Get_x()) / (nsubdiv - 1), (LabEnd.Get_y() -LabStart.Get_y()) / (nsubdiv - 1), + (LabEnd.Get_z() - LabStart.Get_z()) / (nsubdiv - 1)); + + C_RGB_XYZ_Lab *VecLabOut_tmp = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab *VecRGBOut_tmp = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab *VecLabOut_fin = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab *VecRGBOut_fin = new C_RGB_XYZ_Lab[ninterstops]; + C_RGB_XYZ_Lab RGBTmp; + C_RGB_XYZ_Lab LabTmp; + // make a vector of RGB values with 100 subdivisions + // make a matching Lab vector; + + VecRGBOut_tmp[0] = C_RGB_XYZ_Lab(RGBStart); + VecLabOut_tmp[0] = C_RGB_XYZ_Lab(GradStop1.Get_Lab()); + int Stop1Index = 1; + if (!GradStop1.Get_InRGBLimits()) + { + bool retValue = false; + int i_index = 1; + LabTmp.Set(GradStop1.Get_Lab().Get_x() + i_index * dLab.Get_x(), + GradStop1.Get_Lab().Get_y() + i_index * dLab.Get_y(), + GradStop1.Get_Lab().Get_z() + i_index * dLab.Get_z()); + while ((!retValue) & (i_indexLabtoRGB(VecLabOut_tmp[i]); + } + //recalculate dRGB + int SI1 = Stop1Index ; + int SI2 = Stop2Index ; + C_RGB_XYZ_Lab LabStop1(LabStart.Get_x() + SI1 * dLab.Get_x(), + LabStart.Get_y() + SI1 * dLab.Get_y(), LabStart.Get_z() + SI1 * dLab.Get_z()); + C_RGB_XYZ_Lab LabStop2(LabStart.Get_x() + (SI2-1) * dLab.Get_x(), + LabStart.Get_y() + (SI2-1) * dLab.Get_y(), LabStart.Get_z() + (SI2-1) * dLab.Get_z()); + C_RGB_XYZ_Lab RGBStop1 = m_Conv02->LabtoRGB(LabStop1); + C_RGB_XYZ_Lab RGBStop2 = m_Conv02->LabtoRGB(LabStop2); + int nelems = Stop2Index - Stop1Index ; + dRGB = C_RGB_XYZ_Lab((RGBStop2.Get_x() - RGBStop1.Get_x()) / (nelems - 1), (RGBStop2.Get_y() - RGBStop1.Get_y()) / (nelems - 1), + (RGBStop2.Get_z() - RGBStop1.Get_z()) / (nelems - 1)); + int STi = 0; + for (int i = 0; i < nelems; ++i) + { + STi = Stop1Index + i; + VecRGBOut_tmp[STi].Set(RGBStop1.Get_x() + i*dRGB.Get_x(), + RGBStop1.Get_y() + i * dRGB.Get_y(), + RGBStop1.Get_z() + i * dRGB.Get_z()); + VecLabOut_tmp[STi] = CConvertD65.RGBtoLab(VecRGBOut_tmp[STi]); + VecLabOut_tmp[STi].Clamp(LowLab, HighLab); + } + for (int i = Stop2Index; i < nsubdiv; ++i) + { + VecLabOut_tmp[i].Set(VecLabOut_tmp[i - 1].Get_x() + dLab.Get_x(), + VecLabOut_tmp[i - 1].Get_y() + dLab.Get_y(), + VecLabOut_tmp[i - 1].Get_z() + dLab.Get_z()); + VecRGBOut_tmp[i] = m_Conv02->LabtoRGB(VecLabOut_tmp[i]); + } + + int indGrad = 0; + int *pos = new int[ninterstops]; + int i1 = 1; + int j1 = 1; + VecLabOut_fin[indGrad] = VecLabOut_tmp[0]; + VecRGBOut_fin[indGrad] = VecRGBOut_tmp[0]; + pos[indGrad] = 0; + double dE = 0.0; + double dEOld = 0.0; + while (i1 < nsubdiv) + { + dEOld = dE; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[i1], dE); + j1 = i1; + while (dE < dEThr && i1 < nsubdiv && j1 < nsubdiv) + { + j1++; + dEOld = dE; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[j1], dE); + } + if (j1 > i1) + { + j1--; + indGrad++; + VecRGBOut_fin[indGrad] = VecRGBOut_tmp[j1]; + VecLabOut_fin[indGrad] = VecLabOut_tmp[j1]; + pos[indGrad] = j1; + dE = dEOld; + i1 = j1 + 1; + } + else + { + dEOld = dE; + while (dE >= dEThr && i1 =i1; --i) + { + VecRGBOut_tmp[i + 1] = VecRGBOut_tmp[i ]; + VecLabOut_tmp[i + 1] = VecLabOut_tmp[i ]; + } + VecRGBOut_tmp[i1] = RGBTmp; + VecLabOut_tmp[i1] = LabTmp; + CConvertD65.dEcmc(VecLabOut_fin[indGrad], VecLabOut_tmp[i1], dE); + nsubdiv++; + } + indGrad++; + VecRGBOut_fin[indGrad] = VecRGBOut_tmp[j1]; + VecLabOut_fin[indGrad] = VecLabOut_tmp[j1]; + pos[indGrad] = j1; + i1 = j1 + 1; + } + } + nOut = indGrad; + + for (int i = 0; i < nOut; ++i) + { + VecLabOut[i][0] = VecLabOut_fin[i].Get_x(); + VecLabOut[i][1] = VecLabOut_fin[i].Get_y(); + VecLabOut[i][2] = VecLabOut_fin[i].Get_z(); + VecRGBOut[i][0] = VecRGBOut_fin[i].Get_x(); + VecRGBOut[i][1] = VecRGBOut_fin[i].Get_y(); + VecRGBOut[i][2] = VecRGBOut_fin[i].Get_z(); + posOut[i] = pos[i]; + } + //free allocs + if(VecLabOut_tmp != NULL) + { + delete[] VecLabOut_tmp; + VecLabOut_tmp = NULL; + } + if (VecRGBOut_tmp != NULL) + { + delete[] VecRGBOut_tmp; + VecRGBOut_tmp = NULL; + } + if (VecLabOut_fin != NULL) + { + delete[] VecLabOut_fin; + VecLabOut_fin = NULL; + } + if (VecRGBOut_fin != NULL) + { + delete[] VecRGBOut_fin; + VecRGBOut_fin = NULL; + } + if (pos != NULL) + { + delete[] pos; + pos = NULL; + } +} + +void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates* inputcoordinates, ColorSpace colorspace, + VectorXd &Volume, int &GamutRegion, bool same_regions) +{ + size_t nInks = 0; + + C_RGB_XYZ_Lab DataLab; + VectorXd InkOut(m_nInks); + double normFactor = 1; + if (!same_regions) + normFactor = m_colortable->GetNormFactor(); + + if (colorspace ==COLOR_SPACE__RGB) + { + //Convert RGB to Volume, no nee to calculate RGBOut and LabOut + // 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, but will be shown in Relative Colorimetric to the user + + //convert to Lab + ColorConvert CConvertD65(D65, D65); //Destination, source + double *LabIn = new double[3]; + double *RGBOutP = new double[3]; + RGBOutP[0] = inputcoordinates->red; + RGBOutP[1] = inputcoordinates->green; + RGBOutP[2] = inputcoordinates->blue; + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 + LimitLab(LabIn); + + //convert to inks + int GamutRegion; + double *InkOutP = new double[m_nInks]; + if(same_regions) + m_colortable->m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits + else + m_colortable->m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits + + //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_nInks; ++i) + { + InkOutP[i] *= normFactor; + if (InkOutP[i] <= m_NormGamutRegionMaxLim[0]) + { + m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + } + } + InkOut = DoubleToVector(InkOutP, m_nInks); + + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (RGBOutP != NULL) + { + delete[] RGBOutP; + RGBOutP = NULL; + } + } + else if(colorspace ==COLOR_SPACE__LAB) + { + // Basic assumption: Lab data is in relative colorimetric. No Need to convert + + double *LabIn = new double[3]; + LabIn[0] = inputcoordinates->l; //Relative Colorimetric + LabIn[1] = inputcoordinates->a; + LabIn[2] = inputcoordinates->b; + + //convert to Inks + int GamutRegion; + double *InkOutP = new double[m_nInks]; + if(same_regions) + m_colortable->m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval + else + m_colortable->m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval + + for (int i = 0; i < m_nInks; ++i) + { + InkOutP[i] *= normFactor; + if (InkOutP[i] <= m_NormGamutRegionMaxLim[0]) + { + m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + } + } + InkOut = DoubleToVector(InkOutP, m_nInks); + + if (InkOutP != NULL) + { + delete[] InkOutP; + InkOutP = NULL; + } + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + } + else + { + throw std::exception("Unsupported Color Space"); + return; + } + VectorXd NLInkOut(m_nInks); + VectorXd VolumeOut(m_nInks); + double *InkOutL = new double[m_nInks]; + ConvertToNLInks(InkOut, NLInkOut); + LimitInks(NLInkOut, InkOutL); + NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume); + GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP); + NLcmtoPercentage(Volume, Volume); + if (InkOutL != NULL) + { + delete[] InkOutL; + InkOutL = NULL; + } + + return; +} + + +void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* conversionInput, GradientConversionOutput *conversionOutput) +{ + //fill input stops... + + m_nGradStops = conversionInput->n_stops; + int nInks = conversionInput->n_inputliquids; + m_nVolumes = nInks; + if(m_GradStops == NULL) + m_GradStops = new Gradient[m_nGradStops]; + for (int i = 0; i < m_nGradStops; ++i) + m_GradStops[i].SetVolumeSize(nInks); + + InputCoordinates **inputcoordinates = (InputCoordinates**)malloc(sizeof(InputCoordinates*)*m_nGradStops); + for (int i = 0; i < m_nGradStops; ++i) + { + inputcoordinates[i] = (InputCoordinates*)malloc(sizeof(InputCoordinates)); + input_coordinates__init(inputcoordinates[i]); + } + + fillGradientStops(conversionInput); + GradInput2InputCoords(conversionInput, inputcoordinates); + + //Global Parameters of gradient + SetStripWhitepoint(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + bool has_forwarddata = conversionInput->has_forwarddata; + uint8_t *data = conversionInput->forwarddata.data; + m_nProcessRanges = conversionInput->n_processranges; + m_colortable->InitColorTables(has_forwarddata, data, m_nProcessRanges); + SetNumberofInks(m_colortable->GetnA2BnSepOut()); + if(m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nProcessRanges]; + double *tmpVal = m_colortable->GetNormGamutRegionMaxLim(); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = tmpVal[i]; + int n_inputliquids = conversionInput->n_inputliquids; + InputLiquid **inputliquid = conversionInput->inputliquids; + readCalibrationTables(inputliquid, n_inputliquids); + if (m_colortable->GetTableVersion() <= 1) + { + throw std::exception("Color Table Version does not support gradients\0"); + } + //finished reading tables and data + //prepare data to construct the gradient + //gradient is calculated in RGB space, thinned out or expanded based on dE criteria + // returns a vector of volumes and offsets + //gradient stops in different gamut region will use regular transformation + //if all stops in gamut region 0 the color Table will be suited to this gamut region + + //prepare input + //if Color Space = lab, fill rgb and calculate volume + volume region + //if color space = rgb, fill lab and calculate volue + volume region + //if color space = Volume, fill lab and RGB, calculate volume region + + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + if (m_Conv02 == NULL) + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + + // Compare Strip White point to Color Table White Point + //CompareWhitePoints(); + ColorConvert CConvertD65(D65, D65); //Destination, source + if (n_inputliquids != m_nInks) + throw std::exception("Number of available inks does not match ink tables\0"); + + if (m_ProcessRangesMaxP == NULL) + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + m_ProcessRangesMaxP[i] = conversionInput->processranges[i]->maxinkuptake; + } + + VectorXd InkOut(m_nInks); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nInks); + VectorXd Volume(m_nInks); + VectorXd VolumeOut(m_nInks); + //set maxNlPerCM + VectorXd NlperCM(m_nInks); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nInks; ++i) + SetMaxNLperCM(conversionInput->inputliquids[i]->maxnanoliterpercentimeter, i); + //m_nVolumes = m_nB2AnSepOut; + int GamutRegion = 0; + ProcessGradientStops(inputcoordinates); + + //are all stops in the same region? + int maxreg = -10; + int minreg = 10; + for (int i = 0; i < m_nGradStops; ++i) + { + GamutRegion = m_GradStops[i].Get_GamutRegion(); + maxreg = std::max(maxreg, GamutRegion); + minreg = std::min(minreg, GamutRegion); + } + //Choose Gamut Region for Gradient calculation + + bool same_regions = true; + if ((maxreg != minreg) & (maxreg > 0)) + same_regions = false; + double dEThr = 0.8; + //find intermediate points + int ninterstops = 300; + double **VecRGBOut = new double*[ninterstops]; + double **VecLabOut = new double*[ninterstops]; + double *posOut = new double[ninterstops]; + for (int i = 0; i < ninterstops; ++i) + { + VecLabOut[i] = new double[3]; + VecRGBOut[i] = new double[3]; + } + int nOut = 0; + + int nmaxstops = ninterstops * m_nGradStops; + + //Allocate temporary storage for all stops and positions + double **AllRGBOut_tmp = new double*[nmaxstops]; + double **AllLabOut_tmp = new double*[nmaxstops]; + double *AllPos_tmp = new double[nmaxstops]; + for (int i = 0; i < nmaxstops; ++i) + { + AllRGBOut_tmp[i] = new double[3]; + AllLabOut_tmp[i] = new double[3]; + } + AllRGBOut_tmp[0][0] = m_GradStops[0].Get_RGB().Get_x(); + AllRGBOut_tmp[0][1] = m_GradStops[0].Get_RGB().Get_y(); + AllRGBOut_tmp[0][2] = m_GradStops[0].Get_RGB().Get_z(); + AllLabOut_tmp[0][0] = m_GradStops[0].Get_Lab().Get_x(); + AllLabOut_tmp[0][1] = m_GradStops[0].Get_Lab().Get_y(); + AllLabOut_tmp[0][2] = m_GradStops[0].Get_Lab().Get_z(); + AllPos_tmp[0] = m_GradStops[0].Get_Offset(); + int ncountStops = 0; + int nPosStops = 0; + double dOffset = 0; + GradOffset OffsetType = EqSpaced; + + for (int iStop = 0; iStop < m_nGradStops - 1; ++iStop) + { + findStops(m_GradStops[iStop], m_GradStops[iStop + 1], dEThr, ninterstops, nOut, VecRGBOut, VecLabOut, posOut); + switch (OffsetType) + { + case EqSpaced: + if (iStop == m_nGradStops - 2) + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset())*GradientEndThr / (nOut - 1); + else + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset()) / (nOut - 1); + for (int jPos = 1; jPos < nOut; ++jPos) + { + nPosStops++; + AllPos_tmp[nPosStops] = m_GradStops[iStop].Get_Offset() + dOffset * jPos; + } + break; + case dESpaced: + if (iStop == m_nGradStops - 2) + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset())*GradientEndThr / posOut[nOut - 1]; + else + dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset()) / posOut[nOut - 1]; + for (int jPos = 0; jPos < nOut; ++jPos) + { + nPosStops++; + AllPos_tmp[nPosStops] = m_GradStops[iStop].Get_Offset() + dOffset * posOut[jPos]; + } + break; + } + //store the stops in temporary vector + for (int iCount = 1; iCount < nOut; ++iCount) + { + ncountStops++; + for (int jCS = 0; jCS < 3; ++jCS) + { + AllRGBOut_tmp[ncountStops][jCS] = VecRGBOut[iCount][jCS]; + AllLabOut_tmp[ncountStops][jCS] = VecLabOut[iCount][jCS]; + } + } + } + + if (VecRGBOut != NULL) + { + for (int i = 0; i < ninterstops; ++i) + delete[]VecRGBOut[i]; + delete[]VecRGBOut; + } + if (VecLabOut != NULL) + { + for (int i = 0; i < ninterstops; ++i) + delete[]VecLabOut[i]; + delete[]VecLabOut; + VecLabOut = NULL; + } + if (posOut != NULL) + { + delete[]posOut; + posOut = NULL; + } + + //Store Gradient intermediate data in Input Coordinates type structure. + //Simplify calculations, we only need the ink values, input values are in RGB color space + // Use table according to Gamut Regions, all stops in region 0, use 100%table otherwise use regular table, decrease dyeing speed. + + int nTotalStops = ncountStops; + InputCoordinates **SubStops = (InputCoordinates**)malloc(sizeof(InputCoordinates*)*nTotalStops); + + //Calculate and store + for (int iTStops = 0; iTStops < nTotalStops; ++iTStops) + { + SubStops[iTStops] = (InputCoordinates*)malloc(sizeof(InputCoordinates)); + input_coordinates__init(SubStops[iTStops]); + SubStops[iTStops]->l = AllLabOut_tmp[iTStops][0]; + SubStops[iTStops]->a = AllLabOut_tmp[iTStops][1]; + SubStops[iTStops]->b = AllLabOut_tmp[iTStops][2]; + SubStops[iTStops]->red = (int)round(AllRGBOut_tmp[iTStops][0]); + SubStops[iTStops]->green = (int)round(AllRGBOut_tmp[iTStops][1]); + SubStops[iTStops]->blue = (int)round(AllRGBOut_tmp[iTStops][2]); + } + + GradientOutputStop** outputStops = (GradientOutputStop**)malloc(sizeof(GradientOutputStop*) * nTotalStops); + conversionOutput->stops = outputStops; + conversionOutput->n_stops = nTotalStops; + + ColorSpace SubStopsCS = COLOR_SPACE__LAB; + //double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + VectorXd VolumeStop(m_nInks); + MatrixXd MatVolume(ncountStops, m_nInks); + for (int iS = 0; iS < ncountStops; ++iS) + { + GradientOutputStop *stop = (GradientOutputStop*)malloc(sizeof(GradientOutputStop)); + gradient_output_stop__init(stop); + ConvertGradStoptoVolume(SubStops[iS], SubStopsCS, + VolumeStop, GamutRegion, same_regions); + //start filling Output + fillStop(stop, VolumeStop, GamutRegion, AllPos_tmp[iS]); + MatVolume.row(iS) = VolumeStop; + outputStops[iS] = stop; + } + //Smooth Volumes + VectorXd VIn(ncountStops); + VectorXd VOut(ncountStops); + int FilterWidth = 7; + for (int iSep = 0; iSep < m_nInks; ++iSep) + { + for (int jStop = 0; jStop < ncountStops; ++jStop) + VIn(jStop) = MatVolume(jStop, iSep); + SmoothCurveData(VIn, VOut, FilterWidth); + for (int jS = 0; jS < ncountStops; ++jS) + outputStops[jS]->outputliquids[iSep]->volume = VOut(jS); + } + //Temp Output + for (int i = 0; i < ncountStops; ++i) + { + fprintf(stdout, "%d\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%d\t%d\t%d\n", i, + outputStops[i]->offset, outputStops[i]->outputliquids[0]->volume, + outputStops[i]->outputliquids[1]->volume, outputStops[i]->outputliquids[2]->volume, outputStops[i]->outputliquids[3]->volume, + SubStops[i]->l, SubStops[i]->a, SubStops[i]->b, SubStops[i]->red, SubStops[i]->green, SubStops[i]->blue); + } + //release memory + if (AllLabOut_tmp != NULL) + { + for (int i = 0; i < nmaxstops; ++i) + delete[] AllLabOut_tmp[i]; + delete[] AllLabOut_tmp; + AllLabOut_tmp = NULL; + } + if (AllRGBOut_tmp != NULL) + { + for (int i = 0; i < nmaxstops; ++i) + delete[] AllRGBOut_tmp[i]; + delete[] AllRGBOut_tmp; + AllRGBOut_tmp = NULL; + } + if (AllPos_tmp != NULL) + { + delete[] AllPos_tmp; + AllPos_tmp = NULL; + } + + + for (int i = 0; i < m_nGradStops; ++i) + input_coordinates__free_unpacked(inputcoordinates[i], NULL); + free(inputcoordinates); + inputcoordinates = NULL; + for (int i = 0; i < nTotalStops; ++i) + input_coordinates__free_unpacked(SubStops[i], NULL); + free(SubStops); + SubStops = NULL; + +} + + + + +void Tango::ColorLib::ColorConverter::fillStop(GradientOutputStop *&stop, VectorXd Volume, int GamutRegion, double Position) +{ + OutputLiquid** outputLiquids = (OutputLiquid**)malloc(sizeof(OutputLiquid*) * m_nVolumes); + for (int i = 0; i < m_nVolumes; ++i) + { + outputLiquids[i] = (OutputLiquid*)malloc(sizeof(OutputLiquid)); + output_liquid__init(outputLiquids[i]); + switch (m_CalibCurves[i].getInkName()) + { + case LIQUID_TYPE__Cyan: + case LIQUID_TYPE__Magenta: + case LIQUID_TYPE__Yellow: + case LIQUID_TYPE__Black: + { + outputLiquids[i]->has_volume = true; + outputLiquids[i]->has_liquidtype = true; + outputLiquids[i]->liquidtype = (LiquidType)(m_CalibCurves[i].getInkName()); + outputLiquids[i]->volume = Volume(i); + break; + } + default: + throw std::exception("could not fill all volumes"); + } + } + stop->outputliquids = outputLiquids; + stop->n_outputliquids = m_nVolumes; + stop->has_processparameterstableindex = true; + stop->processparameterstableindex = GamutRegion; + stop->has_offset = true; + stop->offset = Position; +} + +void Tango::ColorLib::ColorConverter::GradInput2InputCoords(GradientConversionInput *conversionInput, InputCoordinates **inputcoordinates) +{ + for (size_t i = 0; i < conversionInput->n_stops; i++) + { + switch (conversionInput->stops[i]->colorspace) + { + case COLOR_SPACE__RGB: //Case RGB + inputcoordinates[i]->red = conversionInput->stops[i]->red; + inputcoordinates[i]->green = conversionInput->stops[i]->green; + inputcoordinates[i]->blue = conversionInput->stops[i]->blue; + inputcoordinates[i]->has_red = true; + inputcoordinates[i]->has_green = true; + inputcoordinates[i]->has_blue = true; + break; + case COLOR_SPACE__LAB: //Case LAB + inputcoordinates[i]->l = conversionInput->stops[i]->l; + inputcoordinates[i]->a = conversionInput->stops[i]->a; + inputcoordinates[i]->b = conversionInput->stops[i]->b; + inputcoordinates[i]->has_l = true; + inputcoordinates[i]->has_a = true; + inputcoordinates[i]->has_b = true; + break; + case COLOR_SPACE__Volume: //Case Volume + int size= (int)conversionInput->stops[i]->n_liquidvolumes; + InputLiquid** InputLiquidsIC = (InputLiquid**)malloc(sizeof(InputLiquid*) *size); + for (int j = 0; j < size; j++) + { + InputLiquidsIC[j] = (InputLiquid*)malloc(sizeof(InputLiquid)); + input_liquid__init(InputLiquidsIC[j]); + } + for (size_t j= 0; j< (int)conversionInput->stops[i]->n_liquidvolumes; j++) + { + LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j]; + switch (liquidVolume->liquidtype) + { + case LIQUID_TYPE__Cyan: +// inputcoordinates[i]->inputliquids[0]->volume = liquidVolume->volume; + InputLiquidsIC[0]->volume = liquidVolume->volume; + InputLiquidsIC[0]->liquidtype = LIQUID_TYPE__Cyan; + break; + case LIQUID_TYPE__Magenta: + InputLiquidsIC[1]->volume = liquidVolume->volume; + InputLiquidsIC[1]->liquidtype = LIQUID_TYPE__Magenta; + break; + case LIQUID_TYPE__Yellow: + InputLiquidsIC[2]->volume = liquidVolume->volume; + InputLiquidsIC[2]->liquidtype = LIQUID_TYPE__Yellow; + break; + case LIQUID_TYPE__Black: + InputLiquidsIC[3]->volume = liquidVolume->volume; + InputLiquidsIC[3]->liquidtype = LIQUID_TYPE__Black; + break; + } + + } + inputcoordinates[i]->inputliquids = InputLiquidsIC; + inputcoordinates[i]->n_inputliquids = size; + } + } +} + +void Tango::ColorLib::ColorConverter::LimitInks(VectorXd inInks, double *BoundedInks) +{ + //convert Ink % to [nl/cm] + //Bound Ink + for (int i = 0; i < m_nInks; ++i) + BoundedInks[i] = std::min(inInks(i)*m_maxNlPerCM(i)/100.0, m_ProcessRangesMaxP[m_nProcessRanges - 1]); +} + +void Tango::ColorLib::ColorConverter::NLcmtoPercentage(VectorXd InVolume, VectorXd &OutVolume) +{ + for (int i = 0; i < m_nInks; ++i) + OutVolume(i) =100* InVolume(i) / m_maxNlPerCM(i); +} + +int Tango::ColorLib::ColorConverter::GetGamutRegion(VectorXd Volume, double *GamutLimits) +{ + double TotalVolume = 0.0; + int GamutRegion = 0; + for (int i = 0; i < m_nInks; ++i) + TotalVolume += Volume(i); + for (int i=0; i< m_colortable->GetnGamutRegions(); ++i) + { + if (TotalVolume > GamutLimits[i]) + GamutRegion++; + } + return(GamutRegion); +} + +void Tango::ColorLib::ColorConverter::SmoothCurveData(VectorXd VIn, VectorXd &VOut, int FilterWidth) +{ + int Vlength = VIn.size(); + VectorXd tmpV(Vlength); + int NumIter = (int)(std::max(FilterWidth, 3) - 2); + //Smooth the data with repeated applications of a[1 1 1] filter + for (int i = 0; i < NumIter; ++i) + { + for (int j=0; j< Vlength; ++j) + tmpV(j) = VIn(j); + for (int k=1; k< Vlength-1; ++k) + VIn(k) = (tmpV(k-1) + tmpV(k) + tmpV(k+1)) / 3; + } + for (int j = 0; j < Vlength; ++j) + VOut(j) = VIn(j); +} + +void Tango::ColorLib::ColorConverter::ProcessGradientStops(InputCoordinates **inputcoordinates) +{ + VectorXd Volume(m_nInks); + VectorXd RGBOut(m_nInks); + VectorXd LabOut(m_nInks); + VectorXd InkOut(m_nInks); + VectorXd NLInkOut(m_nInks); + double * InkOutL = new double[m_nInks]; + double * LabOutV = new double[3]; + double * LabOutFinal = new double[3]; + + ColorConvert CConvertD65(D65, D65); + + bool InGamut = true; + int GamutRegion = 0; + for (int i = 0; i < m_nGradStops; ++i) + { + if (m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__Volume || m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__Catalog) + { //Convert volume to Lab + //Convert lab to rgb + ConvertVolumeToRGBDisplay(inputcoordinates[i], m_nProcessRanges, m_GradStops[i].Get_ColorSpace(), Volume, RGBOut, LabOut, GamutRegion); + //RGB has to be calculate from Absolute Colorimetric, in the above function it is calculated from relative. + //Recalculate RGB and do not clip values below zero or above 255 + C_RGB_XYZ_Lab Lab(LabOut); + C_RGB_XYZ_Lab RGB(RGBOut); + RGB = CConvertD65.LabtoRGBNoClip(Lab); // RGB is not clipped and was derived from absolute colorimetric Lab Value + RGBOut = VectorXd(RGB.Get_x(), RGB.Get_y(), RGB.Get_z()); + //store data + m_GradStops[i].Set_Lab(LabOut); + m_GradStops[i].Set_RGB(RGBOut); + m_GradStops[i].Set_GamutRegion( GamutRegion); + bool retValue = CheckLabInRGBGamut(LabOut); + m_GradStops[i].SetInRGBLimits(retValue); + m_GradStops[i].SetInGamut (true); + } + else + { + ConvertColorToLinearInks(inputcoordinates[i], m_GradStops[i].Get_ColorSpace(), 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 + C_RGB_XYZ_Lab Lab(LabOut); + C_RGB_XYZ_Lab RGB(RGBOut); + if (m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__RGB) + { + RGB = CConvertD65.LabtoRGBNoClip(Lab); // RGB is not clipped and was derived from absolute colorimetric Lab Value + RGBOut = VectorXd(RGB.Get_x(), RGB.Get_y(), RGB.Get_z()); + } + ConvertToNLInks(InkOut, NLInkOut); + LimitInks(NLInkOut, InkOutL); + NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume); + GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP); + NLcmtoPercentage(Volume, Volume); + //fill data + //fill volume + //allocate m_GradStops[i].Volume + for (int j = 0; j < m_nInks; ++j) + m_GradStops[i].SetVolumeValue(Volume[j], j); + m_GradStops[i].Set_GamutRegion(GamutRegion); + m_GradStops[i].SetInGamut(InGamut); + //LabOut and RGBOut might be different if the input was out of gamut + m_GradStops[i].Set_Lab(LabOut); + m_GradStops[i].Set_RGB(RGBOut); + } + //Convert Lab Values to Relative Colorimetric. These values will be used in the Gradient Volume calculation. + VectorToDouble(LabOut, LabOutV); + /* if (m_AdaptWP) + { + CConvertD65.ChangeWP(LabOutV, LabOutV, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables + } + */ + //double *LabInFinal2 = DBG_NEW double[3]; + // CConvertD65.ChangeWP(LabOutV, LabOutFinal, m_WP, m_whitepointXYZ_CT); //LabInFinal is in Relative Colorimetric Space + CConvertD65.ChangeWP(LabOutV, LabOutFinal, m_WP, m_whitepointXYZ_Strip); //LabInFinal is in Relative Colorimetric Space + C_RGB_XYZ_Lab LabOut1(LabOutFinal[0], LabOutFinal[1], LabOutFinal[2]); + + m_GradStops[i].Set_Lab(LabOut1); + bool retValue = CheckLabInRGBGamut( DoubleToVector(LabOutFinal,3)); + m_GradStops[i].SetInRGBLimits(retValue); + } + //free vectors + if (LabOutV != NULL) + { + delete[] LabOutV; + LabOutV = NULL; + } + if (LabOutFinal != NULL) + { + delete[] LabOutFinal; + LabOutFinal = NULL; + } + if (InkOutL != NULL) + { + delete[] InkOutL; + InkOutL = NULL; + } +} + +bool Tango::ColorLib::ColorConverter::CheckLabInRGBGamut(VectorXd Lab) +{ + bool retVal = false; + C_RGB_XYZ_Lab DataLab; + DataLab.Set(Lab); + retVal = CheckLabInRGBGamut(DataLab); + return(retVal); +} + +bool Tango::ColorLib::ColorConverter::CheckLabInRGBGamut( C_RGB_XYZ_Lab Lab) +{ + bool retVal = false; + //ColorConvert ColConv(D65, D65); + C_RGB_XYZ_Lab DataRGB1; + C_RGB_XYZ_Lab DataLab1; + //DataRGB1 limited to [0,255] + DataRGB1 = m_Conv02->LabtoRGB(Lab); + DataLab1 = m_Conv02->RGBtoLab(DataRGB1); + double dE = 0; + m_Conv02->dE76(DataLab1, Lab, dE); + if (dE < 0.01) + retVal = true; + return(retVal); +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.cpp new file mode 100644 index 000000000..b70acbda1 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.cpp @@ -0,0 +1,68 @@ +#include +#include "Exports.h" +#include "ColorConverter.h" +#include "ColorCalibrator.h" +//#include +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 +#pragma once + +#define EXPORT_API __declspec(dllexport) + +using namespace std; +using namespace Tango::ColorLib; + +extern "C" EXPORT_API size_t __cdecl Convert(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +{ + ColorConverter converter; + return converter.Convert(input_buffer, input_buffer_size, 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.P_IsInGamut(input_buffer, input_buffer_size, output_buffer); +} + +extern "C" EXPORT_API size_t __cdecl GetLiquidFactor(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +{ + ColorCalibrator calibrator; + return calibrator.GetLiquidFactor(input_buffer, input_buffer_size, output_buffer); +} + +extern "C" EXPORT_API size_t __cdecl GenerateGradient(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +{ + ColorConverter converter; + return converter.GenerateGradient(input_buffer, input_buffer_size, output_buffer); +} + +extern "C" EXPORT_API size_t __cdecl GetLinearizationMeasurements(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +{ + ColorCalibrator calibrator; + return calibrator.GetLinearizationMeasurements(input_buffer, input_buffer_size, output_buffer); +} + +extern "C" EXPORT_API size_t __cdecl GetRecommendedProcessParameters(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +{ + ColorConverter converter; + return converter.GetRecommendedProcessParameters(input_buffer, input_buffer_size, output_buffer); +} + +extern "C" EXPORT_API size_t __cdecl CheckOutOfGamut(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer) +{ + ColorConverter converter; + return converter.CheckOutOfGamut(input_buffer, input_buffer_size, output_buffer); +} + + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.h new file mode 100644 index 000000000..3f386f303 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Exports.h @@ -0,0 +1,6 @@ +#include +#include + +#define EXPORT_API __declspec(dllexport) + +extern "C" EXPORT_API size_t Convert(uint8_t* input_buffer, size_t input_buffer_size, uint8_t*& output_buffer); diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.cpp new file mode 100644 index 000000000..076064f66 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.cpp @@ -0,0 +1,217 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 "ForwardModel.h" +#include +#include +#include "NumConversions.h" +#include "C_RGB_XYZ_Lab.h" +#include "ColorConvert.h" + +using namespace std; + +ForwardModel::ForwardModel() : + m_nChannels(0), m_nPCSChannels(0), m_whiteptLab(NULL), m_prec(0), + m_nEntries(0), m_CoeffList(NULL), m_expList(NULL), m_Vandermonde(NULL) +{ + +} + +ForwardModel::~ForwardModel() +{ + if (m_CoeffList != NULL) + { + for (int i=0; i< m_nPCSChannels; ++i) + delete[] m_CoeffList[i]; + delete[] m_CoeffList; + m_CoeffList = NULL; + } + + if (m_expList != NULL) + { + for (int i = 0; i < m_nChannels; ++i) + delete[] m_expList[i]; + delete[] m_expList; + m_expList = NULL; + } + + if (m_Vandermonde != NULL) + { + delete[] m_Vandermonde; + m_Vandermonde = NULL; + } + + if (m_whiteptLab != NULL) + { + delete[] m_whiteptLab; + m_whiteptLab = NULL; + } + +} + +void ForwardModel::InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize) +{ + // 0 - 3 prec + //4 - 7 reserved, must be 0 + // 8 number of input channels, uint8 + // 9 number of output channels, uint8 + // 10 - 11 number of coefficients + // 12 - 13 LH Limit + // 14 - 15 RH Limit + // 16 - 19 reserved for padding + // 20 - n Model data data + exponent + + if (colorTransformFileSize < 32) + { + throw std::exception("Init Forward Model, invalid size"); + } + + // Check for signature + unsigned char *buffer = colorTransformBuffer; + if (buffer == NULL) + { + throw std::exception("Memory Error, ForwardModel::InitData"); + } + NumConversions Conv; + //Table precision + int bytesread = 0; + int tmpB = Conv.ByteToInt(buffer, 0); + bytesread += 4; + + char FMType[sizeof(tmpB) + 1]; + Conv.getchar(tmpB, *FMType); + //char *luttype = DBG_NEW char[n + 1]; +// strcpy(Curvetype, tmpC); + int FMPrecision; + if (strncmp(FMType, "prc1", sizeof(tmpB)) == 0) + FMPrecision = 1; + else if (strncmp(FMType, "prc2", sizeof(tmpB)) == 0) + FMPrecision = 2; + else + { + throw std::exception("Wrong precision in Forward Model"); + return; + } + + // Skip past reserved padding bytes + bytesread += 4; + + uint8_t num_channels = buffer[bytesread]; + Set_nChannels((int)num_channels); //Numer of channels + bytesread += 1; + + uint8_t num_PCSchannels = buffer[bytesread]; + Set_nPCSChannels((int)num_PCSchannels); //Numer of PCS channels + bytesread += 1; + + unsigned short nEntries = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + Set_nEntries((int)nEntries); + double Interval = (double)(Conv.ByteToShort(buffer, bytesread)); + bytesread += 2; + double RHLim = (double)(Conv.ByteToShort(buffer, bytesread)); + bytesread += 2; + double LHLim = RHLim - Interval; + double Gain = RHLim - LHLim; + double Offset = LHLim; + + if (m_CoeffList == NULL) + { + m_CoeffList = new double*[m_nEntries]; + for (int i = 0; i < m_nEntries; ++i) + m_CoeffList[i] = new double[m_nPCSChannels]; + } + if (m_expList == NULL) + { + m_expList = new double*[m_nEntries]; + for (int i = 0; i < m_nEntries; ++i) + m_expList[i] = new double[m_nChannels]; + } + + if (m_Vandermonde == NULL) + { + m_Vandermonde = new double[m_nEntries]; + for (int i = 0; i < m_nEntries; ++i) + m_Vandermonde[i] = 1.0; + } + + //read Coefficients Tag + if (m_prec == 1) + { + for (int i = 0; i < m_nChannels; ++i) + { + for (int j = 0; j < m_nEntries; ++j) + { + m_CoeffList[j][i] = (double)(buffer[bytesread]); + bytesread += 1; + } + } + } + else + { + for (int i = 0; i < m_nPCSChannels; ++i) + { + for (int j = 0; j < nEntries; ++j) + { + m_CoeffList[j][i] = (double)(Conv.ByteToShort(buffer, bytesread)); + bytesread += 2; + + m_CoeffList[j][i] = Gain * (double(m_CoeffList[j][i]) / 65535) + Offset; + } + } + } + //Read Exponents List + for (int i = 0; i < m_nChannels; ++i) + { + for (int j = 0; j < m_nEntries; ++j) + { + m_expList[j][i] = (double)(buffer[bytesread]); + bytesread += 1; + } + } +} + +void ForwardModel::CalcFM(double *InInk, double *OutLab) +{ + int i, k; + //Calculate Vandermonde Vector [1 x number of entries] + for ( i = 0; i < m_nEntries; ++i) + { + m_Vandermonde[i] = 1.0; + for ( k = 0; k < m_nChannels; ++k) + m_Vandermonde[i] *= std::pow( InInk[k], m_expList[i][k]); + } + + //calculate Lab Vandermodex Coeefficients + FreeTerm + for (i = 0; i < m_nPCSChannels; ++i) + { + OutLab[i] = m_whiteptLab[i]; + for (k = 0; k < m_nEntries; ++k) + OutLab[i] += m_Vandermonde[k] * m_CoeffList[k][i] ; + } +} + +void ForwardModel::SetFreeTerm(C_RGB_XYZ_Lab whiteptLab) +{ + if (m_whiteptLab == NULL) + m_whiteptLab = new double[m_nPCSChannels]; + + m_whiteptLab[0] = whiteptLab.Get_x(); + m_whiteptLab[1] = whiteptLab.Get_y(); + m_whiteptLab[2] = whiteptLab.Get_z(); +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.h new file mode 100644 index 000000000..5a310548f --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ForwardModel.h @@ -0,0 +1,32 @@ +#ifndef _ForwardModel_H_ +#define _ForwardModel_H_ + +#include +#include "C_RGB_XYZ_Lab.h" +class ForwardModel { +public: + ForwardModel(); + ~ForwardModel(); + int Get_nChannels() { return(m_nChannels); }; + int Get_nPCSChannels() { return(m_nPCSChannels); }; + int Get_nEntries() { return(m_nEntries); }; + void InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize); + void CalcFM(double *InInk, double *OutLab); + void SetFreeTerm(C_RGB_XYZ_Lab whiteptLab); + +private: + int m_prec; + int m_nChannels; + int m_nPCSChannels; + int m_nEntries; + double *m_whiteptLab; + void Set_nChannels(int nChannels) { m_nChannels = nChannels; }; + void Set_nPCSChannels(int nPCSChannels) { m_nPCSChannels = nPCSChannels; }; + void Set_nEntries(int nEntries) { m_nEntries = nEntries; }; + + double **m_CoeffList; + double **m_expList; + double *m_Vandermonde; +}; + +#endif diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.c new file mode 100644 index 000000000..981988d99 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.c @@ -0,0 +1,105 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationData.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "CalibrationData.pb-c.h" +void calibration_data__init + (CalibrationData *message) +{ + static const CalibrationData init_value = CALIBRATION_DATA__INIT; + *message = init_value; +} +size_t calibration_data__get_packed_size + (const CalibrationData *message) +{ + assert(message->base.descriptor == &calibration_data__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t calibration_data__pack + (const CalibrationData *message, + uint8_t *out) +{ + assert(message->base.descriptor == &calibration_data__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t calibration_data__pack_to_buffer + (const CalibrationData *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &calibration_data__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CalibrationData * + calibration_data__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CalibrationData *) + protobuf_c_message_unpack (&calibration_data__descriptor, + allocator, len, data); +} +void calibration_data__free_unpacked + (CalibrationData *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &calibration_data__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor calibration_data__field_descriptors[2] = +{ + { + "LiquidType", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(CalibrationData, has_liquidtype), + offsetof(CalibrationData, liquidtype), + &liquid_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "CalibrationPoints", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(CalibrationData, n_calibrationpoints), + offsetof(CalibrationData, calibrationpoints), + &calibration_point__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned calibration_data__field_indices_by_name[] = { + 1, /* field[1] = CalibrationPoints */ + 0, /* field[0] = LiquidType */ +}; +static const ProtobufCIntRange calibration_data__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor calibration_data__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CalibrationData", + "CalibrationData", + "CalibrationData", + "", + sizeof(CalibrationData), + 2, + calibration_data__field_descriptors, + calibration_data__field_indices_by_name, + 1, calibration_data__number_ranges, + (ProtobufCMessageInit) calibration_data__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.h new file mode 100644 index 000000000..ccecc327e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationData.pb-c.h @@ -0,0 +1,76 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationData.proto */ + +#ifndef PROTOBUF_C_CalibrationData_2eproto__INCLUDED +#define PROTOBUF_C_CalibrationData_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "CalibrationPoint.pb-c.h" +#include "LiquidType.pb-c.h" + +typedef struct _CalibrationData CalibrationData; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _CalibrationData +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidtype; + LiquidType liquidtype; + size_t n_calibrationpoints; + CalibrationPoint **calibrationpoints; +}; +#define CALIBRATION_DATA__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&calibration_data__descriptor) \ + , 0, LIQUID_TYPE__Cyan, 0,NULL } + + +/* CalibrationData methods */ +void calibration_data__init + (CalibrationData *message); +size_t calibration_data__get_packed_size + (const CalibrationData *message); +size_t calibration_data__pack + (const CalibrationData *message, + uint8_t *out); +size_t calibration_data__pack_to_buffer + (const CalibrationData *message, + ProtobufCBuffer *buffer); +CalibrationData * + calibration_data__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void calibration_data__free_unpacked + (CalibrationData *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CalibrationData_Closure) + (const CalibrationData *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor calibration_data__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_CalibrationData_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.c new file mode 100644 index 000000000..1cf8e00a7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.c @@ -0,0 +1,145 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationInput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "CalibrationInput.pb-c.h" +void calibration_input__init + (CalibrationInput *message) +{ + static const CalibrationInput init_value = CALIBRATION_INPUT__INIT; + *message = init_value; +} +size_t calibration_input__get_packed_size + (const CalibrationInput *message) +{ + assert(message->base.descriptor == &calibration_input__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t calibration_input__pack + (const CalibrationInput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &calibration_input__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t calibration_input__pack_to_buffer + (const CalibrationInput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &calibration_input__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CalibrationInput * + calibration_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CalibrationInput *) + protobuf_c_message_unpack (&calibration_input__descriptor, + allocator, len, data); +} +void calibration_input__free_unpacked + (CalibrationInput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &calibration_input__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor calibration_input__field_descriptors[5] = +{ + { + "LiquidType", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(CalibrationInput, has_liquidtype), + offsetof(CalibrationInput, liquidtype), + &liquid_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TargetL", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationInput, has_targetl), + offsetof(CalibrationInput, targetl), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TargetA", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationInput, has_targeta), + offsetof(CalibrationInput, targeta), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TargetB", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationInput, has_targetb), + offsetof(CalibrationInput, targetb), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Measurements", + 20, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(CalibrationInput, n_measurements), + offsetof(CalibrationInput, measurements), + &calibration_measurement__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned calibration_input__field_indices_by_name[] = { + 0, /* field[0] = LiquidType */ + 4, /* field[4] = Measurements */ + 2, /* field[2] = TargetA */ + 3, /* field[3] = TargetB */ + 1, /* field[1] = TargetL */ +}; +static const ProtobufCIntRange calibration_input__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 20, 4 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor calibration_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CalibrationInput", + "CalibrationInput", + "CalibrationInput", + "", + sizeof(CalibrationInput), + 5, + calibration_input__field_descriptors, + calibration_input__field_indices_by_name, + 2, calibration_input__number_ranges, + (ProtobufCMessageInit) calibration_input__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.h new file mode 100644 index 000000000..be42ed59b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationInput.pb-c.h @@ -0,0 +1,82 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationInput.proto */ + +#ifndef PROTOBUF_C_CalibrationInput_2eproto__INCLUDED +#define PROTOBUF_C_CalibrationInput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "CalibrationMeasurement.pb-c.h" +#include "LiquidType.pb-c.h" + +typedef struct _CalibrationInput CalibrationInput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _CalibrationInput +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidtype; + LiquidType liquidtype; + protobuf_c_boolean has_targetl; + double targetl; + protobuf_c_boolean has_targeta; + double targeta; + protobuf_c_boolean has_targetb; + double targetb; + size_t n_measurements; + CalibrationMeasurement **measurements; +}; +#define CALIBRATION_INPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&calibration_input__descriptor) \ + , 0, LIQUID_TYPE__Cyan, 0, 0, 0, 0, 0, 0, 0,NULL } + + +/* CalibrationInput methods */ +void calibration_input__init + (CalibrationInput *message); +size_t calibration_input__get_packed_size + (const CalibrationInput *message); +size_t calibration_input__pack + (const CalibrationInput *message, + uint8_t *out); +size_t calibration_input__pack_to_buffer + (const CalibrationInput *message, + ProtobufCBuffer *buffer); +CalibrationInput * + calibration_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void calibration_input__free_unpacked + (CalibrationInput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CalibrationInput_Closure) + (const CalibrationInput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor calibration_input__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_CalibrationInput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.c new file mode 100644 index 000000000..24d499c59 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.c @@ -0,0 +1,131 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationMeasurement.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "CalibrationMeasurement.pb-c.h" +void calibration_measurement__init + (CalibrationMeasurement *message) +{ + static const CalibrationMeasurement init_value = CALIBRATION_MEASUREMENT__INIT; + *message = init_value; +} +size_t calibration_measurement__get_packed_size + (const CalibrationMeasurement *message) +{ + assert(message->base.descriptor == &calibration_measurement__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t calibration_measurement__pack + (const CalibrationMeasurement *message, + uint8_t *out) +{ + assert(message->base.descriptor == &calibration_measurement__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t calibration_measurement__pack_to_buffer + (const CalibrationMeasurement *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &calibration_measurement__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CalibrationMeasurement * + calibration_measurement__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CalibrationMeasurement *) + protobuf_c_message_unpack (&calibration_measurement__descriptor, + allocator, len, data); +} +void calibration_measurement__free_unpacked + (CalibrationMeasurement *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &calibration_measurement__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor calibration_measurement__field_descriptors[4] = +{ + { + "NanoliterPerCentimeter", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationMeasurement, has_nanoliterpercentimeter), + offsetof(CalibrationMeasurement, nanoliterpercentimeter), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "L", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationMeasurement, has_l), + offsetof(CalibrationMeasurement, l), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "A", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationMeasurement, has_a), + offsetof(CalibrationMeasurement, a), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "B", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationMeasurement, has_b), + offsetof(CalibrationMeasurement, b), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned calibration_measurement__field_indices_by_name[] = { + 2, /* field[2] = A */ + 3, /* field[3] = B */ + 1, /* field[1] = L */ + 0, /* field[0] = NanoliterPerCentimeter */ +}; +static const ProtobufCIntRange calibration_measurement__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor calibration_measurement__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CalibrationMeasurement", + "CalibrationMeasurement", + "CalibrationMeasurement", + "", + sizeof(CalibrationMeasurement), + 4, + calibration_measurement__field_descriptors, + calibration_measurement__field_indices_by_name, + 1, calibration_measurement__number_ranges, + (ProtobufCMessageInit) calibration_measurement__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.h new file mode 100644 index 000000000..5c7c58a64 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationMeasurement.pb-c.h @@ -0,0 +1,78 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationMeasurement.proto */ + +#ifndef PROTOBUF_C_CalibrationMeasurement_2eproto__INCLUDED +#define PROTOBUF_C_CalibrationMeasurement_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _CalibrationMeasurement CalibrationMeasurement; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _CalibrationMeasurement +{ + ProtobufCMessage base; + protobuf_c_boolean has_nanoliterpercentimeter; + double nanoliterpercentimeter; + protobuf_c_boolean has_l; + double l; + protobuf_c_boolean has_a; + double a; + protobuf_c_boolean has_b; + double b; +}; +#define CALIBRATION_MEASUREMENT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&calibration_measurement__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, 0 } + + +/* CalibrationMeasurement methods */ +void calibration_measurement__init + (CalibrationMeasurement *message); +size_t calibration_measurement__get_packed_size + (const CalibrationMeasurement *message); +size_t calibration_measurement__pack + (const CalibrationMeasurement *message, + uint8_t *out); +size_t calibration_measurement__pack_to_buffer + (const CalibrationMeasurement *message, + ProtobufCBuffer *buffer); +CalibrationMeasurement * + calibration_measurement__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void calibration_measurement__free_unpacked + (CalibrationMeasurement *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CalibrationMeasurement_Closure) + (const CalibrationMeasurement *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor calibration_measurement__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_CalibrationMeasurement_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.c new file mode 100644 index 000000000..dca0c112b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.c @@ -0,0 +1,119 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationOutput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "CalibrationOutput.pb-c.h" +void calibration_output__init + (CalibrationOutput *message) +{ + static const CalibrationOutput init_value = CALIBRATION_OUTPUT__INIT; + *message = init_value; +} +size_t calibration_output__get_packed_size + (const CalibrationOutput *message) +{ + assert(message->base.descriptor == &calibration_output__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t calibration_output__pack + (const CalibrationOutput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &calibration_output__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t calibration_output__pack_to_buffer + (const CalibrationOutput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &calibration_output__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CalibrationOutput * + calibration_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CalibrationOutput *) + protobuf_c_message_unpack (&calibration_output__descriptor, + allocator, len, data); +} +void calibration_output__free_unpacked + (CalibrationOutput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &calibration_output__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor calibration_output__field_descriptors[3] = +{ + { + "LiquidFactor", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationOutput, has_liquidfactor), + offsetof(CalibrationOutput, liquidfactor), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "HasError", + 20, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(CalibrationOutput, has_haserror), + offsetof(CalibrationOutput, haserror), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ErrorMessage", + 21, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(CalibrationOutput, errormessage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned calibration_output__field_indices_by_name[] = { + 2, /* field[2] = ErrorMessage */ + 1, /* field[1] = HasError */ + 0, /* field[0] = LiquidFactor */ +}; +static const ProtobufCIntRange calibration_output__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 20, 1 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor calibration_output__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CalibrationOutput", + "CalibrationOutput", + "CalibrationOutput", + "", + sizeof(CalibrationOutput), + 3, + calibration_output__field_descriptors, + calibration_output__field_indices_by_name, + 2, calibration_output__number_ranges, + (ProtobufCMessageInit) calibration_output__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.h new file mode 100644 index 000000000..c60f4f3c8 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationOutput.pb-c.h @@ -0,0 +1,75 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationOutput.proto */ + +#ifndef PROTOBUF_C_CalibrationOutput_2eproto__INCLUDED +#define PROTOBUF_C_CalibrationOutput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _CalibrationOutput CalibrationOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _CalibrationOutput +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidfactor; + double liquidfactor; + protobuf_c_boolean has_haserror; + protobuf_c_boolean haserror; + char *errormessage; +}; +#define CALIBRATION_OUTPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&calibration_output__descriptor) \ + , 0, 0, 0, 0, NULL } + + +/* CalibrationOutput methods */ +void calibration_output__init + (CalibrationOutput *message); +size_t calibration_output__get_packed_size + (const CalibrationOutput *message); +size_t calibration_output__pack + (const CalibrationOutput *message, + uint8_t *out); +size_t calibration_output__pack_to_buffer + (const CalibrationOutput *message, + ProtobufCBuffer *buffer); +CalibrationOutput * + calibration_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void calibration_output__free_unpacked + (CalibrationOutput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CalibrationOutput_Closure) + (const CalibrationOutput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor calibration_output__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_CalibrationOutput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.c new file mode 100644 index 000000000..691a97ea6 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.c @@ -0,0 +1,105 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationPoint.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "CalibrationPoint.pb-c.h" +void calibration_point__init + (CalibrationPoint *message) +{ + static const CalibrationPoint init_value = CALIBRATION_POINT__INIT; + *message = init_value; +} +size_t calibration_point__get_packed_size + (const CalibrationPoint *message) +{ + assert(message->base.descriptor == &calibration_point__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t calibration_point__pack + (const CalibrationPoint *message, + uint8_t *out) +{ + assert(message->base.descriptor == &calibration_point__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t calibration_point__pack_to_buffer + (const CalibrationPoint *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &calibration_point__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CalibrationPoint * + calibration_point__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CalibrationPoint *) + protobuf_c_message_unpack (&calibration_point__descriptor, + allocator, len, data); +} +void calibration_point__free_unpacked + (CalibrationPoint *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &calibration_point__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor calibration_point__field_descriptors[2] = +{ + { + "X", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationPoint, has_x), + offsetof(CalibrationPoint, x), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Y", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(CalibrationPoint, has_y), + offsetof(CalibrationPoint, y), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned calibration_point__field_indices_by_name[] = { + 0, /* field[0] = X */ + 1, /* field[1] = Y */ +}; +static const ProtobufCIntRange calibration_point__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor calibration_point__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CalibrationPoint", + "CalibrationPoint", + "CalibrationPoint", + "", + sizeof(CalibrationPoint), + 2, + calibration_point__field_descriptors, + calibration_point__field_indices_by_name, + 1, calibration_point__number_ranges, + (ProtobufCMessageInit) calibration_point__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.h new file mode 100644 index 000000000..a58bc1ec6 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/CalibrationPoint.pb-c.h @@ -0,0 +1,74 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: CalibrationPoint.proto */ + +#ifndef PROTOBUF_C_CalibrationPoint_2eproto__INCLUDED +#define PROTOBUF_C_CalibrationPoint_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _CalibrationPoint CalibrationPoint; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _CalibrationPoint +{ + ProtobufCMessage base; + protobuf_c_boolean has_x; + double x; + protobuf_c_boolean has_y; + double y; +}; +#define CALIBRATION_POINT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&calibration_point__descriptor) \ + , 0, 0, 0, 0 } + + +/* CalibrationPoint methods */ +void calibration_point__init + (CalibrationPoint *message); +size_t calibration_point__get_packed_size + (const CalibrationPoint *message); +size_t calibration_point__pack + (const CalibrationPoint *message, + uint8_t *out); +size_t calibration_point__pack_to_buffer + (const CalibrationPoint *message, + ProtobufCBuffer *buffer); +CalibrationPoint * + calibration_point__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void calibration_point__free_unpacked + (CalibrationPoint *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CalibrationPoint_Closure) + (const CalibrationPoint *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor calibration_point__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_CalibrationPoint_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.c new file mode 100644 index 000000000..8ea22ca90 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.c @@ -0,0 +1,43 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ColorSpace.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "ColorSpace.pb-c.h" +static const ProtobufCEnumValue color_space__enum_values_by_number[5] = +{ + { "Volume", "COLOR_SPACE__Volume", 0 }, + { "RGB", "COLOR_SPACE__RGB", 1 }, + { "CMYK", "COLOR_SPACE__CMYK", 2 }, + { "LAB", "COLOR_SPACE__LAB", 3 }, + { "Catalog", "COLOR_SPACE__Catalog", 4 }, +}; +static const ProtobufCIntRange color_space__value_ranges[] = { +{0, 0},{0, 5} +}; +static const ProtobufCEnumValueIndex color_space__enum_values_by_name[5] = +{ + { "CMYK", 2 }, + { "Catalog", 4 }, + { "LAB", 3 }, + { "RGB", 1 }, + { "Volume", 0 }, +}; +const ProtobufCEnumDescriptor color_space__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "ColorSpace", + "ColorSpace", + "ColorSpace", + "", + 5, + color_space__enum_values_by_number, + 5, + color_space__enum_values_by_name, + 1, + color_space__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.h new file mode 100644 index 000000000..defb93aa2 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ColorSpace.pb-c.h @@ -0,0 +1,46 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ColorSpace.proto */ + +#ifndef PROTOBUF_C_ColorSpace_2eproto__INCLUDED +#define PROTOBUF_C_ColorSpace_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + + + +/* --- enums --- */ + +typedef enum _ColorSpace { + COLOR_SPACE__Volume = 0, + COLOR_SPACE__RGB = 1, + COLOR_SPACE__CMYK = 2, + COLOR_SPACE__LAB = 3, + COLOR_SPACE__Catalog = 4 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(COLOR_SPACE) +} ColorSpace; + +/* --- messages --- */ + +/* --- per-message closures --- */ + + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor color_space__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_ColorSpace_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.c new file mode 100644 index 000000000..92f60a719 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.c @@ -0,0 +1,287 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ConversionInput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "ConversionInput.pb-c.h" +void conversion_input__init + (ConversionInput *message) +{ + static const ConversionInput init_value = CONVERSION_INPUT__INIT; + *message = init_value; +} +size_t conversion_input__get_packed_size + (const ConversionInput *message) +{ + assert(message->base.descriptor == &conversion_input__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t conversion_input__pack + (const ConversionInput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &conversion_input__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t conversion_input__pack_to_buffer + (const ConversionInput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &conversion_input__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +ConversionInput * + conversion_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (ConversionInput *) + protobuf_c_message_unpack (&conversion_input__descriptor, + allocator, len, data); +} +void conversion_input__free_unpacked + (ConversionInput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &conversion_input__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor conversion_input__field_descriptors[16] = +{ + { + "ThreadL", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_threadl), + offsetof(ConversionInput, threadl), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadA", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_threada), + offsetof(ConversionInput, threada), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadB", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_threadb), + offsetof(ConversionInput, threadb), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ColorSpace", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(ConversionInput, has_colorspace), + offsetof(ConversionInput, colorspace), + &color_space__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InputCoordinates", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(ConversionInput, inputcoordinates), + &input_coordinates__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ForwardData", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(ConversionInput, has_forwarddata), + offsetof(ConversionInput, forwarddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InverseData", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(ConversionInput, has_inversedata), + offsetof(ConversionInput, inversedata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "SegmentLength", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_segmentlength), + offsetof(ConversionInput, segmentlength), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "DeltaChroma", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_deltachroma), + offsetof(ConversionInput, deltachroma), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "DeltaL", + 10, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_deltal), + offsetof(ConversionInput, deltal), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ProcessRanges", + 11, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(ConversionInput, n_processranges), + offsetof(ConversionInput, processranges), + &process_range__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "GenerateHive", + 12, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(ConversionInput, has_generatehive), + offsetof(ConversionInput, generatehive), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "UseLightInks", + 13, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(ConversionInput, has_uselightinks), + offsetof(ConversionInput, uselightinks), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "VMax", + 14, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ConversionInput, has_vmax), + offsetof(ConversionInput, vmax), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "GbdData", + 15, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(ConversionInput, has_gbddata), + offsetof(ConversionInput, gbddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "LubData", + 16, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(ConversionInput, has_lubdata), + offsetof(ConversionInput, lubdata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned conversion_input__field_indices_by_name[] = { + 3, /* field[3] = ColorSpace */ + 8, /* field[8] = DeltaChroma */ + 9, /* field[9] = DeltaL */ + 5, /* field[5] = ForwardData */ + 14, /* field[14] = GbdData */ + 11, /* field[11] = GenerateHive */ + 4, /* field[4] = InputCoordinates */ + 6, /* field[6] = InverseData */ + 15, /* field[15] = LubData */ + 10, /* field[10] = ProcessRanges */ + 7, /* field[7] = SegmentLength */ + 1, /* field[1] = ThreadA */ + 2, /* field[2] = ThreadB */ + 0, /* field[0] = ThreadL */ + 12, /* field[12] = UseLightInks */ + 13, /* field[13] = VMax */ +}; +static const ProtobufCIntRange conversion_input__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 16 } +}; +const ProtobufCMessageDescriptor conversion_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "ConversionInput", + "ConversionInput", + "ConversionInput", + "", + sizeof(ConversionInput), + 16, + conversion_input__field_descriptors, + conversion_input__field_indices_by_name, + 1, conversion_input__number_ranges, + (ProtobufCMessageInit) conversion_input__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.h new file mode 100644 index 000000000..5f03aeceb --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionInput.pb-c.h @@ -0,0 +1,104 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ConversionInput.proto */ + +#ifndef PROTOBUF_C_ConversionInput_2eproto__INCLUDED +#define PROTOBUF_C_ConversionInput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "InputCoordinates.pb-c.h" +#include "ColorSpace.pb-c.h" +#include "ProcessRange.pb-c.h" + +typedef struct _ConversionInput ConversionInput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _ConversionInput +{ + ProtobufCMessage base; + protobuf_c_boolean has_threadl; + double threadl; + protobuf_c_boolean has_threada; + double threada; + protobuf_c_boolean has_threadb; + double threadb; + protobuf_c_boolean has_colorspace; + ColorSpace colorspace; + InputCoordinates *inputcoordinates; + protobuf_c_boolean has_forwarddata; + ProtobufCBinaryData forwarddata; + protobuf_c_boolean has_inversedata; + ProtobufCBinaryData inversedata; + protobuf_c_boolean has_segmentlength; + double segmentlength; + protobuf_c_boolean has_deltachroma; + double deltachroma; + protobuf_c_boolean has_deltal; + double deltal; + size_t n_processranges; + ProcessRange **processranges; + protobuf_c_boolean has_generatehive; + protobuf_c_boolean generatehive; + protobuf_c_boolean has_uselightinks; + protobuf_c_boolean uselightinks; + protobuf_c_boolean has_vmax; + double vmax; + protobuf_c_boolean has_gbddata; + ProtobufCBinaryData gbddata; + protobuf_c_boolean has_lubdata; + ProtobufCBinaryData lubdata; +}; +#define CONVERSION_INPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&conversion_input__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, COLOR_SPACE__Volume, NULL, 0, {0,NULL}, 0, {0,NULL}, 0, 0, 0, 0, 0, 0, 0,NULL, 0, 0, 0, 0, 0, 0, 0, {0,NULL}, 0, {0,NULL} } + + +/* ConversionInput methods */ +void conversion_input__init + (ConversionInput *message); +size_t conversion_input__get_packed_size + (const ConversionInput *message); +size_t conversion_input__pack + (const ConversionInput *message, + uint8_t *out); +size_t conversion_input__pack_to_buffer + (const ConversionInput *message, + ProtobufCBuffer *buffer); +ConversionInput * + conversion_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void conversion_input__free_unpacked + (ConversionInput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*ConversionInput_Closure) + (const ConversionInput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor conversion_input__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_ConversionInput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.c new file mode 100644 index 000000000..da44f28ac --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.c @@ -0,0 +1,158 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ConversionOutput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "ConversionOutput.pb-c.h" +void conversion_output__init + (ConversionOutput *message) +{ + static const ConversionOutput init_value = CONVERSION_OUTPUT__INIT; + *message = init_value; +} +size_t conversion_output__get_packed_size + (const ConversionOutput *message) +{ + assert(message->base.descriptor == &conversion_output__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t conversion_output__pack + (const ConversionOutput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &conversion_output__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t conversion_output__pack_to_buffer + (const ConversionOutput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &conversion_output__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +ConversionOutput * + conversion_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (ConversionOutput *) + protobuf_c_message_unpack (&conversion_output__descriptor, + allocator, len, data); +} +void conversion_output__free_unpacked + (ConversionOutput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &conversion_output__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor conversion_output__field_descriptors[6] = +{ + { + "HiveCoordinates", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(ConversionOutput, n_hivecoordinates), + offsetof(ConversionOutput, hivecoordinates), + &output_coordinates__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TripleCoordinates", + 2, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(ConversionOutput, n_triplecoordinates), + offsetof(ConversionOutput, triplecoordinates), + &output_coordinates__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "SingleCoordinates", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(ConversionOutput, singlecoordinates), + &output_coordinates__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "OutOfGamut", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(ConversionOutput, has_outofgamut), + offsetof(ConversionOutput, outofgamut), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "HasError", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(ConversionOutput, has_haserror), + offsetof(ConversionOutput, haserror), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ErrorMessage", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(ConversionOutput, errormessage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned conversion_output__field_indices_by_name[] = { + 5, /* field[5] = ErrorMessage */ + 4, /* field[4] = HasError */ + 0, /* field[0] = HiveCoordinates */ + 3, /* field[3] = OutOfGamut */ + 2, /* field[2] = SingleCoordinates */ + 1, /* field[1] = TripleCoordinates */ +}; +static const ProtobufCIntRange conversion_output__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 5, 3 }, + { 0, 6 } +}; +const ProtobufCMessageDescriptor conversion_output__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "ConversionOutput", + "ConversionOutput", + "ConversionOutput", + "", + sizeof(ConversionOutput), + 6, + conversion_output__field_descriptors, + conversion_output__field_indices_by_name, + 2, conversion_output__number_ranges, + (ProtobufCMessageInit) conversion_output__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.h new file mode 100644 index 000000000..c85c11bd7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ConversionOutput.pb-c.h @@ -0,0 +1,81 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ConversionOutput.proto */ + +#ifndef PROTOBUF_C_ConversionOutput_2eproto__INCLUDED +#define PROTOBUF_C_ConversionOutput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "OutputCoordinates.pb-c.h" + +typedef struct _ConversionOutput ConversionOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _ConversionOutput +{ + ProtobufCMessage base; + size_t n_hivecoordinates; + OutputCoordinates **hivecoordinates; + size_t n_triplecoordinates; + OutputCoordinates **triplecoordinates; + OutputCoordinates *singlecoordinates; + protobuf_c_boolean has_outofgamut; + protobuf_c_boolean outofgamut; + protobuf_c_boolean has_haserror; + protobuf_c_boolean haserror; + char *errormessage; +}; +#define CONVERSION_OUTPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&conversion_output__descriptor) \ + , 0,NULL, 0,NULL, NULL, 0, 0, 0, 0, NULL } + + +/* ConversionOutput methods */ +void conversion_output__init + (ConversionOutput *message); +size_t conversion_output__get_packed_size + (const ConversionOutput *message); +size_t conversion_output__pack + (const ConversionOutput *message, + uint8_t *out); +size_t conversion_output__pack_to_buffer + (const ConversionOutput *message, + ProtobufCBuffer *buffer); +ConversionOutput * + conversion_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void conversion_output__free_unpacked + (ConversionOutput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*ConversionOutput_Closure) + (const ConversionOutput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor conversion_output__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_ConversionOutput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.c new file mode 100644 index 000000000..3b4f011b3 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.c @@ -0,0 +1,209 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientConversionInput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "GradientConversionInput.pb-c.h" +void gradient_conversion_input__init + (GradientConversionInput *message) +{ + static const GradientConversionInput init_value = GRADIENT_CONVERSION_INPUT__INIT; + *message = init_value; +} +size_t gradient_conversion_input__get_packed_size + (const GradientConversionInput *message) +{ + assert(message->base.descriptor == &gradient_conversion_input__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t gradient_conversion_input__pack + (const GradientConversionInput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &gradient_conversion_input__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t gradient_conversion_input__pack_to_buffer + (const GradientConversionInput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &gradient_conversion_input__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +GradientConversionInput * + gradient_conversion_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (GradientConversionInput *) + protobuf_c_message_unpack (&gradient_conversion_input__descriptor, + allocator, len, data); +} +void gradient_conversion_input__free_unpacked + (GradientConversionInput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &gradient_conversion_input__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor gradient_conversion_input__field_descriptors[10] = +{ + { + "ThreadL", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientConversionInput, has_threadl), + offsetof(GradientConversionInput, threadl), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadA", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientConversionInput, has_threada), + offsetof(GradientConversionInput, threada), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadB", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientConversionInput, has_threadb), + offsetof(GradientConversionInput, threadb), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ForwardData", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(GradientConversionInput, has_forwarddata), + offsetof(GradientConversionInput, forwarddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "SegmentLength", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientConversionInput, has_segmentlength), + offsetof(GradientConversionInput, segmentlength), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Stops", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientConversionInput, n_stops), + offsetof(GradientConversionInput, stops), + &gradient_input_stop__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InputLiquids", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientConversionInput, n_inputliquids), + offsetof(GradientConversionInput, inputliquids), + &input_liquid__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ProcessRanges", + 8, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientConversionInput, n_processranges), + offsetof(GradientConversionInput, processranges), + &process_range__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "GbdData", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(GradientConversionInput, has_gbddata), + offsetof(GradientConversionInput, gbddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "LubData", + 10, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(GradientConversionInput, has_lubdata), + offsetof(GradientConversionInput, lubdata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned gradient_conversion_input__field_indices_by_name[] = { + 3, /* field[3] = ForwardData */ + 8, /* field[8] = GbdData */ + 6, /* field[6] = InputLiquids */ + 9, /* field[9] = LubData */ + 7, /* field[7] = ProcessRanges */ + 4, /* field[4] = SegmentLength */ + 5, /* field[5] = Stops */ + 1, /* field[1] = ThreadA */ + 2, /* field[2] = ThreadB */ + 0, /* field[0] = ThreadL */ +}; +static const ProtobufCIntRange gradient_conversion_input__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 10 } +}; +const ProtobufCMessageDescriptor gradient_conversion_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "GradientConversionInput", + "GradientConversionInput", + "GradientConversionInput", + "", + sizeof(GradientConversionInput), + 10, + gradient_conversion_input__field_descriptors, + gradient_conversion_input__field_indices_by_name, + 1, gradient_conversion_input__number_ranges, + (ProtobufCMessageInit) gradient_conversion_input__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.h new file mode 100644 index 000000000..fa9007907 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionInput.pb-c.h @@ -0,0 +1,93 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientConversionInput.proto */ + +#ifndef PROTOBUF_C_GradientConversionInput_2eproto__INCLUDED +#define PROTOBUF_C_GradientConversionInput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "ProcessRange.pb-c.h" +#include "InputLiquid.pb-c.h" +#include "GradientInputStop.pb-c.h" + +typedef struct _GradientConversionInput GradientConversionInput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _GradientConversionInput +{ + ProtobufCMessage base; + protobuf_c_boolean has_threadl; + double threadl; + protobuf_c_boolean has_threada; + double threada; + protobuf_c_boolean has_threadb; + double threadb; + protobuf_c_boolean has_forwarddata; + ProtobufCBinaryData forwarddata; + protobuf_c_boolean has_segmentlength; + double segmentlength; + size_t n_stops; + GradientInputStop **stops; + size_t n_inputliquids; + InputLiquid **inputliquids; + size_t n_processranges; + ProcessRange **processranges; + protobuf_c_boolean has_gbddata; + ProtobufCBinaryData gbddata; + protobuf_c_boolean has_lubdata; + ProtobufCBinaryData lubdata; +}; +#define GRADIENT_CONVERSION_INPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&gradient_conversion_input__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, {0,NULL}, 0, 0, 0,NULL, 0,NULL, 0,NULL, 0, {0,NULL}, 0, {0,NULL} } + + +/* GradientConversionInput methods */ +void gradient_conversion_input__init + (GradientConversionInput *message); +size_t gradient_conversion_input__get_packed_size + (const GradientConversionInput *message); +size_t gradient_conversion_input__pack + (const GradientConversionInput *message, + uint8_t *out); +size_t gradient_conversion_input__pack_to_buffer + (const GradientConversionInput *message, + ProtobufCBuffer *buffer); +GradientConversionInput * + gradient_conversion_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void gradient_conversion_input__free_unpacked + (GradientConversionInput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*GradientConversionInput_Closure) + (const GradientConversionInput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor gradient_conversion_input__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_GradientConversionInput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.c new file mode 100644 index 000000000..50c69152f --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.c @@ -0,0 +1,118 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientConversionOutput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "GradientConversionOutput.pb-c.h" +void gradient_conversion_output__init + (GradientConversionOutput *message) +{ + static const GradientConversionOutput init_value = GRADIENT_CONVERSION_OUTPUT__INIT; + *message = init_value; +} +size_t gradient_conversion_output__get_packed_size + (const GradientConversionOutput *message) +{ + assert(message->base.descriptor == &gradient_conversion_output__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t gradient_conversion_output__pack + (const GradientConversionOutput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &gradient_conversion_output__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t gradient_conversion_output__pack_to_buffer + (const GradientConversionOutput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &gradient_conversion_output__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +GradientConversionOutput * + gradient_conversion_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (GradientConversionOutput *) + protobuf_c_message_unpack (&gradient_conversion_output__descriptor, + allocator, len, data); +} +void gradient_conversion_output__free_unpacked + (GradientConversionOutput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &gradient_conversion_output__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor gradient_conversion_output__field_descriptors[3] = +{ + { + "Stops", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientConversionOutput, n_stops), + offsetof(GradientConversionOutput, stops), + &gradient_output_stop__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "HasError", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(GradientConversionOutput, has_haserror), + offsetof(GradientConversionOutput, haserror), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ErrorMessage", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(GradientConversionOutput, errormessage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned gradient_conversion_output__field_indices_by_name[] = { + 2, /* field[2] = ErrorMessage */ + 1, /* field[1] = HasError */ + 0, /* field[0] = Stops */ +}; +static const ProtobufCIntRange gradient_conversion_output__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor gradient_conversion_output__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "GradientConversionOutput", + "GradientConversionOutput", + "GradientConversionOutput", + "", + sizeof(GradientConversionOutput), + 3, + gradient_conversion_output__field_descriptors, + gradient_conversion_output__field_indices_by_name, + 1, gradient_conversion_output__number_ranges, + (ProtobufCMessageInit) gradient_conversion_output__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.h new file mode 100644 index 000000000..48a581c0f --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientConversionOutput.pb-c.h @@ -0,0 +1,76 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientConversionOutput.proto */ + +#ifndef PROTOBUF_C_GradientConversionOutput_2eproto__INCLUDED +#define PROTOBUF_C_GradientConversionOutput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "GradientOutputStop.pb-c.h" + +typedef struct _GradientConversionOutput GradientConversionOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _GradientConversionOutput +{ + ProtobufCMessage base; + size_t n_stops; + GradientOutputStop **stops; + protobuf_c_boolean has_haserror; + protobuf_c_boolean haserror; + char *errormessage; +}; +#define GRADIENT_CONVERSION_OUTPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&gradient_conversion_output__descriptor) \ + , 0,NULL, 0, 0, NULL } + + +/* GradientConversionOutput methods */ +void gradient_conversion_output__init + (GradientConversionOutput *message); +size_t gradient_conversion_output__get_packed_size + (const GradientConversionOutput *message); +size_t gradient_conversion_output__pack + (const GradientConversionOutput *message, + uint8_t *out); +size_t gradient_conversion_output__pack_to_buffer + (const GradientConversionOutput *message, + ProtobufCBuffer *buffer); +GradientConversionOutput * + gradient_conversion_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void gradient_conversion_output__free_unpacked + (GradientConversionOutput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*GradientConversionOutput_Closure) + (const GradientConversionOutput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor gradient_conversion_output__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_GradientConversionOutput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.c new file mode 100644 index 000000000..7a3002748 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.c @@ -0,0 +1,248 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientInputStop.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "GradientInputStop.pb-c.h" +void gradient_input_stop__init + (GradientInputStop *message) +{ + static const GradientInputStop init_value = GRADIENT_INPUT_STOP__INIT; + *message = init_value; +} +size_t gradient_input_stop__get_packed_size + (const GradientInputStop *message) +{ + assert(message->base.descriptor == &gradient_input_stop__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t gradient_input_stop__pack + (const GradientInputStop *message, + uint8_t *out) +{ + assert(message->base.descriptor == &gradient_input_stop__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t gradient_input_stop__pack_to_buffer + (const GradientInputStop *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &gradient_input_stop__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +GradientInputStop * + gradient_input_stop__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (GradientInputStop *) + protobuf_c_message_unpack (&gradient_input_stop__descriptor, + allocator, len, data); +} +void gradient_input_stop__free_unpacked + (GradientInputStop *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &gradient_input_stop__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor gradient_input_stop__field_descriptors[13] = +{ + { + "Offset", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_offset), + offsetof(GradientInputStop, offset), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ColorSpace", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(GradientInputStop, has_colorspace), + offsetof(GradientInputStop, colorspace), + &color_space__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Red", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(GradientInputStop, has_red), + offsetof(GradientInputStop, red), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Green", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(GradientInputStop, has_green), + offsetof(GradientInputStop, green), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Blue", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(GradientInputStop, has_blue), + offsetof(GradientInputStop, blue), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Cyan", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_cyan), + offsetof(GradientInputStop, cyan), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Magenta", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_magenta), + offsetof(GradientInputStop, magenta), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Yellow", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_yellow), + offsetof(GradientInputStop, yellow), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Key", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_key), + offsetof(GradientInputStop, key), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "L", + 10, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_l), + offsetof(GradientInputStop, l), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "A", + 11, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_a), + offsetof(GradientInputStop, a), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "B", + 12, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientInputStop, has_b), + offsetof(GradientInputStop, b), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "LiquidVolumes", + 13, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientInputStop, n_liquidvolumes), + offsetof(GradientInputStop, liquidvolumes), + &liquid_volume__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned gradient_input_stop__field_indices_by_name[] = { + 10, /* field[10] = A */ + 11, /* field[11] = B */ + 4, /* field[4] = Blue */ + 1, /* field[1] = ColorSpace */ + 5, /* field[5] = Cyan */ + 3, /* field[3] = Green */ + 8, /* field[8] = Key */ + 9, /* field[9] = L */ + 12, /* field[12] = LiquidVolumes */ + 6, /* field[6] = Magenta */ + 0, /* field[0] = Offset */ + 2, /* field[2] = Red */ + 7, /* field[7] = Yellow */ +}; +static const ProtobufCIntRange gradient_input_stop__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 13 } +}; +const ProtobufCMessageDescriptor gradient_input_stop__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "GradientInputStop", + "GradientInputStop", + "GradientInputStop", + "", + sizeof(GradientInputStop), + 13, + gradient_input_stop__field_descriptors, + gradient_input_stop__field_indices_by_name, + 1, gradient_input_stop__number_ranges, + (ProtobufCMessageInit) gradient_input_stop__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.h new file mode 100644 index 000000000..058120b82 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientInputStop.pb-c.h @@ -0,0 +1,98 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientInputStop.proto */ + +#ifndef PROTOBUF_C_GradientInputStop_2eproto__INCLUDED +#define PROTOBUF_C_GradientInputStop_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "ColorSpace.pb-c.h" +#include "LiquidVolume.pb-c.h" + +typedef struct _GradientInputStop GradientInputStop; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _GradientInputStop +{ + ProtobufCMessage base; + protobuf_c_boolean has_offset; + double offset; + protobuf_c_boolean has_colorspace; + ColorSpace colorspace; + protobuf_c_boolean has_red; + int32_t red; + protobuf_c_boolean has_green; + int32_t green; + protobuf_c_boolean has_blue; + int32_t blue; + protobuf_c_boolean has_cyan; + double cyan; + protobuf_c_boolean has_magenta; + double magenta; + protobuf_c_boolean has_yellow; + double yellow; + protobuf_c_boolean has_key; + double key; + protobuf_c_boolean has_l; + double l; + protobuf_c_boolean has_a; + double a; + protobuf_c_boolean has_b; + double b; + size_t n_liquidvolumes; + LiquidVolume **liquidvolumes; +}; +#define GRADIENT_INPUT_STOP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&gradient_input_stop__descriptor) \ + , 0, 0, 0, COLOR_SPACE__Volume, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,NULL } + + +/* GradientInputStop methods */ +void gradient_input_stop__init + (GradientInputStop *message); +size_t gradient_input_stop__get_packed_size + (const GradientInputStop *message); +size_t gradient_input_stop__pack + (const GradientInputStop *message, + uint8_t *out); +size_t gradient_input_stop__pack_to_buffer + (const GradientInputStop *message, + ProtobufCBuffer *buffer); +GradientInputStop * + gradient_input_stop__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void gradient_input_stop__free_unpacked + (GradientInputStop *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*GradientInputStop_Closure) + (const GradientInputStop *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor gradient_input_stop__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_GradientInputStop_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.c new file mode 100644 index 000000000..62b3b744a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.c @@ -0,0 +1,118 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientOutputStop.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "GradientOutputStop.pb-c.h" +void gradient_output_stop__init + (GradientOutputStop *message) +{ + static const GradientOutputStop init_value = GRADIENT_OUTPUT_STOP__INIT; + *message = init_value; +} +size_t gradient_output_stop__get_packed_size + (const GradientOutputStop *message) +{ + assert(message->base.descriptor == &gradient_output_stop__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t gradient_output_stop__pack + (const GradientOutputStop *message, + uint8_t *out) +{ + assert(message->base.descriptor == &gradient_output_stop__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t gradient_output_stop__pack_to_buffer + (const GradientOutputStop *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &gradient_output_stop__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +GradientOutputStop * + gradient_output_stop__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (GradientOutputStop *) + protobuf_c_message_unpack (&gradient_output_stop__descriptor, + allocator, len, data); +} +void gradient_output_stop__free_unpacked + (GradientOutputStop *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &gradient_output_stop__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor gradient_output_stop__field_descriptors[3] = +{ + { + "Offset", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientOutputStop, has_offset), + offsetof(GradientOutputStop, offset), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ProcessParametersTableIndex", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(GradientOutputStop, has_processparameterstableindex), + offsetof(GradientOutputStop, processparameterstableindex), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "OutputLiquids", + 3, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientOutputStop, n_outputliquids), + offsetof(GradientOutputStop, outputliquids), + &output_liquid__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned gradient_output_stop__field_indices_by_name[] = { + 0, /* field[0] = Offset */ + 2, /* field[2] = OutputLiquids */ + 1, /* field[1] = ProcessParametersTableIndex */ +}; +static const ProtobufCIntRange gradient_output_stop__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor gradient_output_stop__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "GradientOutputStop", + "GradientOutputStop", + "GradientOutputStop", + "", + sizeof(GradientOutputStop), + 3, + gradient_output_stop__field_descriptors, + gradient_output_stop__field_indices_by_name, + 1, gradient_output_stop__number_ranges, + (ProtobufCMessageInit) gradient_output_stop__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.h new file mode 100644 index 000000000..4d765a8bf --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/GradientOutputStop.pb-c.h @@ -0,0 +1,77 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: GradientOutputStop.proto */ + +#ifndef PROTOBUF_C_GradientOutputStop_2eproto__INCLUDED +#define PROTOBUF_C_GradientOutputStop_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "OutputLiquid.pb-c.h" + +typedef struct _GradientOutputStop GradientOutputStop; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _GradientOutputStop +{ + ProtobufCMessage base; + protobuf_c_boolean has_offset; + double offset; + protobuf_c_boolean has_processparameterstableindex; + int32_t processparameterstableindex; + size_t n_outputliquids; + OutputLiquid **outputliquids; +}; +#define GRADIENT_OUTPUT_STOP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&gradient_output_stop__descriptor) \ + , 0, 0, 0, 0, 0,NULL } + + +/* GradientOutputStop methods */ +void gradient_output_stop__init + (GradientOutputStop *message); +size_t gradient_output_stop__get_packed_size + (const GradientOutputStop *message); +size_t gradient_output_stop__pack + (const GradientOutputStop *message, + uint8_t *out); +size_t gradient_output_stop__pack_to_buffer + (const GradientOutputStop *message, + ProtobufCBuffer *buffer); +GradientOutputStop * + gradient_output_stop__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void gradient_output_stop__free_unpacked + (GradientOutputStop *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*GradientOutputStop_Closure) + (const GradientOutputStop *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor gradient_output_stop__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_GradientOutputStop_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.c new file mode 100644 index 000000000..a12759a89 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.c @@ -0,0 +1,248 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: InputCoordinates.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "InputCoordinates.pb-c.h" +void input_coordinates__init + (InputCoordinates *message) +{ + static const InputCoordinates init_value = INPUT_COORDINATES__INIT; + *message = init_value; +} +size_t input_coordinates__get_packed_size + (const InputCoordinates *message) +{ + assert(message->base.descriptor == &input_coordinates__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t input_coordinates__pack + (const InputCoordinates *message, + uint8_t *out) +{ + assert(message->base.descriptor == &input_coordinates__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t input_coordinates__pack_to_buffer + (const InputCoordinates *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &input_coordinates__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +InputCoordinates * + input_coordinates__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (InputCoordinates *) + protobuf_c_message_unpack (&input_coordinates__descriptor, + allocator, len, data); +} +void input_coordinates__free_unpacked + (InputCoordinates *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &input_coordinates__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor input_coordinates__field_descriptors[13] = +{ + { + "Length", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_length), + offsetof(InputCoordinates, length), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Red", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputCoordinates, has_red), + offsetof(InputCoordinates, red), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Green", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputCoordinates, has_green), + offsetof(InputCoordinates, green), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Blue", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputCoordinates, has_blue), + offsetof(InputCoordinates, blue), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Cyan", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_cyan), + offsetof(InputCoordinates, cyan), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Magenta", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_magenta), + offsetof(InputCoordinates, magenta), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Yellow", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_yellow), + offsetof(InputCoordinates, yellow), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Key", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_key), + offsetof(InputCoordinates, key), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "L", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_l), + offsetof(InputCoordinates, l), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "A", + 10, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_a), + offsetof(InputCoordinates, a), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "B", + 11, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputCoordinates, has_b), + offsetof(InputCoordinates, b), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "PantonCode", + 12, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputCoordinates, has_pantoncode), + offsetof(InputCoordinates, pantoncode), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InputLiquids", + 13, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(InputCoordinates, n_inputliquids), + offsetof(InputCoordinates, inputliquids), + &input_liquid__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned input_coordinates__field_indices_by_name[] = { + 9, /* field[9] = A */ + 10, /* field[10] = B */ + 3, /* field[3] = Blue */ + 4, /* field[4] = Cyan */ + 2, /* field[2] = Green */ + 12, /* field[12] = InputLiquids */ + 7, /* field[7] = Key */ + 8, /* field[8] = L */ + 0, /* field[0] = Length */ + 5, /* field[5] = Magenta */ + 11, /* field[11] = PantonCode */ + 1, /* field[1] = Red */ + 6, /* field[6] = Yellow */ +}; +static const ProtobufCIntRange input_coordinates__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 13 } +}; +const ProtobufCMessageDescriptor input_coordinates__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "InputCoordinates", + "InputCoordinates", + "InputCoordinates", + "", + sizeof(InputCoordinates), + 13, + input_coordinates__field_descriptors, + input_coordinates__field_indices_by_name, + 1, input_coordinates__number_ranges, + (ProtobufCMessageInit) input_coordinates__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.h new file mode 100644 index 000000000..0b159cd59 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputCoordinates.pb-c.h @@ -0,0 +1,97 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: InputCoordinates.proto */ + +#ifndef PROTOBUF_C_InputCoordinates_2eproto__INCLUDED +#define PROTOBUF_C_InputCoordinates_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "InputLiquid.pb-c.h" + +typedef struct _InputCoordinates InputCoordinates; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _InputCoordinates +{ + ProtobufCMessage base; + protobuf_c_boolean has_length; + double length; + protobuf_c_boolean has_red; + int32_t red; + protobuf_c_boolean has_green; + int32_t green; + protobuf_c_boolean has_blue; + int32_t blue; + protobuf_c_boolean has_cyan; + double cyan; + protobuf_c_boolean has_magenta; + double magenta; + protobuf_c_boolean has_yellow; + double yellow; + protobuf_c_boolean has_key; + double key; + protobuf_c_boolean has_l; + double l; + protobuf_c_boolean has_a; + double a; + protobuf_c_boolean has_b; + double b; + protobuf_c_boolean has_pantoncode; + int32_t pantoncode; + size_t n_inputliquids; + InputLiquid **inputliquids; +}; +#define INPUT_COORDINATES__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&input_coordinates__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,NULL } + + +/* InputCoordinates methods */ +void input_coordinates__init + (InputCoordinates *message); +size_t input_coordinates__get_packed_size + (const InputCoordinates *message); +size_t input_coordinates__pack + (const InputCoordinates *message, + uint8_t *out); +size_t input_coordinates__pack_to_buffer + (const InputCoordinates *message, + ProtobufCBuffer *buffer); +InputCoordinates * + input_coordinates__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void input_coordinates__free_unpacked + (InputCoordinates *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*InputCoordinates_Closure) + (const InputCoordinates *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor input_coordinates__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_InputCoordinates_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.c new file mode 100644 index 000000000..2d033e2a1 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.c @@ -0,0 +1,131 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: InputLiquid.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "InputLiquid.pb-c.h" +void input_liquid__init + (InputLiquid *message) +{ + static const InputLiquid init_value = INPUT_LIQUID__INIT; + *message = init_value; +} +size_t input_liquid__get_packed_size + (const InputLiquid *message) +{ + assert(message->base.descriptor == &input_liquid__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t input_liquid__pack + (const InputLiquid *message, + uint8_t *out) +{ + assert(message->base.descriptor == &input_liquid__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t input_liquid__pack_to_buffer + (const InputLiquid *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &input_liquid__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +InputLiquid * + input_liquid__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (InputLiquid *) + protobuf_c_message_unpack (&input_liquid__descriptor, + allocator, len, data); +} +void input_liquid__free_unpacked + (InputLiquid *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &input_liquid__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor input_liquid__field_descriptors[4] = +{ + { + "LiquidType", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(InputLiquid, has_liquidtype), + offsetof(InputLiquid, liquidtype), + &liquid_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "CalibrationData", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(InputLiquid, calibrationdata), + &calibration_data__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "MaxNanoliterPerCentimeter", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputLiquid, has_maxnanoliterpercentimeter), + offsetof(InputLiquid, maxnanoliterpercentimeter), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Volume", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(InputLiquid, has_volume), + offsetof(InputLiquid, volume), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned input_liquid__field_indices_by_name[] = { + 1, /* field[1] = CalibrationData */ + 0, /* field[0] = LiquidType */ + 2, /* field[2] = MaxNanoliterPerCentimeter */ + 3, /* field[3] = Volume */ +}; +static const ProtobufCIntRange input_liquid__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor input_liquid__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "InputLiquid", + "InputLiquid", + "InputLiquid", + "", + sizeof(InputLiquid), + 4, + input_liquid__field_descriptors, + input_liquid__field_indices_by_name, + 1, input_liquid__number_ranges, + (ProtobufCMessageInit) input_liquid__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.h new file mode 100644 index 000000000..c2a47b166 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/InputLiquid.pb-c.h @@ -0,0 +1,79 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: InputLiquid.proto */ + +#ifndef PROTOBUF_C_InputLiquid_2eproto__INCLUDED +#define PROTOBUF_C_InputLiquid_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "LiquidType.pb-c.h" +#include "CalibrationData.pb-c.h" + +typedef struct _InputLiquid InputLiquid; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _InputLiquid +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidtype; + LiquidType liquidtype; + CalibrationData *calibrationdata; + protobuf_c_boolean has_maxnanoliterpercentimeter; + double maxnanoliterpercentimeter; + protobuf_c_boolean has_volume; + double volume; +}; +#define INPUT_LIQUID__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&input_liquid__descriptor) \ + , 0, LIQUID_TYPE__Cyan, NULL, 0, 0, 0, 0 } + + +/* InputLiquid methods */ +void input_liquid__init + (InputLiquid *message); +size_t input_liquid__get_packed_size + (const InputLiquid *message); +size_t input_liquid__pack + (const InputLiquid *message, + uint8_t *out); +size_t input_liquid__pack_to_buffer + (const InputLiquid *message, + ProtobufCBuffer *buffer); +InputLiquid * + input_liquid__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void input_liquid__free_unpacked + (InputLiquid *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*InputLiquid_Closure) + (const InputLiquid *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor input_liquid__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_InputLiquid_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.c new file mode 100644 index 000000000..5d30f6cd5 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.c @@ -0,0 +1,144 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LinearizationInput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "LinearizationInput.pb-c.h" +void linearization_input__init + (LinearizationInput *message) +{ + static const LinearizationInput init_value = LINEARIZATION_INPUT__INIT; + *message = init_value; +} +size_t linearization_input__get_packed_size + (const LinearizationInput *message) +{ + assert(message->base.descriptor == &linearization_input__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t linearization_input__pack + (const LinearizationInput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &linearization_input__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t linearization_input__pack_to_buffer + (const LinearizationInput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &linearization_input__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +LinearizationInput * + linearization_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (LinearizationInput *) + protobuf_c_message_unpack (&linearization_input__descriptor, + allocator, len, data); +} +void linearization_input__free_unpacked + (LinearizationInput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &linearization_input__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor linearization_input__field_descriptors[5] = +{ + { + "LiquidType", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(LinearizationInput, has_liquidtype), + offsetof(LinearizationInput, liquidtype), + &liquid_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TargetL", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationInput, has_targetl), + offsetof(LinearizationInput, targetl), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TargetA", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationInput, has_targeta), + offsetof(LinearizationInput, targeta), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "TargetB", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationInput, has_targetb), + offsetof(LinearizationInput, targetb), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Measurements", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(LinearizationInput, n_measurements), + offsetof(LinearizationInput, measurements), + &linearization_measurement__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned linearization_input__field_indices_by_name[] = { + 0, /* field[0] = LiquidType */ + 4, /* field[4] = Measurements */ + 2, /* field[2] = TargetA */ + 3, /* field[3] = TargetB */ + 1, /* field[1] = TargetL */ +}; +static const ProtobufCIntRange linearization_input__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor linearization_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "LinearizationInput", + "LinearizationInput", + "LinearizationInput", + "", + sizeof(LinearizationInput), + 5, + linearization_input__field_descriptors, + linearization_input__field_indices_by_name, + 1, linearization_input__number_ranges, + (ProtobufCMessageInit) linearization_input__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.h new file mode 100644 index 000000000..9cab974c5 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationInput.pb-c.h @@ -0,0 +1,82 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LinearizationInput.proto */ + +#ifndef PROTOBUF_C_LinearizationInput_2eproto__INCLUDED +#define PROTOBUF_C_LinearizationInput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "LinearizationMeasurement.pb-c.h" +#include "LiquidType.pb-c.h" + +typedef struct _LinearizationInput LinearizationInput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _LinearizationInput +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidtype; + LiquidType liquidtype; + protobuf_c_boolean has_targetl; + double targetl; + protobuf_c_boolean has_targeta; + double targeta; + protobuf_c_boolean has_targetb; + double targetb; + size_t n_measurements; + LinearizationMeasurement **measurements; +}; +#define LINEARIZATION_INPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&linearization_input__descriptor) \ + , 0, LIQUID_TYPE__Cyan, 0, 0, 0, 0, 0, 0, 0,NULL } + + +/* LinearizationInput methods */ +void linearization_input__init + (LinearizationInput *message); +size_t linearization_input__get_packed_size + (const LinearizationInput *message); +size_t linearization_input__pack + (const LinearizationInput *message, + uint8_t *out); +size_t linearization_input__pack_to_buffer + (const LinearizationInput *message, + ProtobufCBuffer *buffer); +LinearizationInput * + linearization_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void linearization_input__free_unpacked + (LinearizationInput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*LinearizationInput_Closure) + (const LinearizationInput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor linearization_input__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_LinearizationInput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.c new file mode 100644 index 000000000..0a242ee0f --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.c @@ -0,0 +1,131 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LinearizationMeasurement.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "LinearizationMeasurement.pb-c.h" +void linearization_measurement__init + (LinearizationMeasurement *message) +{ + static const LinearizationMeasurement init_value = LINEARIZATION_MEASUREMENT__INIT; + *message = init_value; +} +size_t linearization_measurement__get_packed_size + (const LinearizationMeasurement *message) +{ + assert(message->base.descriptor == &linearization_measurement__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t linearization_measurement__pack + (const LinearizationMeasurement *message, + uint8_t *out) +{ + assert(message->base.descriptor == &linearization_measurement__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t linearization_measurement__pack_to_buffer + (const LinearizationMeasurement *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &linearization_measurement__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +LinearizationMeasurement * + linearization_measurement__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (LinearizationMeasurement *) + protobuf_c_message_unpack (&linearization_measurement__descriptor, + allocator, len, data); +} +void linearization_measurement__free_unpacked + (LinearizationMeasurement *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &linearization_measurement__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor linearization_measurement__field_descriptors[4] = +{ + { + "InkPercentage", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationMeasurement, has_inkpercentage), + offsetof(LinearizationMeasurement, inkpercentage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "L", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationMeasurement, has_l), + offsetof(LinearizationMeasurement, l), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "A", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationMeasurement, has_a), + offsetof(LinearizationMeasurement, a), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "B", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationMeasurement, has_b), + offsetof(LinearizationMeasurement, b), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned linearization_measurement__field_indices_by_name[] = { + 2, /* field[2] = A */ + 3, /* field[3] = B */ + 0, /* field[0] = InkPercentage */ + 1, /* field[1] = L */ +}; +static const ProtobufCIntRange linearization_measurement__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor linearization_measurement__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "LinearizationMeasurement", + "LinearizationMeasurement", + "LinearizationMeasurement", + "", + sizeof(LinearizationMeasurement), + 4, + linearization_measurement__field_descriptors, + linearization_measurement__field_indices_by_name, + 1, linearization_measurement__number_ranges, + (ProtobufCMessageInit) linearization_measurement__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.h new file mode 100644 index 000000000..b4f17f87e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationMeasurement.pb-c.h @@ -0,0 +1,78 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LinearizationMeasurement.proto */ + +#ifndef PROTOBUF_C_LinearizationMeasurement_2eproto__INCLUDED +#define PROTOBUF_C_LinearizationMeasurement_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _LinearizationMeasurement LinearizationMeasurement; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _LinearizationMeasurement +{ + ProtobufCMessage base; + protobuf_c_boolean has_inkpercentage; + double inkpercentage; + protobuf_c_boolean has_l; + double l; + protobuf_c_boolean has_a; + double a; + protobuf_c_boolean has_b; + double b; +}; +#define LINEARIZATION_MEASUREMENT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&linearization_measurement__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, 0 } + + +/* LinearizationMeasurement methods */ +void linearization_measurement__init + (LinearizationMeasurement *message); +size_t linearization_measurement__get_packed_size + (const LinearizationMeasurement *message); +size_t linearization_measurement__pack + (const LinearizationMeasurement *message, + uint8_t *out); +size_t linearization_measurement__pack_to_buffer + (const LinearizationMeasurement *message, + ProtobufCBuffer *buffer); +LinearizationMeasurement * + linearization_measurement__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void linearization_measurement__free_unpacked + (LinearizationMeasurement *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*LinearizationMeasurement_Closure) + (const LinearizationMeasurement *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor linearization_measurement__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_LinearizationMeasurement_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.c new file mode 100644 index 000000000..5bd04b218 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.c @@ -0,0 +1,119 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LinearizationOutput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "LinearizationOutput.pb-c.h" +void linearization_output__init + (LinearizationOutput *message) +{ + static const LinearizationOutput init_value = LINEARIZATION_OUTPUT__INIT; + *message = init_value; +} +size_t linearization_output__get_packed_size + (const LinearizationOutput *message) +{ + assert(message->base.descriptor == &linearization_output__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t linearization_output__pack + (const LinearizationOutput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &linearization_output__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t linearization_output__pack_to_buffer + (const LinearizationOutput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &linearization_output__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +LinearizationOutput * + linearization_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (LinearizationOutput *) + protobuf_c_message_unpack (&linearization_output__descriptor, + allocator, len, data); +} +void linearization_output__free_unpacked + (LinearizationOutput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &linearization_output__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor linearization_output__field_descriptors[3] = +{ + { + "InkPercentage", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LinearizationOutput, n_inkpercentage), + offsetof(LinearizationOutput, inkpercentage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "HasError", + 20, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(LinearizationOutput, has_haserror), + offsetof(LinearizationOutput, haserror), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ErrorMessage", + 21, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(LinearizationOutput, errormessage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned linearization_output__field_indices_by_name[] = { + 2, /* field[2] = ErrorMessage */ + 1, /* field[1] = HasError */ + 0, /* field[0] = InkPercentage */ +}; +static const ProtobufCIntRange linearization_output__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 20, 1 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor linearization_output__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "LinearizationOutput", + "LinearizationOutput", + "LinearizationOutput", + "", + sizeof(LinearizationOutput), + 3, + linearization_output__field_descriptors, + linearization_output__field_indices_by_name, + 2, linearization_output__number_ranges, + (ProtobufCMessageInit) linearization_output__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.h new file mode 100644 index 000000000..b0ab54e12 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LinearizationOutput.pb-c.h @@ -0,0 +1,75 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LinearizationOutput.proto */ + +#ifndef PROTOBUF_C_LinearizationOutput_2eproto__INCLUDED +#define PROTOBUF_C_LinearizationOutput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _LinearizationOutput LinearizationOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _LinearizationOutput +{ + ProtobufCMessage base; + size_t n_inkpercentage; + double *inkpercentage; + protobuf_c_boolean has_haserror; + protobuf_c_boolean haserror; + char *errormessage; +}; +#define LINEARIZATION_OUTPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&linearization_output__descriptor) \ + , 0,NULL, 0, 0, NULL } + + +/* LinearizationOutput methods */ +void linearization_output__init + (LinearizationOutput *message); +size_t linearization_output__get_packed_size + (const LinearizationOutput *message); +size_t linearization_output__pack + (const LinearizationOutput *message, + uint8_t *out); +size_t linearization_output__pack_to_buffer + (const LinearizationOutput *message, + ProtobufCBuffer *buffer); +LinearizationOutput * + linearization_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void linearization_output__free_unpacked + (LinearizationOutput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*LinearizationOutput_Closure) + (const LinearizationOutput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor linearization_output__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_LinearizationOutput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.c new file mode 100644 index 000000000..d6d4117b7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.c @@ -0,0 +1,53 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LiquidType.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "LiquidType.pb-c.h" +static const ProtobufCEnumValue liquid_type__enum_values_by_number[10] = +{ + { "Cyan", "LIQUID_TYPE__Cyan", 0 }, + { "Magenta", "LIQUID_TYPE__Magenta", 1 }, + { "Yellow", "LIQUID_TYPE__Yellow", 2 }, + { "Black", "LIQUID_TYPE__Black", 3 }, + { "TransparentInk", "LIQUID_TYPE__TransparentInk", 4 }, + { "Lubricant", "LIQUID_TYPE__Lubricant", 5 }, + { "Cleaner", "LIQUID_TYPE__Cleaner", 6 }, + { "LightCyan", "LIQUID_TYPE__LightCyan", 7 }, + { "LightMagenta", "LIQUID_TYPE__LightMagenta", 8 }, + { "LightYellow", "LIQUID_TYPE__LightYellow", 9 }, +}; +static const ProtobufCIntRange liquid_type__value_ranges[] = { +{0, 0},{0, 10} +}; +static const ProtobufCEnumValueIndex liquid_type__enum_values_by_name[10] = +{ + { "Black", 3 }, + { "Cleaner", 6 }, + { "Cyan", 0 }, + { "LightCyan", 7 }, + { "LightMagenta", 8 }, + { "LightYellow", 9 }, + { "Lubricant", 5 }, + { "Magenta", 1 }, + { "TransparentInk", 4 }, + { "Yellow", 2 }, +}; +const ProtobufCEnumDescriptor liquid_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "LiquidType", + "LiquidType", + "LiquidType", + "", + 10, + liquid_type__enum_values_by_number, + 10, + liquid_type__enum_values_by_name, + 1, + liquid_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.h new file mode 100644 index 000000000..eba52c4a7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidType.pb-c.h @@ -0,0 +1,51 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LiquidType.proto */ + +#ifndef PROTOBUF_C_LiquidType_2eproto__INCLUDED +#define PROTOBUF_C_LiquidType_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + + + +/* --- enums --- */ + +typedef enum _LiquidType { + LIQUID_TYPE__Cyan = 0, + LIQUID_TYPE__Magenta = 1, + LIQUID_TYPE__Yellow = 2, + LIQUID_TYPE__Black = 3, + LIQUID_TYPE__TransparentInk = 4, + LIQUID_TYPE__Lubricant = 5, + LIQUID_TYPE__Cleaner = 6, + LIQUID_TYPE__LightCyan = 7, + LIQUID_TYPE__LightMagenta = 8, + LIQUID_TYPE__LightYellow = 9 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(LIQUID_TYPE) +} LiquidType; + +/* --- messages --- */ + +/* --- per-message closures --- */ + + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor liquid_type__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_LiquidType_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.c new file mode 100644 index 000000000..118d5b92d --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.c @@ -0,0 +1,105 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LiquidVolume.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "LiquidVolume.pb-c.h" +void liquid_volume__init + (LiquidVolume *message) +{ + static const LiquidVolume init_value = LIQUID_VOLUME__INIT; + *message = init_value; +} +size_t liquid_volume__get_packed_size + (const LiquidVolume *message) +{ + assert(message->base.descriptor == &liquid_volume__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t liquid_volume__pack + (const LiquidVolume *message, + uint8_t *out) +{ + assert(message->base.descriptor == &liquid_volume__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t liquid_volume__pack_to_buffer + (const LiquidVolume *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &liquid_volume__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +LiquidVolume * + liquid_volume__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (LiquidVolume *) + protobuf_c_message_unpack (&liquid_volume__descriptor, + allocator, len, data); +} +void liquid_volume__free_unpacked + (LiquidVolume *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &liquid_volume__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor liquid_volume__field_descriptors[2] = +{ + { + "LiquidType", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(LiquidVolume, has_liquidtype), + offsetof(LiquidVolume, liquidtype), + &liquid_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Volume", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(LiquidVolume, has_volume), + offsetof(LiquidVolume, volume), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned liquid_volume__field_indices_by_name[] = { + 0, /* field[0] = LiquidType */ + 1, /* field[1] = Volume */ +}; +static const ProtobufCIntRange liquid_volume__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor liquid_volume__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "LiquidVolume", + "LiquidVolume", + "LiquidVolume", + "", + sizeof(LiquidVolume), + 2, + liquid_volume__field_descriptors, + liquid_volume__field_indices_by_name, + 1, liquid_volume__number_ranges, + (ProtobufCMessageInit) liquid_volume__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.h new file mode 100644 index 000000000..82ee62dfb --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/LiquidVolume.pb-c.h @@ -0,0 +1,75 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: LiquidVolume.proto */ + +#ifndef PROTOBUF_C_LiquidVolume_2eproto__INCLUDED +#define PROTOBUF_C_LiquidVolume_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "LiquidType.pb-c.h" + +typedef struct _LiquidVolume LiquidVolume; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _LiquidVolume +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidtype; + LiquidType liquidtype; + protobuf_c_boolean has_volume; + double volume; +}; +#define LIQUID_VOLUME__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&liquid_volume__descriptor) \ + , 0, LIQUID_TYPE__Cyan, 0, 0 } + + +/* LiquidVolume methods */ +void liquid_volume__init + (LiquidVolume *message); +size_t liquid_volume__get_packed_size + (const LiquidVolume *message); +size_t liquid_volume__pack + (const LiquidVolume *message, + uint8_t *out); +size_t liquid_volume__pack_to_buffer + (const LiquidVolume *message, + ProtobufCBuffer *buffer); +LiquidVolume * + liquid_volume__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void liquid_volume__free_unpacked + (LiquidVolume *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*LiquidVolume_Closure) + (const LiquidVolume *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor liquid_volume__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_LiquidVolume_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.c new file mode 100644 index 000000000..115985567 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.c @@ -0,0 +1,196 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutOfGamutInput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "OutOfGamutInput.pb-c.h" +void out_of_gamut_input__init + (OutOfGamutInput *message) +{ + static const OutOfGamutInput init_value = OUT_OF_GAMUT_INPUT__INIT; + *message = init_value; +} +size_t out_of_gamut_input__get_packed_size + (const OutOfGamutInput *message) +{ + assert(message->base.descriptor == &out_of_gamut_input__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t out_of_gamut_input__pack + (const OutOfGamutInput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &out_of_gamut_input__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t out_of_gamut_input__pack_to_buffer + (const OutOfGamutInput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &out_of_gamut_input__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +OutOfGamutInput * + out_of_gamut_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (OutOfGamutInput *) + protobuf_c_message_unpack (&out_of_gamut_input__descriptor, + allocator, len, data); +} +void out_of_gamut_input__free_unpacked + (OutOfGamutInput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &out_of_gamut_input__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor out_of_gamut_input__field_descriptors[9] = +{ + { + "ThreadL", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutOfGamutInput, has_threadl), + offsetof(OutOfGamutInput, threadl), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadA", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutOfGamutInput, has_threada), + offsetof(OutOfGamutInput, threada), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadB", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutOfGamutInput, has_threadb), + offsetof(OutOfGamutInput, threadb), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ColorSpace", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(OutOfGamutInput, has_colorspace), + offsetof(OutOfGamutInput, colorspace), + &color_space__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InputCoordinates", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(OutOfGamutInput, inputcoordinates), + &input_coordinates__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ForwardData", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(OutOfGamutInput, has_forwarddata), + offsetof(OutOfGamutInput, forwarddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ProcessRanges", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(OutOfGamutInput, n_processranges), + offsetof(OutOfGamutInput, processranges), + &process_range__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "GbdData", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(OutOfGamutInput, has_gbddata), + offsetof(OutOfGamutInput, gbddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "LubData", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(OutOfGamutInput, has_lubdata), + offsetof(OutOfGamutInput, lubdata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned out_of_gamut_input__field_indices_by_name[] = { + 3, /* field[3] = ColorSpace */ + 5, /* field[5] = ForwardData */ + 7, /* field[7] = GbdData */ + 4, /* field[4] = InputCoordinates */ + 8, /* field[8] = LubData */ + 6, /* field[6] = ProcessRanges */ + 1, /* field[1] = ThreadA */ + 2, /* field[2] = ThreadB */ + 0, /* field[0] = ThreadL */ +}; +static const ProtobufCIntRange out_of_gamut_input__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 9 } +}; +const ProtobufCMessageDescriptor out_of_gamut_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "OutOfGamutInput", + "OutOfGamutInput", + "OutOfGamutInput", + "", + sizeof(OutOfGamutInput), + 9, + out_of_gamut_input__field_descriptors, + out_of_gamut_input__field_indices_by_name, + 1, out_of_gamut_input__number_ranges, + (ProtobufCMessageInit) out_of_gamut_input__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.h new file mode 100644 index 000000000..4255f3b82 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutInput.pb-c.h @@ -0,0 +1,90 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutOfGamutInput.proto */ + +#ifndef PROTOBUF_C_OutOfGamutInput_2eproto__INCLUDED +#define PROTOBUF_C_OutOfGamutInput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "InputCoordinates.pb-c.h" +#include "ColorSpace.pb-c.h" +#include "ProcessRange.pb-c.h" + +typedef struct _OutOfGamutInput OutOfGamutInput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _OutOfGamutInput +{ + ProtobufCMessage base; + protobuf_c_boolean has_threadl; + double threadl; + protobuf_c_boolean has_threada; + double threada; + protobuf_c_boolean has_threadb; + double threadb; + protobuf_c_boolean has_colorspace; + ColorSpace colorspace; + InputCoordinates *inputcoordinates; + protobuf_c_boolean has_forwarddata; + ProtobufCBinaryData forwarddata; + size_t n_processranges; + ProcessRange **processranges; + protobuf_c_boolean has_gbddata; + ProtobufCBinaryData gbddata; + protobuf_c_boolean has_lubdata; + ProtobufCBinaryData lubdata; +}; +#define OUT_OF_GAMUT_INPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&out_of_gamut_input__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, COLOR_SPACE__Volume, NULL, 0, {0,NULL}, 0,NULL, 0, {0,NULL}, 0, {0,NULL} } + + +/* OutOfGamutInput methods */ +void out_of_gamut_input__init + (OutOfGamutInput *message); +size_t out_of_gamut_input__get_packed_size + (const OutOfGamutInput *message); +size_t out_of_gamut_input__pack + (const OutOfGamutInput *message, + uint8_t *out); +size_t out_of_gamut_input__pack_to_buffer + (const OutOfGamutInput *message, + ProtobufCBuffer *buffer); +OutOfGamutInput * + out_of_gamut_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void out_of_gamut_input__free_unpacked + (OutOfGamutInput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*OutOfGamutInput_Closure) + (const OutOfGamutInput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor out_of_gamut_input__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_OutOfGamutInput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.c new file mode 100644 index 000000000..fbd1854ab --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.c @@ -0,0 +1,118 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutOfGamutOutput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "OutOfGamutOutput.pb-c.h" +void out_of_gamut_output__init + (OutOfGamutOutput *message) +{ + static const OutOfGamutOutput init_value = OUT_OF_GAMUT_OUTPUT__INIT; + *message = init_value; +} +size_t out_of_gamut_output__get_packed_size + (const OutOfGamutOutput *message) +{ + assert(message->base.descriptor == &out_of_gamut_output__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t out_of_gamut_output__pack + (const OutOfGamutOutput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &out_of_gamut_output__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t out_of_gamut_output__pack_to_buffer + (const OutOfGamutOutput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &out_of_gamut_output__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +OutOfGamutOutput * + out_of_gamut_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (OutOfGamutOutput *) + protobuf_c_message_unpack (&out_of_gamut_output__descriptor, + allocator, len, data); +} +void out_of_gamut_output__free_unpacked + (OutOfGamutOutput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &out_of_gamut_output__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor out_of_gamut_output__field_descriptors[3] = +{ + { + "OutOfGamut", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(OutOfGamutOutput, has_outofgamut), + offsetof(OutOfGamutOutput, outofgamut), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "HasError", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(OutOfGamutOutput, has_haserror), + offsetof(OutOfGamutOutput, haserror), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ErrorMessage", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(OutOfGamutOutput, errormessage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned out_of_gamut_output__field_indices_by_name[] = { + 2, /* field[2] = ErrorMessage */ + 1, /* field[1] = HasError */ + 0, /* field[0] = OutOfGamut */ +}; +static const ProtobufCIntRange out_of_gamut_output__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor out_of_gamut_output__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "OutOfGamutOutput", + "OutOfGamutOutput", + "OutOfGamutOutput", + "", + sizeof(OutOfGamutOutput), + 3, + out_of_gamut_output__field_descriptors, + out_of_gamut_output__field_indices_by_name, + 1, out_of_gamut_output__number_ranges, + (ProtobufCMessageInit) out_of_gamut_output__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.h new file mode 100644 index 000000000..21bfa08ca --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutOfGamutOutput.pb-c.h @@ -0,0 +1,75 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutOfGamutOutput.proto */ + +#ifndef PROTOBUF_C_OutOfGamutOutput_2eproto__INCLUDED +#define PROTOBUF_C_OutOfGamutOutput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _OutOfGamutOutput OutOfGamutOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _OutOfGamutOutput +{ + ProtobufCMessage base; + protobuf_c_boolean has_outofgamut; + protobuf_c_boolean outofgamut; + protobuf_c_boolean has_haserror; + protobuf_c_boolean haserror; + char *errormessage; +}; +#define OUT_OF_GAMUT_OUTPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&out_of_gamut_output__descriptor) \ + , 0, 0, 0, 0, NULL } + + +/* OutOfGamutOutput methods */ +void out_of_gamut_output__init + (OutOfGamutOutput *message); +size_t out_of_gamut_output__get_packed_size + (const OutOfGamutOutput *message); +size_t out_of_gamut_output__pack + (const OutOfGamutOutput *message, + uint8_t *out); +size_t out_of_gamut_output__pack_to_buffer + (const OutOfGamutOutput *message, + ProtobufCBuffer *buffer); +OutOfGamutOutput * + out_of_gamut_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void out_of_gamut_output__free_unpacked + (OutOfGamutOutput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*OutOfGamutOutput_Closure) + (const OutOfGamutOutput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor out_of_gamut_output__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_OutOfGamutOutput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.c new file mode 100644 index 000000000..85aeb6ee5 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.c @@ -0,0 +1,183 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutputCoordinates.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "OutputCoordinates.pb-c.h" +void output_coordinates__init + (OutputCoordinates *message) +{ + static const OutputCoordinates init_value = OUTPUT_COORDINATES__INIT; + *message = init_value; +} +size_t output_coordinates__get_packed_size + (const OutputCoordinates *message) +{ + assert(message->base.descriptor == &output_coordinates__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t output_coordinates__pack + (const OutputCoordinates *message, + uint8_t *out) +{ + assert(message->base.descriptor == &output_coordinates__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t output_coordinates__pack_to_buffer + (const OutputCoordinates *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &output_coordinates__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +OutputCoordinates * + output_coordinates__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (OutputCoordinates *) + protobuf_c_message_unpack (&output_coordinates__descriptor, + allocator, len, data); +} +void output_coordinates__free_unpacked + (OutputCoordinates *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &output_coordinates__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor output_coordinates__field_descriptors[8] = +{ + { + "Red", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(OutputCoordinates, has_red), + offsetof(OutputCoordinates, red), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Green", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(OutputCoordinates, has_green), + offsetof(OutputCoordinates, green), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Blue", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(OutputCoordinates, has_blue), + offsetof(OutputCoordinates, blue), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "OutputLiquids", + 4, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(OutputCoordinates, n_outputliquids), + offsetof(OutputCoordinates, outputliquids), + &output_liquid__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ProcessParametersTableIndex", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(OutputCoordinates, has_processparameterstableindex), + offsetof(OutputCoordinates, processparameterstableindex), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "L", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutputCoordinates, has_l), + offsetof(OutputCoordinates, l), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "A", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutputCoordinates, has_a), + offsetof(OutputCoordinates, a), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "B", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutputCoordinates, has_b), + offsetof(OutputCoordinates, b), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned output_coordinates__field_indices_by_name[] = { + 6, /* field[6] = A */ + 7, /* field[7] = B */ + 2, /* field[2] = Blue */ + 1, /* field[1] = Green */ + 5, /* field[5] = L */ + 3, /* field[3] = OutputLiquids */ + 4, /* field[4] = ProcessParametersTableIndex */ + 0, /* field[0] = Red */ +}; +static const ProtobufCIntRange output_coordinates__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 8 } +}; +const ProtobufCMessageDescriptor output_coordinates__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "OutputCoordinates", + "OutputCoordinates", + "OutputCoordinates", + "", + sizeof(OutputCoordinates), + 8, + output_coordinates__field_descriptors, + output_coordinates__field_indices_by_name, + 1, output_coordinates__number_ranges, + (ProtobufCMessageInit) output_coordinates__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.h new file mode 100644 index 000000000..749ba3e7b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputCoordinates.pb-c.h @@ -0,0 +1,87 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutputCoordinates.proto */ + +#ifndef PROTOBUF_C_OutputCoordinates_2eproto__INCLUDED +#define PROTOBUF_C_OutputCoordinates_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "OutputLiquid.pb-c.h" + +typedef struct _OutputCoordinates OutputCoordinates; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _OutputCoordinates +{ + ProtobufCMessage base; + protobuf_c_boolean has_red; + int32_t red; + protobuf_c_boolean has_green; + int32_t green; + protobuf_c_boolean has_blue; + int32_t blue; + protobuf_c_boolean has_l; + double l; + protobuf_c_boolean has_a; + double a; + protobuf_c_boolean has_b; + double b; + size_t n_outputliquids; + OutputLiquid **outputliquids; + protobuf_c_boolean has_processparameterstableindex; + int32_t processparameterstableindex; +}; +#define OUTPUT_COORDINATES__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&output_coordinates__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,NULL, 0, 0 } + + +/* OutputCoordinates methods */ +void output_coordinates__init + (OutputCoordinates *message); +size_t output_coordinates__get_packed_size + (const OutputCoordinates *message); +size_t output_coordinates__pack + (const OutputCoordinates *message, + uint8_t *out); +size_t output_coordinates__pack_to_buffer + (const OutputCoordinates *message, + ProtobufCBuffer *buffer); +OutputCoordinates * + output_coordinates__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void output_coordinates__free_unpacked + (OutputCoordinates *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*OutputCoordinates_Closure) + (const OutputCoordinates *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor output_coordinates__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_OutputCoordinates_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.c new file mode 100644 index 000000000..73f47bb20 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.c @@ -0,0 +1,106 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutputLiquid.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "OutputLiquid.pb-c.h" +void output_liquid__init + (OutputLiquid *message) +{ + static const OutputLiquid init_value = OUTPUT_LIQUID__INIT; + *message = init_value; +} +size_t output_liquid__get_packed_size + (const OutputLiquid *message) +{ + assert(message->base.descriptor == &output_liquid__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t output_liquid__pack + (const OutputLiquid *message, + uint8_t *out) +{ + assert(message->base.descriptor == &output_liquid__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t output_liquid__pack_to_buffer + (const OutputLiquid *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &output_liquid__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +OutputLiquid * + output_liquid__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (OutputLiquid *) + protobuf_c_message_unpack (&output_liquid__descriptor, + allocator, len, data); +} +void output_liquid__free_unpacked + (OutputLiquid *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &output_liquid__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor output_liquid__field_descriptors[2] = +{ + { + "LiquidType", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(OutputLiquid, has_liquidtype), + offsetof(OutputLiquid, liquidtype), + &liquid_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Volume", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(OutputLiquid, has_volume), + offsetof(OutputLiquid, volume), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned output_liquid__field_indices_by_name[] = { + 0, /* field[0] = LiquidType */ + 1, /* field[1] = Volume */ +}; +static const ProtobufCIntRange output_liquid__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 4, 1 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor output_liquid__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "OutputLiquid", + "OutputLiquid", + "OutputLiquid", + "", + sizeof(OutputLiquid), + 2, + output_liquid__field_descriptors, + output_liquid__field_indices_by_name, + 2, output_liquid__number_ranges, + (ProtobufCMessageInit) output_liquid__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.h new file mode 100644 index 000000000..5401b8114 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/OutputLiquid.pb-c.h @@ -0,0 +1,75 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: OutputLiquid.proto */ + +#ifndef PROTOBUF_C_OutputLiquid_2eproto__INCLUDED +#define PROTOBUF_C_OutputLiquid_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "LiquidType.pb-c.h" + +typedef struct _OutputLiquid OutputLiquid; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _OutputLiquid +{ + ProtobufCMessage base; + protobuf_c_boolean has_liquidtype; + LiquidType liquidtype; + protobuf_c_boolean has_volume; + double volume; +}; +#define OUTPUT_LIQUID__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&output_liquid__descriptor) \ + , 0, LIQUID_TYPE__Cyan, 0, 0 } + + +/* OutputLiquid methods */ +void output_liquid__init + (OutputLiquid *message); +size_t output_liquid__get_packed_size + (const OutputLiquid *message); +size_t output_liquid__pack + (const OutputLiquid *message, + uint8_t *out); +size_t output_liquid__pack_to_buffer + (const OutputLiquid *message, + ProtobufCBuffer *buffer); +OutputLiquid * + output_liquid__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void output_liquid__free_unpacked + (OutputLiquid *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*OutputLiquid_Closure) + (const OutputLiquid *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor output_liquid__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_OutputLiquid_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.c new file mode 100644 index 000000000..f1caa25dc --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.c @@ -0,0 +1,105 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ProcessRange.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "ProcessRange.pb-c.h" +void process_range__init + (ProcessRange *message) +{ + static const ProcessRange init_value = PROCESS_RANGE__INIT; + *message = init_value; +} +size_t process_range__get_packed_size + (const ProcessRange *message) +{ + assert(message->base.descriptor == &process_range__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t process_range__pack + (const ProcessRange *message, + uint8_t *out) +{ + assert(message->base.descriptor == &process_range__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t process_range__pack_to_buffer + (const ProcessRange *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &process_range__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +ProcessRange * + process_range__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (ProcessRange *) + protobuf_c_message_unpack (&process_range__descriptor, + allocator, len, data); +} +void process_range__free_unpacked + (ProcessRange *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &process_range__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor process_range__field_descriptors[2] = +{ + { + "MinInkUptake", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ProcessRange, has_mininkuptake), + offsetof(ProcessRange, mininkuptake), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "MaxInkUptake", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(ProcessRange, has_maxinkuptake), + offsetof(ProcessRange, maxinkuptake), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned process_range__field_indices_by_name[] = { + 1, /* field[1] = MaxInkUptake */ + 0, /* field[0] = MinInkUptake */ +}; +static const ProtobufCIntRange process_range__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor process_range__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "ProcessRange", + "ProcessRange", + "ProcessRange", + "", + sizeof(ProcessRange), + 2, + process_range__field_descriptors, + process_range__field_indices_by_name, + 1, process_range__number_ranges, + (ProtobufCMessageInit) process_range__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.h new file mode 100644 index 000000000..c7eedfd8a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/ProcessRange.pb-c.h @@ -0,0 +1,74 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: ProcessRange.proto */ + +#ifndef PROTOBUF_C_ProcessRange_2eproto__INCLUDED +#define PROTOBUF_C_ProcessRange_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _ProcessRange ProcessRange; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _ProcessRange +{ + ProtobufCMessage base; + protobuf_c_boolean has_mininkuptake; + double mininkuptake; + protobuf_c_boolean has_maxinkuptake; + double maxinkuptake; +}; +#define PROCESS_RANGE__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&process_range__descriptor) \ + , 0, 0, 0, 0 } + + +/* ProcessRange methods */ +void process_range__init + (ProcessRange *message); +size_t process_range__get_packed_size + (const ProcessRange *message); +size_t process_range__pack + (const ProcessRange *message, + uint8_t *out); +size_t process_range__pack_to_buffer + (const ProcessRange *message, + ProtobufCBuffer *buffer); +ProcessRange * + process_range__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void process_range__free_unpacked + (ProcessRange *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*ProcessRange_Closure) + (const ProcessRange *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor process_range__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_ProcessRange_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.c new file mode 100644 index 000000000..1d4e52e7f --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.c @@ -0,0 +1,209 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: RecommendedProcessTableInput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "RecommendedProcessTableInput.pb-c.h" +void recommended_process_table_input__init + (RecommendedProcessTableInput *message) +{ + static const RecommendedProcessTableInput init_value = RECOMMENDED_PROCESS_TABLE_INPUT__INIT; + *message = init_value; +} +size_t recommended_process_table_input__get_packed_size + (const RecommendedProcessTableInput *message) +{ + assert(message->base.descriptor == &recommended_process_table_input__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t recommended_process_table_input__pack + (const RecommendedProcessTableInput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &recommended_process_table_input__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t recommended_process_table_input__pack_to_buffer + (const RecommendedProcessTableInput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &recommended_process_table_input__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RecommendedProcessTableInput * + recommended_process_table_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RecommendedProcessTableInput *) + protobuf_c_message_unpack (&recommended_process_table_input__descriptor, + allocator, len, data); +} +void recommended_process_table_input__free_unpacked + (RecommendedProcessTableInput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &recommended_process_table_input__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor recommended_process_table_input__field_descriptors[10] = +{ + { + "ThreadL", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(RecommendedProcessTableInput, has_threadl), + offsetof(RecommendedProcessTableInput, threadl), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadA", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(RecommendedProcessTableInput, has_threada), + offsetof(RecommendedProcessTableInput, threada), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ThreadB", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(RecommendedProcessTableInput, has_threadb), + offsetof(RecommendedProcessTableInput, threadb), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ForwardData", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(RecommendedProcessTableInput, has_forwarddata), + offsetof(RecommendedProcessTableInput, forwarddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Stops", + 5, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RecommendedProcessTableInput, n_stops), + offsetof(RecommendedProcessTableInput, stops), + &gradient_input_stop__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InputLiquids", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RecommendedProcessTableInput, n_inputliquids), + offsetof(RecommendedProcessTableInput, inputliquids), + &input_liquid__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ProcessRanges", + 7, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RecommendedProcessTableInput, n_processranges), + offsetof(RecommendedProcessTableInput, processranges), + &process_range__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "UseLightInks", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(RecommendedProcessTableInput, has_uselightinks), + offsetof(RecommendedProcessTableInput, uselightinks), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "GbdData", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(RecommendedProcessTableInput, has_gbddata), + offsetof(RecommendedProcessTableInput, gbddata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "LubData", + 10, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + offsetof(RecommendedProcessTableInput, has_lubdata), + offsetof(RecommendedProcessTableInput, lubdata), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned recommended_process_table_input__field_indices_by_name[] = { + 3, /* field[3] = ForwardData */ + 8, /* field[8] = GbdData */ + 5, /* field[5] = InputLiquids */ + 9, /* field[9] = LubData */ + 6, /* field[6] = ProcessRanges */ + 4, /* field[4] = Stops */ + 1, /* field[1] = ThreadA */ + 2, /* field[2] = ThreadB */ + 0, /* field[0] = ThreadL */ + 7, /* field[7] = UseLightInks */ +}; +static const ProtobufCIntRange recommended_process_table_input__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 10 } +}; +const ProtobufCMessageDescriptor recommended_process_table_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RecommendedProcessTableInput", + "RecommendedProcessTableInput", + "RecommendedProcessTableInput", + "", + sizeof(RecommendedProcessTableInput), + 10, + recommended_process_table_input__field_descriptors, + recommended_process_table_input__field_indices_by_name, + 1, recommended_process_table_input__number_ranges, + (ProtobufCMessageInit) recommended_process_table_input__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.h new file mode 100644 index 000000000..393b50ddc --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableInput.pb-c.h @@ -0,0 +1,93 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: RecommendedProcessTableInput.proto */ + +#ifndef PROTOBUF_C_RecommendedProcessTableInput_2eproto__INCLUDED +#define PROTOBUF_C_RecommendedProcessTableInput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "ProcessRange.pb-c.h" +#include "InputLiquid.pb-c.h" +#include "GradientInputStop.pb-c.h" + +typedef struct _RecommendedProcessTableInput RecommendedProcessTableInput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _RecommendedProcessTableInput +{ + ProtobufCMessage base; + protobuf_c_boolean has_threadl; + double threadl; + protobuf_c_boolean has_threada; + double threada; + protobuf_c_boolean has_threadb; + double threadb; + protobuf_c_boolean has_forwarddata; + ProtobufCBinaryData forwarddata; + size_t n_stops; + GradientInputStop **stops; + size_t n_inputliquids; + InputLiquid **inputliquids; + size_t n_processranges; + ProcessRange **processranges; + protobuf_c_boolean has_uselightinks; + protobuf_c_boolean uselightinks; + protobuf_c_boolean has_gbddata; + ProtobufCBinaryData gbddata; + protobuf_c_boolean has_lubdata; + ProtobufCBinaryData lubdata; +}; +#define RECOMMENDED_PROCESS_TABLE_INPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&recommended_process_table_input__descriptor) \ + , 0, 0, 0, 0, 0, 0, 0, {0,NULL}, 0,NULL, 0,NULL, 0,NULL, 0, 0, 0, {0,NULL}, 0, {0,NULL} } + + +/* RecommendedProcessTableInput methods */ +void recommended_process_table_input__init + (RecommendedProcessTableInput *message); +size_t recommended_process_table_input__get_packed_size + (const RecommendedProcessTableInput *message); +size_t recommended_process_table_input__pack + (const RecommendedProcessTableInput *message, + uint8_t *out); +size_t recommended_process_table_input__pack_to_buffer + (const RecommendedProcessTableInput *message, + ProtobufCBuffer *buffer); +RecommendedProcessTableInput * + recommended_process_table_input__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void recommended_process_table_input__free_unpacked + (RecommendedProcessTableInput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*RecommendedProcessTableInput_Closure) + (const RecommendedProcessTableInput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor recommended_process_table_input__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_RecommendedProcessTableInput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.c new file mode 100644 index 000000000..0ef6e7f9e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.c @@ -0,0 +1,118 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: RecommendedProcessTableOutput.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "RecommendedProcessTableOutput.pb-c.h" +void recommended_process_table_output__init + (RecommendedProcessTableOutput *message) +{ + static const RecommendedProcessTableOutput init_value = RECOMMENDED_PROCESS_TABLE_OUTPUT__INIT; + *message = init_value; +} +size_t recommended_process_table_output__get_packed_size + (const RecommendedProcessTableOutput *message) +{ + assert(message->base.descriptor == &recommended_process_table_output__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t recommended_process_table_output__pack + (const RecommendedProcessTableOutput *message, + uint8_t *out) +{ + assert(message->base.descriptor == &recommended_process_table_output__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t recommended_process_table_output__pack_to_buffer + (const RecommendedProcessTableOutput *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &recommended_process_table_output__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RecommendedProcessTableOutput * + recommended_process_table_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RecommendedProcessTableOutput *) + protobuf_c_message_unpack (&recommended_process_table_output__descriptor, + allocator, len, data); +} +void recommended_process_table_output__free_unpacked + (RecommendedProcessTableOutput *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &recommended_process_table_output__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor recommended_process_table_output__field_descriptors[3] = +{ + { + "ProcessParametersTableIndex", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(RecommendedProcessTableOutput, has_processparameterstableindex), + offsetof(RecommendedProcessTableOutput, processparameterstableindex), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "HasError", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BOOL, + offsetof(RecommendedProcessTableOutput, has_haserror), + offsetof(RecommendedProcessTableOutput, haserror), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ErrorMessage", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(RecommendedProcessTableOutput, errormessage), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned recommended_process_table_output__field_indices_by_name[] = { + 2, /* field[2] = ErrorMessage */ + 1, /* field[1] = HasError */ + 0, /* field[0] = ProcessParametersTableIndex */ +}; +static const ProtobufCIntRange recommended_process_table_output__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor recommended_process_table_output__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RecommendedProcessTableOutput", + "RecommendedProcessTableOutput", + "RecommendedProcessTableOutput", + "", + sizeof(RecommendedProcessTableOutput), + 3, + recommended_process_table_output__field_descriptors, + recommended_process_table_output__field_indices_by_name, + 1, recommended_process_table_output__number_ranges, + (ProtobufCMessageInit) recommended_process_table_output__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.h new file mode 100644 index 000000000..c836b4074 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/PMR/ColorLab/RecommendedProcessTableOutput.pb-c.h @@ -0,0 +1,75 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: RecommendedProcessTableOutput.proto */ + +#ifndef PROTOBUF_C_RecommendedProcessTableOutput_2eproto__INCLUDED +#define PROTOBUF_C_RecommendedProcessTableOutput_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1003000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct _RecommendedProcessTableOutput RecommendedProcessTableOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _RecommendedProcessTableOutput +{ + ProtobufCMessage base; + protobuf_c_boolean has_processparameterstableindex; + int32_t processparameterstableindex; + protobuf_c_boolean has_haserror; + protobuf_c_boolean haserror; + char *errormessage; +}; +#define RECOMMENDED_PROCESS_TABLE_OUTPUT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&recommended_process_table_output__descriptor) \ + , 0, 0, 0, 0, NULL } + + +/* RecommendedProcessTableOutput methods */ +void recommended_process_table_output__init + (RecommendedProcessTableOutput *message); +size_t recommended_process_table_output__get_packed_size + (const RecommendedProcessTableOutput *message); +size_t recommended_process_table_output__pack + (const RecommendedProcessTableOutput *message, + uint8_t *out); +size_t recommended_process_table_output__pack_to_buffer + (const RecommendedProcessTableOutput *message, + ProtobufCBuffer *buffer); +RecommendedProcessTableOutput * + recommended_process_table_output__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void recommended_process_table_output__free_unpacked + (RecommendedProcessTableOutput *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*RecommendedProcessTableOutput_Closure) + (const RecommendedProcessTableOutput *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor recommended_process_table_output__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_RecommendedProcessTableOutput_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ReadMe.txt b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ReadMe.txt new file mode 100644 index 000000000..d9b08497d --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/ReadMe.txt @@ -0,0 +1,48 @@ +======================================================================== + DYNAMIC LINK LIBRARY : Tango.ColorLib Project Overview +======================================================================== + +AppWizard has created this Tango.ColorLib DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your Tango.ColorLib application. + + +Tango.ColorLib.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +Tango.ColorLib.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +Tango.ColorLib.cpp + This is the main DLL source file. + + When created, this DLL does not export any symbols. As a result, it + will not produce a .lib file when it is built. If you wish this project + to be a project dependency of some other project, you will either need to + add code to export some symbols from the DLL so that an export library + will be produced, or you can set the Ignore Input Library property to Yes + on the General propert page of the Linker folder in the project's Property + Pages dialog box. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named Tango.ColorLib.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj new file mode 100644 index 000000000..49c4e83ce --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj @@ -0,0 +1,270 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059} + Win32Proj + TangoColorLib + 10.0.15063.0 + + + + DynamicLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + false + MultiByte + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)Build\ColorLib\Debug + $(ProjectDir);$(IncludePath) + true + + + true + + + false + $(SolutionDir)Build\ColorLib\Release + $(ProjectDir);$(IncludePath) + false + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;TANGOCOLORLIB_EXPORTS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + $(ProjectDir);$(ProjectDir)..\EigenDir;$(ProjectDir)..\EigenDir\Eigen;$(ProjectDir)Utils;$(ProjectDir)PMR\ColorLab;%(AdditionalIncludeDirectories) + + + + + Windows + true + + + "$(SolutionDir)Build\Utilities\Debug\proto-tc.exe" -i "$(SolutionDir)..\PMR\Messages" -o "$(ProjectDir)PMR" -l C -c "ColorLab" + + + + + + + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;TANGOCOLORLIB_EXPORTS;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;TANGOCOLORLIB_EXPORTS;%(PreprocessorDefinitions) + $(ProjectDir);$(ProjectDir)..\EigenDir;$(ProjectDir)..\EigenDir\Eigen;$(ProjectDir)Utils;$(ProjectDir)PMR\ColorLab;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + "$(SolutionDir)Build\Utilities\Debug\proto-tc.exe" -i "$(SolutionDir)..\PMR\Messages" -o "$(ProjectDir)PMR" -l C -c "ColorLab" + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;TANGOCOLORLIB_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj.filters b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj.filters new file mode 100644 index 000000000..aa2eda221 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Tango.ColorLib_v6.vcxproj.filters @@ -0,0 +1,318 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {0f952433-0681-4d49-9d48-c95684b56970} + + + {51e509a9-ffc2-4cf6-8206-247eff6fa786} + + + {ba97ff4c-dbb7-4557-921e-b19687f10882} + + + + + + + + Header Files + + + Header Files + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + Protobuf + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Header Files + + + Utils + + + Utils + + + PMR + + + Utils + + + Header Files + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + Utils + + + Utils + + + Utils + + + PMR + + + PMR + + + PMR + + + PMR + + + Utils + + + Utils + + + Utils + + + Utils + + + + + Source Files + + + Source Files + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + Protobuf + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + Utils + + + PMR + + + Utils + + + Source Files + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + PMR + + + Utils + + + Utils + + + Utils + + + PMR + + + PMR + + + PMR + + + PMR + + + Utils + + + Utils + + + Utils + + + Utils + + + \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.cpp new file mode 100644 index 000000000..85a82cf0c --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.cpp @@ -0,0 +1,114 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif +#include "CT_Header.h" +#include +#include +#include + +CT_Header::CT_Header() : + m_Version(NULL), m_ColorSpace(NULL), m_ConnectionSpace(NULL), m_TblSize(0), + m_DeviceManufacturer(NULL), m_Illuminant(0), m_nGamutRegions(0), m_GRegMaxLim(NULL), + m_GRegMinLim(NULL), m_CTLiquidFactors(NULL) +{ + +} + +CT_Header::~CT_Header() +{ + if (m_Version != NULL) + { + delete[]m_Version; + m_Version = NULL; + } + if (m_ColorSpace != NULL) + { + delete m_ColorSpace; + m_ColorSpace = NULL; + } + if (m_ConnectionSpace != NULL) + { + delete m_ConnectionSpace; + m_ConnectionSpace = NULL; + } + if (m_DeviceManufacturer != NULL) + { + delete m_DeviceManufacturer; + m_DeviceManufacturer = NULL; + } + if (m_GRegMaxLim != NULL) + { + delete[]m_GRegMaxLim; + m_GRegMaxLim = NULL; + } + if (m_GRegMinLim != NULL) + { + delete[]m_GRegMinLim; + m_GRegMinLim = NULL; + } + if (m_CTLiquidFactors != NULL) + { + delete[]m_CTLiquidFactors; + m_CTLiquidFactors = NULL; + } +} + +void CT_Header::SetTableVersion(unsigned int *Version) +{ + if(m_Version == NULL) + m_Version = new unsigned int[3]; + for (int i = 0; i < 3; ++i) + m_Version[i] = Version[i]; +} + +C_RGB_XYZ_Lab CT_Header::GetIlluminant() { + return(m_Illuminant); +}; + +void CT_Header::SetColorSpace(char *ColorSPace) +{ + int nsize = sizeof(ColorSPace); + if(m_ColorSpace == NULL) + m_ColorSpace = new char[nsize+1]; + strncpy_s(m_ColorSpace, nsize +1,ColorSPace, nsize); +} + +void CT_Header :: SetConnectionSpace(char *ConnectionSpace) +{ + int nsize = sizeof(ConnectionSpace); + if(m_ConnectionSpace == NULL) + m_ConnectionSpace = new char[nsize+1]; + strncpy_s(m_ConnectionSpace, nsize+1,ConnectionSpace, nsize); +} + +void CT_Header::SetDeviceManufacturer(char *DeviceManufacturer) +{ + int nsize = sizeof(DeviceManufacturer); + if(m_DeviceManufacturer == NULL) + m_DeviceManufacturer = new char[nsize+1]; + strncpy_s(m_DeviceManufacturer, nsize + 1, DeviceManufacturer, nsize); +} + +void CT_Header::SetGamutRegionsMaxLimit(double *GRegMaxLim) +{ + if (m_GRegMaxLim == NULL) + m_GRegMaxLim = new double[m_nGamutRegions]; + for (int i = 0; i < m_nGamutRegions; ++i) + m_GRegMaxLim[i] = GRegMaxLim[i]; +} + +void CT_Header::SetGamutRegionsMinLimit(double *GRegMinLim) +{ + if (m_GRegMinLim == NULL) + m_GRegMinLim = new double[m_nGamutRegions]; + for (int i = 0; i < m_nGamutRegions; ++i) + m_GRegMinLim[i] = GRegMinLim[i]; +} + +void CT_Header::SetLiquidFactors(double *LF) +{ + if (m_CTLiquidFactors == NULL) + m_CTLiquidFactors = new double[4]; + for (int i = 0; i < 4; ++i) + m_CTLiquidFactors[i] = LF[i]; +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.h new file mode 100644 index 000000000..3872b55e6 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CT_Header.h @@ -0,0 +1,63 @@ +#ifndef _CT_HEADER_H_ +#define _CT_HEADER_H_ +#pragma once +#include +#include "C_RGB_XYZ_Lab.h" + +class CT_Header { +public: + CT_Header(); + ~CT_Header(); + unsigned int GetTableSize() { return(m_TblSize); }; + void SetTableSize(unsigned int TableSize) { + m_TblSize = TableSize; + }; + unsigned int *GetTableVersion() { return(m_Version); }; + void SetTableVersion(unsigned int *version); + char* GetColorSpace() { + return(m_ColorSpace); + }; + void SetColorSpace(char *ColorSPace); + char* GetConnectionSpace() { + return(m_ConnectionSpace); + }; + void SetConnectionSpace(char *ConnectionSpace); + + char* GetDeviceManufacturer() { + return(m_DeviceManufacturer); + }; + void SetDeviceManufacturer(char *DeviceManufacturer); + + C_RGB_XYZ_Lab GetIlluminant(); + + void SetIlluminant(C_RGB_XYZ_Lab Illuminant) { + m_Illuminant = Illuminant; + }; + + void SetNGamutRegions(unsigned char GamutRegions) { + m_nGamutRegions = GamutRegions; + }; + unsigned char GetNGamutRegions() { + return(m_nGamutRegions); + }; + void SetGamutRegionsMaxLimit(double *GRegMaxLim); + void SetGamutRegionsMinLimit(double *GRegMinLim); + void SetLiquidFactors(double *LF); + double *GetGamutRegionsMaxLimit() { return(m_GRegMaxLim); }; + double *GetGamutRegionsMinLimit() { return(m_GRegMinLim); }; + double *GetLiquidFactors() { return (m_CTLiquidFactors); }; + +private: + unsigned int *m_Version; + char *m_ColorSpace; + char * m_ConnectionSpace; + char * m_DeviceManufacturer; + C_RGB_XYZ_Lab m_Illuminant; + unsigned char m_nGamutRegions ; + double *m_GRegMaxLim; + double *m_GRegMinLim; + double *m_CTLiquidFactors; + unsigned int m_TblSize; +}; + +#endif \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.cpp new file mode 100644 index 000000000..d14619ff7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.cpp @@ -0,0 +1,188 @@ +#include "C_RGB_XYZ_Lab.h" +//#include +//#include // std::min, max + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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*/ + + +// Default Constructor ... C_RGB_XYZ_Lab = (0, 0, 0) +C_RGB_XYZ_Lab::C_RGB_XYZ_Lab(void) : + m_x(0.0), + m_y(0.0), + m_z(0.0) +{ +} + + +// Constructor from a constant ... C_RGB_XYZ_Lab = (val, val, val) +C_RGB_XYZ_Lab::C_RGB_XYZ_Lab(const double &val) : + m_x(val), + m_y(val), + m_z(val) +{ +} + + +// Constructor from 3 values ... C_RGB_XYZ_Lab = (val1, val2, val3) +C_RGB_XYZ_Lab::C_RGB_XYZ_Lab(const double &val1, const double &val2, const double &val3) : + m_x(val1), + m_y(val2), + m_z(val3) +{ +} + + +// Constructor from 3 values in a vector +C_RGB_XYZ_Lab::C_RGB_XYZ_Lab(const VectorXd &Val): +m_x(Val(0)), +m_y(Val(1)), +m_z(Val(2)) +{ + +} + + +// Copy constructor +C_RGB_XYZ_Lab::C_RGB_XYZ_Lab(const C_RGB_XYZ_Lab &rhs) : + m_x(rhs.m_x), + m_y(rhs.m_y), + m_z(rhs.m_z) +{ +} + +//Destructor +C_RGB_XYZ_Lab::~C_RGB_XYZ_Lab() +{ +} + + + +// Get a vector from the RGB/XYZ/Lab +VectorXd C_RGB_XYZ_Lab::Get() const +{ + VectorXd vec(3); + vec(0) = m_x; + vec(1) = m_y; + vec(2) = m_z; + return vec; +} + + +// Set RGB/XYZ/Lab from a vector +void C_RGB_XYZ_Lab::Set(const VectorXd &rhs) +{ + m_x = rhs(0); + m_y = rhs(1); + m_z = rhs(2); +} + + +// Set RGB/XYZ/Lab from three values +void C_RGB_XYZ_Lab::Set(const double &val1, const double &val2, const double &val3) +{ + m_x = val1; + m_y = val2; + m_z = val3; +} + + +// Clip the individual components to the range [low,high] +void C_RGB_XYZ_Lab::Clamp(C_RGB_XYZ_Lab &low, C_RGB_XYZ_Lab &high) +{ + m_x = std::min(std::max(m_x, low.Get_x()), high.Get_x()); + m_y = std::min(std::max(m_y, low.Get_y()), high.Get_y()); + m_z = std::min(std::max(m_z, low.Get_z()), high.Get_z());; +} + +C_RGB_XYZ_Lab C_RGB_XYZ_Lab::labuint16_to_labdouble(uint16_t * LabShort) +{ + double tmp[3]; + C_RGB_XYZ_Lab out; + tmp[0] = (double(LabShort[0]) * (100.0 + (25500.0 / 65280.0))) / 65535.0; + tmp[1] = ((double(LabShort[1]) * (255.0 + (255.0 / 256.0))) / 65535.0) - 128.0; + tmp[2] = ((double(LabShort[2]) * (255.0 + (255.0 / 256.0))) / 65535.0) - 128.0; + out.Set(tmp[0], tmp[1], tmp[2]); + return (out); +} + +C_RGB_XYZ_Lab C_RGB_XYZ_Lab::labdouble_to_labuint16(double* LabDouble) +{ +//Do the scale and offset and cast to uint16 + C_RGB_XYZ_Lab out; + double tmp[3]; +tmp[0]= round(65535 * LabDouble[0] / (100 + (25500 / 65280))); +tmp[1] = round(65535 * ((128 + LabDouble[1]) / (255 + (255 / 256)))); +tmp[2] = round(65535 * ((128 + LabDouble[2]) / (255 + (255 / 256)))); +for (int i = 0; i < 3; ++i) + tmp[0] = std::min(std::max(tmp[0], 0.0), 65535.0); +out.Set((uint16_t)tmp[0], (uint16_t)tmp[1], (uint16_t)tmp[2]); +return (out); +} + +// add to existing value (rgb += rhs) +C_RGB_XYZ_Lab &C_RGB_XYZ_Lab::operator += (C_RGB_XYZ_Lab &rhs) +{ + m_x += rhs.m_x; + m_y += rhs.m_y; + m_z += rhs.m_z; + return (*this); +} + + +// subtract from existing value (lab -= rhs) +C_RGB_XYZ_Lab &C_RGB_XYZ_Lab::operator -= (C_RGB_XYZ_Lab &rhs) +{ + m_x -= rhs.m_x; + m_y -= rhs.m_y; + m_z -= rhs.m_z; + return (*this); +} + + +// multiply 2 RGB's (lab *= rhs) +C_RGB_XYZ_Lab &C_RGB_XYZ_Lab::operator *= (C_RGB_XYZ_Lab &rhs) +{ + m_x *= rhs.m_x; + m_y *= rhs.m_y; + m_z *= rhs.m_z; + return (*this); +} + + +// Divide 2 RGB's (lab /= rhs) +C_RGB_XYZ_Lab &C_RGB_XYZ_Lab::operator /= (C_RGB_XYZ_Lab &rhs) +{ + m_x /= rhs.m_x; + m_y /= rhs.m_y; + m_z /= rhs.m_z; + return (*this); +} + +// isequal (lhs == rhs) +bool operator == (C_RGB_XYZ_Lab &lhs, C_RGB_XYZ_Lab &rhs) +{ + return ((lhs.Get_x() == rhs.Get_x()) && (lhs.Get_y() == rhs.Get_y()) && (lhs.Get_z() == rhs.Get_z())); +} + + + +// isnotequal (lhs != rhs) +bool operator != (C_RGB_XYZ_Lab &lhs, C_RGB_XYZ_Lab &rhs) +{ + return (!operator == (lhs, rhs)); +} + + + + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.h new file mode 100644 index 000000000..a82ba7d5b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/C_RGB_XYZ_Lab.h @@ -0,0 +1,48 @@ +#ifndef __CRGB_XYZ_Lab_H__ +#define __CRGB_XYZ_Lab_H__ + +#include "Dense" +using Eigen::MatrixXd; +using Eigen::VectorXd; + +#define nRGB (3) +#define nXYZ (3) +#define nLab (3) + +class C_RGB_XYZ_Lab + { + public: + + C_RGB_XYZ_Lab(void); // (0,0,0) + ~C_RGB_XYZ_Lab(void); + C_RGB_XYZ_Lab(const double &val); // (x,x,x) + C_RGB_XYZ_Lab(const double &rval, const double &gval, const double &bval); // (X,Y,Z) + C_RGB_XYZ_Lab(const VectorXd &xyzval); + C_RGB_XYZ_Lab(const C_RGB_XYZ_Lab &rhs); + + // Get/Set to/from a vector + VectorXd Get() const; + void Set(const VectorXd &rhs); + void Set (const double &rval, const double &gval, const double &bval); + double Get_x() { return (m_x); }; + double Get_y() { return (m_y); }; + double Get_z() { return (m_z); }; + // Clamp the elements to the range [low, high] + void Clamp (C_RGB_XYZ_Lab &low, C_RGB_XYZ_Lab &high); + C_RGB_XYZ_Lab labuint16_to_labdouble(uint16_t *LabShort); + C_RGB_XYZ_Lab labdouble_to_labuint16(double* LabDouble); + C_RGB_XYZ_Lab &operator += (C_RGB_XYZ_Lab &rhs); + C_RGB_XYZ_Lab &operator -= (C_RGB_XYZ_Lab &rhs); + C_RGB_XYZ_Lab &operator *= (C_RGB_XYZ_Lab &rhs); + C_RGB_XYZ_Lab &operator /= (C_RGB_XYZ_Lab &rhs); + + + private: + + double m_x; + double m_y; + double m_z; + }; + + +#endif // __C_RGB_XYZ_Lab__ \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.cpp new file mode 100644 index 000000000..6ec1bf24e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.cpp @@ -0,0 +1,90 @@ +#include "CalibData.h" + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 */ + +CalibData::CalibData(): m_npoints(0), m_XCoords(NULL), +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_LinearInterp(rhs.m_LinearInterp), m_InvLinearInterp(rhs.m_InvLinearInterp) +{ +} + +CalibData::~CalibData() +{ + if (m_XCoords != NULL) + { + delete[] m_XCoords; + m_XCoords = NULL; + } + if (m_YCoords != NULL) + { + 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) +{ + if(m_XCoords ==NULL) + { + m_XCoords = new double[m_npoints]; + //m_XCoords = DBG_NEW double[m_npoints]; + for (int i=0; iInit(m_XCoords, m_YCoords, m_npoints); + m_InvLinearInterp->Init(m_YCoords, m_XCoords, m_npoints); +} + +double CalibData::GetMaxXValue() +{ + int nsize = getSize(); + double *xval; + xval = getxCoords(); + double maxVal = 0; + maxVal = xval[nsize - 1]; + return(maxVal); +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.h new file mode 100644 index 000000000..716fd92f2 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/CalibData.h @@ -0,0 +1,33 @@ +#ifndef __CALIBDATA_H__ +#define __CALIBDATA_H__ +#include +#include +#include "Interp.h" + +class CalibData +{ + public: + CalibData(void) ; + CalibData (const CalibData &rhs); + ~CalibData(); + int getSize() { return(m_npoints); } + double GetMaxXValue(); + double *getxCoords() { return(m_XCoords); } + double *getyCoords() { return(m_YCoords); } + int getInkName() { return(m_InkName); } + void SetCalibName(int InkName) { m_InkName = InkName; } + void SetCalibCurveSize(int npoints) { m_npoints = npoints; } + 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; + double *m_YCoords; + int m_InkName; + double m_maxNlPerCM; +}; +#endif // __CALIBDATA_H__ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.cpp new file mode 100644 index 000000000..cc53b0473 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.cpp @@ -0,0 +1,1254 @@ +#include "ColorConvert.h" +#include +#include + +using namespace std; +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 */ + +//define constants for RGB conversion +const static double CHROMATICITIES[nRGB*nXYZ] = { 0.0, 0.6400, 0.3300, 0.0, 0.3000, 0.6000, 0.0, 0.1500, 0.0600 }; +static double m_Chromaticities[nRGB*nXYZ] = { 0.0, 0.6400, 0.3300, 0.0, 0.3000, 0.6000, 0.0, 0.1500, 0.0600 }; +static double White2DegreeD50[nXYZ] = { 63190.0 / 65536, 1.0, 54061.0 / 65536 }; +static double White2DegreeD65[nXYZ] = { 0.9505, 1.00, 1.0888 }; + +static const double kCIELabDelta = (6.0 / 29.0); // = 0.20689 +static const double kCIELabEpsilon = (216.0 / 24389.0); // = 0.008856 (= kCIELabDelta^3) +static const double kCIELabKappa = (8.0 / kCIELabEpsilon); // = 903.3 +static const double kCIELabScale = (kCIELabKappa / 116.0); // = 7.787 + +static const double kCIELabOffset = (16.0 / 116.0); // = 16/116 +static const double kCIELabKappaEps = (kCIELabEpsilon * kCIELabKappa); +static const double kCIELab3Delta2 = (3.0 * kCIELabDelta * kCIELabDelta); +static const double kCIELabOneThird = (1.0 / 3.0); // = 1/3 +static const C_RGB_XYZ_Lab ZeroVal(0.0, 0.0, 0.0); + +static bool m_MatricesInitialized = false; +static MatrixXd m_RGBtoXYZMatrix = MatrixXd(nXYZ, nRGB); +static MatrixXd m_XYZtoRGBMatrix = MatrixXd(nRGB, nXYZ); +C_RGB_XYZ_Lab LowLab(0.0, -128.0, -128.0); +C_RGB_XYZ_Lab HighLab(100.0, 127.0, 127.0); + +// Default Constructor (defaults to reference white of D50, 2 degree) +ColorConvert::ColorConvert (void) +{ + m_ReferenceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + m_SourceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + m_InvReferenceWhite.Set ((1.0/m_ReferenceWhite.Get_x()), (1.0/m_ReferenceWhite.Get_y()), (1.0/m_ReferenceWhite.Get_z())); + m_BradfordMatrix << 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0; + Initciecam02_parameters(); + InitJab_parameters(); +} + +ColorConvert::ColorConvert(C_RGB_XYZ_Lab DestWhite, Illum D) +{ + switch (D) { + case D50: + { + m_SourceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_SourceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + m_ReferenceWhite =DestWhite; + m_InvReferenceWhite.Set((1.0 / m_ReferenceWhite.Get_x()), (1.0 / m_ReferenceWhite.Get_y()), (1.0 / m_ReferenceWhite.Get_z())); + CAT_BradfordMat(); + Initciecam02_parameters(); + InitJab_parameters(); +} +// Constructor for setting reference white +ColorConvert::ColorConvert(Illum D, C_RGB_XYZ_Lab SourceWhite) +{ + switch (D) { + case D50: + { + m_ReferenceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_ReferenceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + m_InvReferenceWhite.Set((1.0 / m_ReferenceWhite.Get_x()), (1.0 / m_ReferenceWhite.Get_y()), (1.0 / m_ReferenceWhite.Get_z())); + m_SourceWhite = SourceWhite; + CAT_BradfordMat(); + Initciecam02_parameters(); + InitJab_parameters(); +} + +ColorConvert::ColorConvert(Illum DDest, Illum DSource) +{ + switch (DDest) + { + case D50: + { + m_ReferenceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_ReferenceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + m_InvReferenceWhite.Set((1.0 / m_ReferenceWhite.Get_x()), (1.0 / m_ReferenceWhite.Get_y()), (1.0 / m_ReferenceWhite.Get_z())); + switch (DSource) { + case D50: + { + m_SourceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_SourceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + CAT_BradfordMat(); + Initciecam02_parameters(); + InitJab_parameters(); +} + +ColorConvert::ColorConvert(C_RGB_XYZ_Lab DDest, C_RGB_XYZ_Lab DSource) +{ + + m_ReferenceWhite= DDest; + m_InvReferenceWhite.Set((1.0 / m_ReferenceWhite.Get_x()), (1.0 / m_ReferenceWhite.Get_y()), (1.0 / m_ReferenceWhite.Get_z())); + m_SourceWhite = DSource; + CAT_BradfordMat(); + Initciecam02_parameters(); + InitJab_parameters(); +} + +ColorConvert::ColorConvert(Illum DDest, Illum DSource, double Y_b, double L_A, SURROUND sur, CAM02CS CS) +{ + SetCAM02CS(CS); + SetSurround(sur); + switch (DDest) + { + case D50: + { + m_ReferenceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_ReferenceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + m_InvReferenceWhite.Set((1.0 / m_ReferenceWhite.Get_x()), (1.0 / m_ReferenceWhite.Get_y()), (1.0 / m_ReferenceWhite.Get_z())); + switch (DSource) { + case D50: + { + m_SourceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_SourceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + CAT_BradfordMat(); + //m_JabParams =new Jab_Params; + //m_ParamsCIECam02 = new CIECAM02Params; + InitCiecamParams(Y_b, L_A, sur, CS); +} + +// Copy constructor +ColorConvert::ColorConvert(const ColorConvert &rhs) : + m_ReferenceWhite(rhs.m_ReferenceWhite), + m_InvReferenceWhite(rhs.m_InvReferenceWhite), + m_SourceWhite(rhs.m_SourceWhite), + m_BradfordMatrix(rhs.m_BradfordMatrix), + m_JabParams(rhs.m_JabParams), + m_ParamsCIECam02(rhs.m_ParamsCIECam02), + m_CS(rhs.m_CS), + m_sur(rhs.m_sur) +{ +} + +// Assignment operator (cielab = rhs) +ColorConvert &ColorConvert::operator = (const ColorConvert &rhs) +{ + if ( this != &rhs ) { + m_ReferenceWhite = rhs.m_ReferenceWhite; + m_InvReferenceWhite = rhs.m_InvReferenceWhite; + m_SourceWhite = rhs.m_SourceWhite; + m_BradfordMatrix = rhs.m_BradfordMatrix; + m_JabParams = rhs.m_JabParams; + m_ParamsCIECam02 = rhs.m_ParamsCIECam02; + } + return ( *this ); +} + +ColorConvert::~ColorConvert() +{ + //delete m_JabParams; + //delete m_ParamsCIECam02; +} + + +// convert from XYZ to Lab using the standard CIE-Lab +// +// +// L* = 116 * f(Y/Yn) = 16 +// a* = 500 * (f(X/Xn) - f(Y/Yn)) +// b* = 200 * (f(Y/Yn) - f(Z/Zn)) +// +// where +// f(t) = t^(1/3) t < 0.008856 +// = 7.787 * t - 16/116 otherwise +// +C_RGB_XYZ_Lab ColorConvert::XYZToLab (C_RGB_XYZ_Lab xyzVal) +{ + double fX, fY, fZ; + + C_RGB_XYZ_Lab LabVal(ZeroVal); +// if ((xyzVal.Get_x() != 0.0) && (xyzVal.Get_y()) != 0.0 && (xyzVal.Get_z() != 0.0)) { + + C_RGB_XYZ_Lab xyzNorm (xyzVal); + xyzNorm *= m_InvReferenceWhite; + fX = (xyzNorm.Get_x() > kCIELabEpsilon) ? std::pow (xyzNorm.Get_x(), kCIELabOneThird) : + kCIELabScale * xyzNorm.Get_x() + kCIELabOffset; + fY = (xyzNorm.Get_y() > kCIELabEpsilon) ? std::pow (xyzNorm.Get_y(), kCIELabOneThird) : + kCIELabScale * xyzNorm.Get_y() + kCIELabOffset; + fZ = (xyzNorm.Get_z() > kCIELabEpsilon) ? std::pow (xyzNorm.Get_z(), kCIELabOneThird) : + kCIELabScale * xyzNorm.Get_z() + kCIELabOffset; + LabVal.Set (116.0 * fY - 16.0, 500.0 * (fX - fY), 200.0 * (fY - fZ)); +// } + + return ( LabVal ); +} + + +// Function to convert from Lab to XYZ using standard CIE-Lab + + C_RGB_XYZ_Lab ColorConvert::LabToXYZ ( C_RGB_XYZ_Lab labVal) +{ + double fX, fY, fZ; + C_RGB_XYZ_Lab xyzNorm; + + C_RGB_XYZ_Lab XyzVal = ZeroVal; +// if ((labVal.Get_x() != 0.0) && (labVal.Get_y()) != 0.0 && (labVal.Get_z()!=0.0)) { + + C_RGB_XYZ_Lab cieLab (labVal); + + fY = (cieLab.Get_x() + 16.0) / 116.0; + fX = fY + cieLab.Get_y() / 500.0; + fZ = fY - cieLab.Get_z() / 200.0; + + double X = ((fX > kCIELabDelta) ? fX * fX * fX : + kCIELab3Delta2 * (fX - kCIELabOffset)); + double Y = ((fY > kCIELabDelta) ? fY * fY * fY : + kCIELab3Delta2 * (fY - kCIELabOffset)); + double Z = ((fZ > kCIELabDelta) ? fZ * fZ * fZ : + kCIELab3Delta2 * (fZ - kCIELabOffset)); + xyzNorm.Set(X, Y, Z); + XyzVal = xyzNorm; + XyzVal *= m_ReferenceWhite; +// } + return ( XyzVal ); +} + +// Returns reference white +const C_RGB_XYZ_Lab &ColorConvert::GetReferenceWhite(void) const +{ + return (m_ReferenceWhite); +} + + +// Sets reference white + void ColorConvert::SetReferenceWhite(C_RGB_XYZ_Lab &refWhite) +{ + if ((refWhite.Get_x() > 0.0) && (refWhite.Get_y() > 0.0) && (refWhite.Get_z() > 0.0)) { + m_ReferenceWhite = refWhite; + m_InvReferenceWhite.Set((1.0 / refWhite.Get_x()),(1.0 / refWhite.Get_y()), (1.0 / refWhite.Get_z())); + } +} + + + void ColorConvert::SetReferenceWhite(Illum D) + { + switch (D) { + case D50: + { + m_ReferenceWhite.Set(White2DegreeD50[0], White2DegreeD50[1], White2DegreeD50[2]); + break; + } + case D65: + { + m_ReferenceWhite.Set(White2DegreeD65[0], White2DegreeD65[1], White2DegreeD65[2]); + break; + } + } + CAT_BradfordMat(); + } + + // inverse of a 3x3 matrix: A is the input matrix, B its inverse + void ColorConvert::InverseOfThreeByThreeMatrix(const MatrixXd& A, MatrixXd& B) + { + //det = a00(a22a11-a21a12)-a10(a22a01-a21a02)+a20(a12a01-a11a02) + // b00 = (a22a11-a21a12)/det + // b01 = -(a22a01-a21a02)/det + // b02 = (a12a01-a11a02)/det + // b10 = -(a22a10-a20a12)/det + // b11 = (a22a00-a20a02)/det + // b12 = -(a12a00-a10a02)/det + // b20 = (a21a10-a20a11)/det + // b21 = -(a21a00-a20a01)/det + // b22 = (a11a00-a10a01)/det + + double det = A(0, 0) * (A(2, 2)*A(1, 1) - A(2, 1)*A(1, 2)) - A(1, 0) * (A(2, 2)*A(0, 1) - A(2, 1)*A(0, 2)) + A(2, 0) * (A(1, 2)*A(0, 1) - A(1, 1)*A(0, 2)); + B(0, 0) = (A(2, 2) * A(1, 1) - A(2, 1) * A(1, 2)) / det; + B(0, 1) = -(A(2, 2) * A(0, 1) - A(2, 1) * A(0, 2)) / det; + B(0, 2) = (A(1, 2) * A(0, 1) - A(1, 1) * A(0, 2)) / det; + B(1, 0) = -(A(2, 2) * A(1, 0) - A(2, 0) * A(1, 2)) / det; + B(1, 1) = (A(2, 2) * A(0, 0) - A(2, 0) * A(0, 2)) / det; + B(1, 2) = -(A(1, 2) * A(0, 0) - A(1, 0) * A(0, 2)) / det; + B(2, 0) = (A(2, 1) * A(1, 0) - A(2, 0) * A(1, 1)) / det; + B(2, 1) = -(A(2, 1) * A(0, 0) - A(2, 0) * A(0, 1)) / det; + B(2, 2) = (A(1, 1) * A(0, 0) - A(1, 0) * A(0, 1)) / det; + } + + C_RGB_XYZ_Lab ColorConvert::RGBtoXYZ(C_RGB_XYZ_Lab& rgbVal) + { + if (!m_MatricesInitialized) InitializeConversionMatrices(); + VectorXd rgb; + VectorXd xyz(nXYZ); + rgb = rgbVal.Get(); + +//convert to linear RGB + for (int i = 0; i < nRGB; ++i) + rgb(i) = GammaExpand_sRGB(rgb(i)/255.0); + + xyz = m_RGBtoXYZMatrix * rgb; + return (C_RGB_XYZ_Lab(xyz)); + } + + C_RGB_XYZ_Lab ColorConvert::XYZtoRGB(C_RGB_XYZ_Lab& xyzVal) + { + if (!m_MatricesInitialized) InitializeConversionMatrices(); + VectorXd rgb(nRGB); + VectorXd xyz; + xyz = xyzVal.Get(); + //XYZ to Linear RGB + rgb = m_XYZtoRGBMatrix * xyz; + for (int i = 0; i < nRGB; ++i) + { + rgb(i) = GammaCompress_sRGB(rgb(i)); + rgb(i) = std::min(std::max(rgb(i), 0.0), 1.0); + rgb(i) *= 255; + } + return(C_RGB_XYZ_Lab(rgb)); + } + + C_RGB_XYZ_Lab ColorConvert::XYZtoRGBNoClip(C_RGB_XYZ_Lab& xyzVal) + { + if (!m_MatricesInitialized) InitializeConversionMatrices(); + VectorXd rgb(nRGB); + VectorXd xyz; + xyz = xyzVal.Get(); + //XYZ to Linear RGB + rgb = m_XYZtoRGBMatrix * xyz; + for (int i = 0; i < nRGB; ++i) + { + rgb(i) = GammaCompress_sRGB(rgb(i)); + // rgb(i) = std::min(std::max(rgb(i), 0.0), 1.0); + rgb(i) *= 255; + } + return(C_RGB_XYZ_Lab(rgb)); + } + + void ColorConvert::LabtoRGB(double*InLab, double *OutRGB) + { + C_RGB_XYZ_Lab DataLab; + DataLab.Set(InLab[0], InLab[1], InLab[2]); + C_RGB_XYZ_Lab DataRGB; + DataRGB =LabtoRGB(DataLab); + // double *RGB = new double[3]; + OutRGB[0] = DataRGB.Get_x(); + OutRGB[1] = DataRGB.Get_y(); + OutRGB[2] = DataRGB.Get_z(); + } + + void ColorConvert::LabtoRGBNoClip(double*InLab, double *OutRGB) + { + C_RGB_XYZ_Lab DataLab; + DataLab.Set(InLab[0], InLab[1], InLab[2]); + C_RGB_XYZ_Lab DataRGB; + DataRGB = LabtoRGBNoClip(DataLab); + // double *RGB = new double[3]; + OutRGB[0] = DataRGB.Get_x(); + OutRGB[1] = DataRGB.Get_y(); + OutRGB[2] = DataRGB.Get_z(); + } + + C_RGB_XYZ_Lab ColorConvert::LabtoRGB(C_RGB_XYZ_Lab& LabVal) + { + C_RGB_XYZ_Lab DataXYZ; + DataXYZ = LabToXYZ(LabVal); + C_RGB_XYZ_Lab DataRGB; + DataRGB = XYZtoRGB(DataXYZ); + return(DataRGB); + } + + C_RGB_XYZ_Lab ColorConvert::LabtoRGBNoClip(C_RGB_XYZ_Lab& LabVal) + { + C_RGB_XYZ_Lab DataXYZ; + DataXYZ = LabToXYZ(LabVal); + C_RGB_XYZ_Lab DataRGB; + DataRGB = XYZtoRGBNoClip(DataXYZ); + return(DataRGB); + } + + void ColorConvert::RGBtoLab(double*InRGB, double *OutLab) + { + C_RGB_XYZ_Lab DataRGB(InRGB[0], InRGB[1], InRGB[2]); + C_RGB_XYZ_Lab DataLab; + DataLab = RGBtoLab(DataRGB); + //double *LabOut = new double[3]; + OutLab[0] = DataLab.Get_x(); + OutLab[1] = DataLab.Get_y(); + OutLab[2] = DataLab.Get_z(); + } + + /*void ColorConvert::RGBtoLab(std::vector&InRGB, double *OutLab) + { + C_RGB_XYZ_Lab DataRGB(InRGB[0], InRGB[1], InRGB[2]); + C_RGB_XYZ_Lab DataLab; + DataLab = RGBtoLab(DataRGB); + //double *LabOut = new double[3]; + OutLab[0] = DataLab.Get_x(); + OutLab[1] = DataLab.Get_y(); + OutLab[2] = DataLab.Get_z(); + }*/ + + C_RGB_XYZ_Lab ColorConvert::RGBtoLab(C_RGB_XYZ_Lab& RGBVal) + { + C_RGB_XYZ_Lab DataXYZ; + //C_RGB_XYZ_Lab LowLab(0.0, -128.0, -128.0); + // C_RGB_XYZ_Lab HighLab(100.0, 127.0, 127.0); + + DataXYZ = RGBtoXYZ(RGBVal); + C_RGB_XYZ_Lab DataLab; + DataLab = XYZToLab(DataXYZ); +// DataLab.Clamp(LowLab, HighLab); + return(DataLab); + } + + + void ColorConvert::ChangeWP(double *LabIn, double *LabOut, C_RGB_XYZ_Lab SourceWhite, C_RGB_XYZ_Lab DestWhite) + { + SetReferenceWhite(SourceWhite); + C_RGB_XYZ_Lab Lab; + Lab.Set(LabIn[0], LabIn[1], LabIn[2]); + C_RGB_XYZ_Lab XYZ = LabToXYZ(Lab); + SetReferenceWhite(DestWhite); + C_RGB_XYZ_Lab LabOut1; + LabOut1 = XYZToLab(XYZ); + // LabOut1.Clamp(LowLab, HighLab); + // double *LabD = new double[3]; + LabOut[0] = LabOut1.Get_x(); + LabOut[1] = LabOut1.Get_y(); + LabOut[2] = LabOut1.Get_z(); + // SetReferenceWhite(SourceWhite); +/* C_RGB_XYZ_Lab LabOut2; + LabOut2 = XYZToLab(XYZ); + double *LabD = new double[3]; + double x = 100 - Lab.Get_x(); + double f = 100.0 / (100.0 + pow(x, 3) / 100.0); + LabD[0] = f*LabOut1.Get_x() + (1-f) *LabOut2.Get_x(); + LabD[1] = f*LabOut1.Get_y() + (1 - f) *LabOut2.Get_y(); + LabD[2] = f*LabOut1.Get_z() + (1 - f) *LabOut2.Get_z(); + return(LabD); */ + } + + + void ColorConvert::ChangeWP(C_RGB_XYZ_Lab XYZIn, C_RGB_XYZ_Lab &LabOut, C_RGB_XYZ_Lab SourceWhite, C_RGB_XYZ_Lab DestWhite) + { + SetReferenceWhite(SourceWhite); + C_RGB_XYZ_Lab Lab; + C_RGB_XYZ_Lab XYZ = XYZIn; + SetReferenceWhite(DestWhite); + C_RGB_XYZ_Lab LabOut1; + LabOut1 = XYZToLab(XYZ); + // LabOut1.Clamp(LowLab, HighLab); + // double *LabD = new double[3]; + LabOut = LabOut1; + } + void ColorConvert::InitializeConversionMatrices() + { + for (unsigned int i = 0; i. + + VectorXd JMh(3); + JMh = Jab_2_JMh(Jab); + VectorXd XYZ = ciecam02_2_XYZ(JMh); + return(XYZ); + } + + VectorXd ColorConvert::Jab_2_JMh(VectorXd Jab) + { // Convert fromJ'a'b' colorspace to CIECAM02 JMh values. + + double Jp = Jab(0); + double ap = Jab(1); + double bp = Jab(2); + + Jp = Jp * m_JabParams.KL; + double J = -Jp / (m_JabParams.c1 * Jp - 100 * m_JabParams.c1 - 1); + double h = 0; + if (ap == 0. && bp == 0.) + h = 0.; + else + h = atan2(bp, ap) * 180 / EIGEN_PI; + double Mp = sqrt(ap*ap + bp*bp); + double M = (exp(m_JabParams.c2*Mp) - 1) / m_JabParams.c2; + + VectorXd JMh(3); + JMh << J, M, h; + return(JMh); + } + + VectorXd ColorConvert::ciecam02_2_XYZ(VectorXd JMh) + { + //CIECAM02 to XYZ conversion + + +//Step 1: Get Data + double J = JMh(0); + double C = JMh(1) / pow( m_ParamsCIECam02.F_L, 0.25); + double h = JMh(2); + +// Step 2: + double d = sqrt(J / 100)*pow(1.64 - pow(0.29, m_ParamsCIECam02.n), 0.73); + double t =pow (C /d, (1 / 0.9)); + double et = (cos(EIGEN_PI*h / 180 + 2) + 3.8) / 4; + double A = m_ParamsCIECam02.A_w * pow((J / 100) , 1 / ( m_ParamsCIECam02.c* m_ParamsCIECam02.z)); + double p1 = (50000 / 13) * ( m_ParamsCIECam02.N_c * m_ParamsCIECam02.N_cb) * et / t; + double p2 = A / m_ParamsCIECam02.N_bb + 0.305; + double p3 = 21. / 20.; + double nom = 460 * (p2 * (2 + p3)) / 1403; + double den = 220 * (2 + p3) / 1403; +// Step 3: calculate red - green(a), yellow - blue(b) : + double hr = h*EIGEN_PI / 180.; + double a, b, tmp; + if (abs(sin(hr)) >= abs(cos(hr))) + { + tmp = cos(hr) / sin(hr); + b = nom / ((p1 / sin(hr)) + den*tmp - (27 / 1403) + p3*(6300 / 1403)); + a = b*tmp; + } + else + { + tmp = sin(hr) / cos(hr); + a = nom / ((p1 / cos(hr)) + den - ((27 / 1403) - p3*(6300 / 1403))*tmp); + b = a*tmp; + } +// Step 4: post - adaption cone response : + VectorXd LMSp_a(3); + LMSp_a(0) = (460 * p2 + 451 * a + 288 * b) / 1403; + LMSp_a(1) = (460 * p2 + -891 * a - 261 * b) / 1403; + LMSp_a(2) = (460 * p2 + -220 * a - 6300 * b) / 1403; + +// Step 5: Hunt - Pointer - Estevez response : + VectorXd LMSp(3); + VectorXd SignLMSp_a(3); + for (int i = 0; i < 3; ++i) + { + SignLMSp_a(i) = 0; + tmp = (27.13 * abs(LMSp_a(i) - 0.1)) / (400 - abs(LMSp_a(i) - 0.1)); + if ((LMSp_a(i)-0.1) < 0) + SignLMSp_a(i) = -1; + else if ((LMSp_a(i)-0.1) > 0) + SignLMSp_a(i) = 1; + LMSp(i) = SignLMSp_a(i)* (100. / m_ParamsCIECam02.F_L)*pow(tmp, (1 / 0.42)); + } + +//Step 6: cone responses considering luminance and surround : + + VectorXd LMS_C = ( m_ParamsCIECam02.M_CAT02* m_ParamsCIECam02.M_HPE.inverse()) * LMSp; + + //Step 7 : cone responses : + + VectorXd LMS(3); + for (int i = 0; i < 3; ++i) + LMS(i) = LMS_C(i) / m_ParamsCIECam02.LMS_c(i); + + //Step 8: tristimulus values : + VectorXd XYZ(3); + XYZ = m_ParamsCIECam02.M_CAT02.inverse()*LMS; + return(XYZ); + } + + VectorXd ColorConvert::XYZtoJab(VectorXd pColor, SURROUND sur) + { + C_RGB_XYZ_Lab wp(3); + if ( m_ParamsCIECam02.XYZ_WP[1] == 1.) + wp.Set( m_ParamsCIECam02.XYZ_WP[0] *100, m_ParamsCIECam02.XYZ_WP[0] * 100, m_ParamsCIECam02.XYZ_WP[2] * 100); + else + wp.Set( m_ParamsCIECam02.XYZ_WP[0] , m_ParamsCIECam02.XYZ_WP[1] , m_ParamsCIECam02.XYZ_WP[2]); + + VectorXd surParam(3); + surParam << 1, 0.69, 1; + double LUMINANCE_PCS = 159.16; + double L_A = LUMINANCE_PCS / 5.0; + double Y_b = 20.0; + // ciecam02_parameters( Y_b, 64 / EIGEN_PI / 5, sur); + VectorXd XYZ(3); + XYZ = 100 * pColor; + VectorXd JQCMsHh(7); + JQCMsHh = XYZ_2_ciecam02(XYZ); + VectorXd JMh(3); + JMh << JQCMsHh(0), JQCMsHh(3), JQCMsHh(6); +// Jab_parameters(UCS); + VectorXd Jab(3); + Jab = JMh_2_Jab(JMh); + return(Jab); + } + + double *ColorConvert::LabToJab(double* pColor, SURROUND sur) + { + VectorXd Vec(3); + for (int i = 0; i < 3; ++i) + Vec(i) = pColor[i]; + VectorXd OutVec = LabToJab(Vec, sur); + double *Out = new double[3]; + //double *Out = DBG_NEW double[3]; + for (int i = 0; i < 3; ++i) + Out[i]= OutVec(i); + return(Out); + } + + VectorXd ColorConvert::LabToJab(VectorXd pColor, SURROUND sur) + { + C_RGB_XYZ_Lab Color(pColor); + C_RGB_XYZ_Lab XYZColor; + XYZColor = LabToXYZ(Color); + VectorXd OutColor(3); + VectorXd InColor(3); + InColor << XYZColor.Get_x(), XYZColor.Get_y(), XYZColor.Get_z(); + OutColor = XYZtoJab(InColor, sur); + return(OutColor); + } + void ColorConvert::InitCiecamParams(double Y_b, double L_A, SURROUND sur, CAM02CS CS) + { + ciecam02_parameters( Y_b, L_A, sur); + Jab_parameters(CS); + } + + void ColorConvert::SymmetricaldECMC(VectorXd refX, VectorXd samX, double &dECMCVal) + { + double dECMC1, dECMC2; + dEcmc(refX, samX, dECMC1); + dEcmc(samX, refX, dECMC2); + dECMCVal = (dECMC1 + dECMC2) / 2; + } + + void ColorConvert::dEcmc(C_RGB_XYZ_Lab &refX, C_RGB_XYZ_Lab &samX, double &dECMC) + { + VectorXd refX1 = refX.Get(); + VectorXd samX1 = samX.Get(); + dEcmc(samX1, refX1, dECMC); + } + + void ColorConvert::dEcmc(VectorXd refX, VectorXd samX, double &dECMC) + { + //dEcmc(refX, samX) calculates color difference CMC(2:1) in + //CIE - L*a*b* colorspace between references(refX) and + // samples(samX) + +// reference parameter calculations + // hue calculation + double h1 = atan2(refX(2), refX( 1))*(180 / EIGEN_PI); + if (h1<0) + h1 = h1 + 360; + double h2= atan2(samX( 2), samX( 1))*(180 / EIGEN_PI); + if (h2<0) + h2 = h2 + 360; + double refX_H = h1 ; + //chroma calculation + double refX_C = sqrt(refX(1)*refX(1) + refX(2)*refX(2)); + //reference SL parameter + double refX_SL; + if (refX(0) <= 16) + refX_SL = 0.511; + else + refX_SL = refX(0)*0.040975 / (1 + 0.01765*refX(0)); + //reference SC parameter + double refX_SC = (0.638 + 0.0638*refX_C / (1 + 0.0131*refX_C)); + //reference CQ parameter + double refX_CQ = pow(refX_C, 4); + //reference F parameter + double refX_F = sqrt(refX_CQ / (refX_CQ + 1900)); + // reference T parameter + double refX_T = 0; + if ((refX_H > 164) & (refX_H < 345)) + refX_T = 0.56 + abs(0.2*cos(EIGEN_PI*(refX_H + 168) / 180)); + else if ((refX_H >= 345) | (refX_H <= 164)) + refX_T = 0.36 + abs(0.4*cos(EIGEN_PI*(refX_H + 35) / 180)); + // reference SH parameter + double refX_SH = refX_SC*(refX_T*refX_F + 1 - refX_F); + + //sample parameter calculations + //hue calculation + double samX_H =h2; + //chroma calculation + double samX_C = sqrt(samX(1)*samX(1) + samX(2)*samX(2)); + + double dL = refX( 0) - samX( 0); + double dC = samX_C - refX_C; + 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)); + } + + void ColorConvert::Initciecam02_parameters() + { + m_ParamsCIECam02.XYZ_WP[0] = 0; + m_ParamsCIECam02.XYZ_WP[1] = 0; + m_ParamsCIECam02.XYZ_WP[2] = 0; + m_ParamsCIECam02.F = 0; + m_ParamsCIECam02.c = 0; + m_ParamsCIECam02.N_c = 0; + m_ParamsCIECam02.M_CAT02 = MatrixXd::Zero(3,3); + m_ParamsCIECam02.M_HPE = MatrixXd::Zero(3, 3); + m_ParamsCIECam02.h_i = VectorXd::Zero(5); + m_ParamsCIECam02.e_i = VectorXd::Zero(5); + m_ParamsCIECam02.H_i = VectorXd::Zero(5); + m_ParamsCIECam02.LMS_w = VectorXd::Zero(3); + m_ParamsCIECam02.D = 0; + m_ParamsCIECam02.LMS_c= VectorXd::Zero(3); + m_ParamsCIECam02.LMSp_w = VectorXd::Zero(3); + m_ParamsCIECam02.k = 0; + m_ParamsCIECam02.F_L = 0; + m_ParamsCIECam02.n = 0; + m_ParamsCIECam02.N_bb = 0; + m_ParamsCIECam02.N_cb = 0; + m_ParamsCIECam02.z = 0; + m_ParamsCIECam02.LMSp_aw = VectorXd::Zero(3); + m_ParamsCIECam02.A_w = 0; + } + void ColorConvert::InitJab_parameters() + { + m_JabParams.CS = CAM02CS(0); + m_JabParams.KL = 0; + m_JabParams.c1 = 0; + m_JabParams.c2 = 0; + } + + void ColorConvert::dE76(VectorXd refX, VectorXd samX, double &dE) + { + double dEVal = 0; + for (int i = 0; i < 3; ++i) + { + dEVal += pow(refX(i) - samX(i), 2); + } + dEVal = sqrt(dEVal); + dE = dEVal; + } + + void ColorConvert::dE76(C_RGB_XYZ_Lab &refX, C_RGB_XYZ_Lab &samX, double &dE) + { + VectorXd refX1 = refX.Get(); + VectorXd samX1 = samX.Get(); + dE76(samX1, refX1, dE); +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.h new file mode 100644 index 000000000..55e1ebc41 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorConvert.h @@ -0,0 +1,140 @@ + +#ifndef __COLORCONVERT_H__ +#define __COLORCONVERT_H__ + +#include "C_RGB_XYZ_Lab.h" +#include "Dense" +#include + +using Eigen::MatrixXd; +using Eigen::VectorXd; + +struct CIECAM02Params +{ + double XYZ_WP[3]; + double F; + double c; + double N_c; + MatrixXd M_CAT02; + MatrixXd M_HPE; + VectorXd h_i; + VectorXd e_i; + VectorXd H_i; + VectorXd LMS_w; + double D; + VectorXd LMS_c; + VectorXd LMSp_w; + double k, F_L, n, N_bb, N_cb, z; + VectorXd LMSp_aw; + double A_w; +}; +enum Illum { D50, D65 }; +enum SURROUND +{ + average, + dim, + dark +}; + +enum CAM02CS +{ + UCS, + LCD, + SCD +}; + +struct Jab_Params +{ + CAM02CS CS; + double KL; + double c1; + double c2; +}; + +class ColorConvert +{ + public: + + ColorConvert (void); + ColorConvert (Illum D, C_RGB_XYZ_Lab SourceWhite); + ColorConvert(C_RGB_XYZ_Lab DestWhite, Illum D ); + ColorConvert(Illum DDest, Illum DSource); + ColorConvert (const ColorConvert &rhs); + ColorConvert(C_RGB_XYZ_Lab DDest, C_RGB_XYZ_Lab DSource); + ColorConvert &operator = (const ColorConvert &rhs); + ColorConvert(Illum DDest, Illum DSource, double Y_b, double L_A, SURROUND sur, CAM02CS CS); + ~ColorConvert(); + C_RGB_XYZ_Lab XYZToLab ( C_RGB_XYZ_Lab xyz); + C_RGB_XYZ_Lab LabToXYZ ( C_RGB_XYZ_Lab lab) ; + + const C_RGB_XYZ_Lab &GetReferenceWhite (void) const; + void SetReferenceWhite (C_RGB_XYZ_Lab &refWhite); + void SetReferenceWhite(Illum D); + void CAT_BradfordMat(); + //Conversion between XYZ and RGB + VectorXd GetChromaticities(); + C_RGB_XYZ_Lab RGBtoXYZ(C_RGB_XYZ_Lab & rgbVal); + C_RGB_XYZ_Lab XYZtoRGB(C_RGB_XYZ_Lab& xyzVal); + C_RGB_XYZ_Lab XYZtoRGBNoClip(C_RGB_XYZ_Lab& xyzVal); + C_RGB_XYZ_Lab LabtoRGBNoClip(C_RGB_XYZ_Lab& LabVal); + void LabtoRGBNoClip(double*InLab, double *OutRGB); + void LabtoRGB(double*InLab, double* OutRGB ); + void ChangeWP(double *LabIn, double *LabOut, C_RGB_XYZ_Lab SourceWhite, C_RGB_XYZ_Lab DestWhite); + void ChangeWP(C_RGB_XYZ_Lab LabIn, C_RGB_XYZ_Lab &LabOut, C_RGB_XYZ_Lab SourceWhite, C_RGB_XYZ_Lab DestWhite); + C_RGB_XYZ_Lab LabtoRGB(C_RGB_XYZ_Lab& LabVal); + void RGBtoLab(double *InRGB, double *OutLab); + C_RGB_XYZ_Lab RGBtoLab(C_RGB_XYZ_Lab& RGB); + // void RGBtoLab(std::vector&InRGB, double *OutLab); + void InitializeConversionMatrices(); + void RecalculateConversionMatrices(const VectorXd& chromaticites); + C_RGB_XYZ_Lab ApplyBradfordMat(C_RGB_XYZ_Lab& xyzVal); + 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); + void dEcmc(VectorXd refX, VectorXd samX, double &dE); + void dEcmc(C_RGB_XYZ_Lab &refX, C_RGB_XYZ_Lab &samX, double &dE); + void dE76(VectorXd refX, VectorXd samX, double &dE); + void dE76(C_RGB_XYZ_Lab &refX, C_RGB_XYZ_Lab &samX, double &dE); + void SymmetricaldECMC(VectorXd refX, VectorXd samX, double &dECMC); + CAM02CS getCAM02CS() { return(m_CS); }; + SURROUND getSurround() { return(m_sur); }; + + protected: + + private: + //Explicit inverse of a 3x3 matrix: A is the input matrix, B its inverse + void InverseOfThreeByThreeMatrix(const MatrixXd& A, MatrixXd& B); + void ComputeRGBtoXYZmatrix(); + void ComputeXYZtoRGBmatrix(); + Jab_Params m_JabParams; + CIECAM02Params m_ParamsCIECam02; + void Initciecam02_parameters(); + void InitJab_parameters(); + void ciecam02_parameters( double Y_b, double L_A, SURROUND sur); + VectorXd XYZ_2_ciecam02(VectorXd XYZ); + VectorXd Jab_2_JMh(VectorXd Jab); + VectorXd JMh_2_Jab(VectorXd JMh); + VectorXd ciecam02_2_XYZ(VectorXd JMh); + void Jab_parameters(CAM02CS CS); + C_RGB_XYZ_Lab m_ReferenceWhite; // Reference white + C_RGB_XYZ_Lab m_InvReferenceWhite; // 1.0 / Reference white + C_RGB_XYZ_Lab m_SourceWhite; // 1.0 / Reference white + CAM02CS m_CS; + SURROUND m_sur; + MatrixXd m_BradfordMatrix; + double GammaExpand_sRGB(double nonlinear); + double GammaCompress_sRGB(double linear); + void SetCIECamWhitePoint(C_RGB_XYZ_Lab ReferenceWhite); + void SetCAM02CS(CAM02CS CS) { m_CS = CS; }; + void SetSurround(SURROUND sur) { m_sur = sur; }; + +}; + + + + +#endif // __CIELABCONVERT_H__ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.cpp new file mode 100644 index 000000000..768647a0b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.cpp @@ -0,0 +1,769 @@ +#include "ColorTable.h" +#include "NumConversions.h" + +using namespace std; + +//Constructor +ColorTable::ColorTable() : + m_B2ATransform(NULL), m_A2BTransform(NULL), +m_B2ARTransform(NULL), m_A2BRTransform(NULL), +m_GBD(NULL), m_GBDR(NULL), +m_LinCurves(NULL), m_LinCurvesR(NULL), +m_nB2AnSepIn(0), m_nB2AnSepOut(0), +m_nA2BnSepIn(0), m_nA2BnSepOut(0), +m_TableVersion(0), m_TableSubVersion(0), m_NormFactor(NULL), m_InvNormFactor(NULL), +m_nGamutRegions(0), m_nProcessRanges(0), m_GamutRegionMinLim(NULL), +m_GamutRegionMaxLim(NULL), m_NormGamutRegionMaxLim(NULL), m_CTLiquidFactors(NULL), +m_whitepointXYZ_CT(0.0), m_forwardmodel(NULL), m_forwardmodelR(NULL) +{ +} + +ColorTable::~ColorTable() +{ + if (m_B2ATransform != NULL) + { + delete m_B2ATransform; + m_B2ATransform = NULL; + } + if (m_B2ARTransform != NULL) + { + delete m_B2ARTransform; + m_B2ARTransform = NULL; + } + if (m_A2BTransform != NULL) + { + delete m_A2BTransform; + m_A2BTransform = NULL; + } + if (m_A2BRTransform != NULL) + { + delete m_A2BRTransform; + m_A2BRTransform = NULL; + } + if (m_GBD != NULL) + { + delete m_GBD; + m_GBD = NULL; + } + if (m_GBDR != NULL) + { + delete m_GBDR; + m_GBDR = NULL; + } + if (m_LinCurves != NULL) + { + delete m_LinCurves; + m_LinCurves = NULL; + } + if (m_LinCurvesR != NULL) + { + delete m_LinCurvesR; + m_LinCurvesR = NULL; + } + if (m_GamutRegionMaxLim != NULL) + { + delete[] m_GamutRegionMaxLim; + m_GamutRegionMaxLim = NULL; + } + if (m_NormGamutRegionMaxLim != NULL) + { + delete[] m_NormGamutRegionMaxLim; + m_NormGamutRegionMaxLim = NULL; + } + if (m_NormFactor != NULL) + { + delete[] m_NormFactor; + m_NormFactor = NULL; + } + if (m_InvNormFactor != NULL) + { + delete[] m_InvNormFactor; + m_InvNormFactor = NULL; + } + /*if (m_CTLiquidFactors != NULL) + { + delete[] m_CTLiquidFactors; + m_CTLiquidFactors = NULL; + }*/ +} +void ColorTable::InitColorTables(bool has_rddata, uint8_t *data, int nprocessranges) +{ + readColorTables(has_rddata, data, nprocessranges); + SetNormFactor(); + SetInverseNormFactor(); + if (m_NormGamutRegionMaxLim == NULL) + m_NormGamutRegionMaxLim = new double[m_nGamutRegions]; + NormGamutRegionMaxLim(); +} + +void ColorTable::readColorTables(bool has_data, uint8_t * data, int nprocessranges) +{ + //parse Color Tansformations, placed in forward data + int bytesread = 0; + NumConversions conv; + int tag_count = 0; + int TblVer = 0; + int TblSubVer = 0; + if (has_data) + { + //Read Header + CT_Header *header = read_header(data, bytesread); + SetnGamutRegions((int)(header->GetNGamutRegions())); + TblVer = (int)header->GetTableVersion()[0]; + TblSubVer = (int)header->GetTableVersion()[1]; + SetTableVersion(TblVer); + SetTableSubVersion(TblSubVer); + + if (m_nGamutRegions != nprocessranges) + { + throw std::exception("Number of gamut regions in table does not match STRIP\0"); + return; + } + double *tmpGamutRegionsLim = header->GetGamutRegionsMaxLimit(); + if(m_GamutRegionMaxLim == NULL) + m_GamutRegionMaxLim = new double[m_nGamutRegions]; + for (int i = 0; i < m_nGamutRegions; ++i) + { + if(tmpGamutRegionsLim[i]<=0) + { + throw std::exception("Gamut region Limit is zero or negative\0"); + return; + } + else + m_GamutRegionMaxLim[i] = tmpGamutRegionsLim[i]; //in[nl/cm] + } + m_nProcessRanges = (int)(nprocessranges); + double *tmpLF = header->GetLiquidFactors(); + if (m_CTLiquidFactors == NULL) + m_CTLiquidFactors = new double[4]; + for (int i = 0; i < 4; ++i) + { + if (tmpLF[i] <= 0) + { + throw std::exception("Color Table Liquid Factors are 0 or negative\0"); + return; + } + else + m_CTLiquidFactors[i] = tmpLF[i]; //in [nl/cm] + } + if (m_GamutRegionMinLim == NULL) + m_GamutRegionMinLim = new double[m_nGamutRegions]; + if (m_TableSubVersion > 0) + { + tmpGamutRegionsLim = header->GetGamutRegionsMinLimit(); + for (int i = 0; i < m_nGamutRegions; ++i) + { + if (tmpGamutRegionsLim[i] <= 0) + { + throw std::exception("Min Gamut region Limit is zero or negative\0"); + return; + } + else + m_GamutRegionMinLim[i] = tmpGamutRegionsLim[i]; //in [nl/cm] + } + } + else + { + m_GamutRegionMinLim[0] = 200; + m_GamutRegionMinLim[1] = 300; + } + uint32_t tmp; + uint8_t *buff = data; + tmp = conv.ByteToInt(buff, bytesread); + tag_count = (int)tmp; + bytesread += 4; + //read Tag Table + char **TagNames = new char*[tag_count]; + //char **TagNames = DBG_NEW char*[tag_count]; + int **TagSize = new int*[tag_count]; + + //int **TagSize = DBG_NEW int*[tag_count]; + char tmpC[80]; + int n = 0; + int i; + for (i = 0; i < tag_count; ++i) + { + TagSize[i] = new int[2]; + //TagSize[i] = DBG_NEW int[3]; + tmp = conv.ByteToInt(buff, bytesread); + n = sizeof(tmp); + //tmpC = DBG_NEW char[n]; + conv.getchar(tmp, *tmpC); + TagNames[i] = new char[n+1]; + //TagNames[i] = DBG_NEW char[n]; + strncpy_s(TagNames[i], n + 1, tmpC, n); + bytesread += 4; + TagSize[i][0] = conv.ByteToInt(buff, bytesread); + bytesread += 4; + TagSize[i][1] = conv.ByteToInt(buff, bytesread); + bytesread += 4; + } + + int *TList = new int[tag_count]; + //int *TList = DBG_NEW int[tag_count]; + for (int k = 0; k < tag_count; ++k) + { + if (strncmp(TagNames[k], "A2B ", 4) == 0) + TList[k] = A2B; + else if (strncmp(TagNames[k], "A2BR", 4) == 0) + TList[k] = A2BR; + else if (strncmp(TagNames[k], "B2A ", 4) == 0) + TList[k] = B2A; + else if (strncmp(TagNames[k], "B2AR ", 4) == 0) + TList[k] = B2AR; + else if (strncmp(TagNames[k], "wtpt", 4) == 0) + TList[k] = wtpt; + else if (strncmp(TagNames[k], "desc", 4) == 0) + TList[k] = desc; + else if (strncmp(TagNames[k], "gbd ", 4) == 0) + TList[k] = gbd; + else if (strncmp(TagNames[k], "gbdR", 4) == 0) + TList[k] = gbdR; + 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], "lcrR", 4) == 0) + TList[k] = lcrR; + else if (strncmp(TagNames[k], "FMCo", 4) == 0) + TList[k] = FMCo; + else if (strncmp(TagNames[k], "FMCR", 4) == 0) + TList[k] = FMCR; + // else if (strncmp(TagNames[k], "GReg", 2) == 0) + // TList[k] = GReg; + else + throw std::exception("Unknown Tag in Color Tables"); + } + + + for (int k = 0; k < tag_count; ++k) + { + switch (TList[k]) + { + case A2B: + { + uint8_t *A2BLUT = &(data[TagSize[k][0]]); + int A2BLutsize = TagSize[k][1]; + if(m_A2BTransform == NULL) + m_A2BTransform = new ColorTransf(); + //m_A2BTransform = DBG_NEW ColorTransf(); + m_A2BTransform->InitData(A2BLUT, A2BLutsize); + m_nA2BnSepIn = m_A2BTransform->GetSeparationsIn(); + m_nA2BnSepOut = m_A2BTransform->GetSeparationsOut(); + break; + } + case A2BR: + { + uint8_t *A2BRLUT = &(data[TagSize[k][0]]); + int A2BRLutsize = TagSize[k][1]; + if (m_A2BRTransform == NULL) + m_A2BRTransform = new ColorTransf(); + //m_A2BTransform = DBG_NEW ColorTransf(); + m_A2BRTransform->InitData(A2BRLUT, A2BRLutsize); + break; + } + case B2A: + { + uint8_t *B2ALUT = &(data[TagSize[k][0]]); + int B2ALutsize = TagSize[k][1]; + if(m_B2ATransform == NULL) + m_B2ATransform = new ColorTransf(); + //m_B2ATransform = DBG_NEW ColorTransf(); + m_B2ATransform->InitData(B2ALUT, B2ALutsize); + m_nB2AnSepIn = m_B2ATransform->GetSeparationsIn(); + m_nB2AnSepOut = m_B2ATransform->GetSeparationsOut(); + break; + } + case B2AR: + { + uint8_t *B2ARLUT = &(data[TagSize[k][0]]); + int B2ARLutsize = TagSize[k][1]; + if(m_B2ARTransform == NULL) + m_B2ARTransform = new ColorTransf(); + //m_B2ATransform = DBG_NEW ColorTransf(); + m_B2ARTransform->InitData(B2ARLUT, B2ARLutsize); + 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 = &(data[TagSize[k][0]]); + if(m_GBD == NULL) + m_GBD = new GBD(); + //m_GBD = DBG_NEW GBD(); + int GBDSize = TagSize[k][1]; + m_GBD->InitData(GBDList, GBDSize); + break; + } + case gbdR: + { + uint8_t *GBDRList = &(data[TagSize[k][0]]); + if(m_GBDR == NULL) + m_GBDR = new GBD(); + //m_GBD = DBG_NEW GBD(); + int GBDRSize = TagSize[k][1]; + m_GBDR->InitData(GBDRList, GBDRSize); + break; + } + case lcrv: + { + uint8_t *CurvesData = &(data[TagSize[k][0]]); + if(m_LinCurves == NULL) + m_LinCurves = new Curves(); + int CurvesSize = TagSize[k][1]; + m_LinCurves->InitData(CurvesData, CurvesSize); + break; + } + case lcrR: + { + uint8_t *CurvesData = &(data[TagSize[k][0]]); + if (m_LinCurvesR == NULL) + m_LinCurvesR = new Curves(); + int CurvesSize = TagSize[k][1]; + m_LinCurvesR->InitData(CurvesData, CurvesSize); + break; + } + case wtpt: + { + read_xyz_type(TagSize[k][0], TagSize[k][1], &m_whitepointXYZ_CT, data); + + break; + } + case cprt: + { + std::string textstr; + read_text_type(TagSize[k][0], TagSize[k][1], &textstr, data); + break; + } + case desc: + { + std::string textdescstr; + read_text_description_type(TagSize[k][0], TagSize[k][1], &textdescstr, data); + break; + } + case FMCo: + { + uint8_t *FMD = &(data[TagSize[k][0]]); + if (m_forwardmodel == NULL) + m_forwardmodel = new ForwardModel(); + int FMSize = TagSize[k][1]; + m_forwardmodel->InitData(FMD, FMSize); + break; + } + case FMCR: + { + uint8_t *FMD = &(data[TagSize[k][0]]); + if (m_forwardmodelR == NULL) + m_forwardmodelR = new ForwardModel(); + int FMSize = TagSize[k][1]; + m_forwardmodelR->InitData(FMD, FMSize); + break; + } + default: + { + throw std::exception("Unresolved Tag in Color Tables"); + return; + } + + } + } + if (TagNames != NULL) + { + for (int i = 0; i < tag_count; ++i) + { + delete[] TagNames[i]; + // TagNames[i] = NULL; + } + delete[]TagNames; + TagNames = NULL; + } + + if (TagSize != NULL) + { + for (int i = 0; i < tag_count; ++i) + { + delete[] TagSize[i]; + TagSize[i] = NULL; + } + delete[]TagSize; + TagSize = NULL; + } + if (TList != NULL) + { + delete[] TList; + TList = NULL; + } + if (header != NULL) + { + delete header; + header = NULL; + } + } + else + throw std::exception("Color Table has no Data"); + + + //Verify all relevant tags had been read + if (m_A2BTransform == NULL) + { + throw std::exception("Missing Forward Transform in Color Tables"); + return; + } + if( TblVer > 1 ) + { + if (m_A2BRTransform == NULL) + { + throw std::exception("Missing Reduced Forward Transform in Color Tables"); + return; + } + } + if (m_B2ATransform == NULL) + { + throw std::exception("Missing Inverse Transform in Color Tables"); + return; + } + if (TblVer > 1) + { + if (m_B2ARTransform == NULL) + { + throw std::exception("Missing Reduced Inverse Transform in Color Tables"); + return; + } + } + if (m_GBD == NULL) + { + throw std::exception("Missing Gamut Boundary Descriptor in Color Tables"); + return; + } + if (TblVer > 1) + { + if (m_GBDR == NULL) + { + throw std::exception("Missing Reduced Gamut Boundary Descriptor in Color Tables"); + return; + } + } + if ((m_whitepointXYZ_CT.Get_x() == -1) && (m_whitepointXYZ_CT.Get_y() == -1) && (m_whitepointXYZ_CT.Get_z() == -1)) + { + throw std::exception("Missing Whitepoint in Color Tables"); + return; + } + if (m_LinCurves == NULL) + { + throw std::exception("Missing Linear Curves in Color Tables"); + return; + } + if( TblVer > 1) + { + if (m_LinCurvesR == NULL) + { + throw std::exception("Missing Linear Curves 100 in Color Tables"); + return; + } + } + if (m_TableSubVersion > 0) + { + if(m_forwardmodel == NULL) + throw std::exception("Missing Forward Model Info in Color Tables"); + return; + if(m_TableVersion > 1) + { + if (m_forwardmodelR == NULL) + throw std::exception("Missing Forward Model 100 Info in Color Tables"); + return; + } + } + return; // OK +} + +CT_Header *ColorTable::read_header(uint8_t *data, int &bytesread) +{ + //CT_Header *Header = new CT_Header; + //CT_Header *Header = DBG_NEW CT_Header; + CT_Header *Header = new CT_Header; + + // unsigned int tmp = (buffer[2 * i + 1] << 8) | buffer[2 * i]; + uint8_t *ColorTableData = data; + //File Size + NumConversions Conv; + unsigned int TblSize = Conv.ByteToInt(ColorTableData, bytesread); + Header->SetTableSize(TblSize); + bytesread = 4; + uint8_t versionBCT[2]; + versionBCT[0] = (unsigned int)ColorTableData[bytesread]; + bytesread += 1; + versionBCT[1] = (unsigned int)ColorTableData[bytesread]; + unsigned int TVersion[3]; + TVersion[0] = versionBCT[0]; + TVersion[1] = versionBCT[1] >> 4; + TVersion[2] = versionBCT[1] & 15; + Header->SetTableVersion(TVersion); + + bytesread += 1; + uint32_t tmp = Conv.ByteToInt(ColorTableData, bytesread); + //char *tmpC = DBG_NEW char[n]; + char tmpC_CS[sizeof(tmp)+1]; + Conv.getchar(tmp, * tmpC_CS); + //Header.ColorSpace = DBG_NEW char[n]; + Header->SetColorSpace(tmpC_CS); + + bytesread += 4; + tmp = Conv.ByteToInt(ColorTableData, bytesread); + char tmp_connectionspace[sizeof(tmp)+1]; + Conv.getchar(tmp, *tmp_connectionspace); + //Header.ConnectionSpace = DBG_NEW char[n]; + Header->SetConnectionSpace(tmp_connectionspace); + + bytesread += 4; + + bytesread += 12; + tmp = Conv.ByteToInt(ColorTableData, bytesread); + char tmp_DM[sizeof(tmp)+1]; + Conv.getchar(tmp, *tmp_DM); + //Header.DeviceManufacturer = DBG_NEW char[n]; + Header->SetDeviceManufacturer(tmp_DM); + + bytesread += 4; + //read illuminant + double xyz[3]; + for (int j = 0; j < 3; ++j) + { + tmp = Conv.ByteToInt(ColorTableData, bytesread); + xyz[j] = (double)(tmp) / 65536; + bytesread += 4; + } + C_RGB_XYZ_Lab XYZIllum(xyz[0], xyz[1], xyz[2]); + Header->SetIlluminant(XYZIllum); + //Read Number of Gamut Regions and Max Limits per Region + Header->SetNGamutRegions(ColorTableData[bytesread]); + bytesread++; + int nsize = Header->GetNGamutRegions(); + + double *GRegMaxLim = new double[nsize]; + for (int i = 0; i < nsize; ++i) + { + tmp = Conv.ByteToShort(ColorTableData, bytesread); + bytesread += 2; + GRegMaxLim[i] = (double)tmp; + } + Header->SetGamutRegionsMaxLimit(GRegMaxLim); + + double *LiquidFactors = new double[4]; + for (int i = 0; i < 4; ++i) + { + tmp = Conv.ByteToShort(ColorTableData, bytesread); + bytesread += 2; + LiquidFactors[i] = (double)tmp; + } + Header->SetLiquidFactors(LiquidFactors); + double *GRegMinLim = new double[nsize]; + if(TVersion[1]>0) + { + for (int i = 0; i < nsize; ++i) + { + tmp = Conv.ByteToShort(ColorTableData, bytesread); + bytesread += 2; + GRegMinLim[i] = (double)tmp; + } + } + else + { + GRegMinLim[0] = 200; + GRegMinLim[1] = 300; + } + Header->SetGamutRegionsMinLimit(GRegMinLim); + + + if (GRegMaxLim != NULL) + { + delete[] GRegMaxLim; + GRegMaxLim = NULL; + } + if (GRegMinLim != NULL) + { + delete[] GRegMinLim; + GRegMinLim = NULL; + } + if (LiquidFactors != NULL) + { + delete[] LiquidFactors; + LiquidFactors = NULL; + } + if (bytesread < 128) + { + bytesread = 128; + return(Header); + } + else + { + throw std::exception("could not read Color table Header"); + } +} + +void ColorTable::read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *XYZ, uint8_t *data) +{ + // 0 - 3 'XYZ ' + //4 - 7 reserved, must be 0 + // 8 - n array of XYZ numbers + + if (data_size < 8) + { + throw std::exception("not enough data to read xyz"); + } + uint8_t *buff = &(data[offset]); + NumConversions Conv; + int bytesread = 0; + int tmpxyz = Conv.ByteToInt(buff, bytesread); + + //char* tmpC = DBG_NEW char[n]; + int n = sizeof(tmpxyz); + //char tmpC[sizeof(tmpxyz)]; + char xyztype[sizeof(tmpxyz)+1]; + Conv.getchar(tmpxyz, *xyztype); + + //char *xyztype = DBG_NEW char[n + 1]; +// strcpy(xyztype, tmpC); + if (strncmp(xyztype, "XYZ ", sizeof(tmpxyz)) != 0) + { + throw std::exception("Wrong Tag Type"); + return; + } + + bytesread = 8; + int num_values = (data_size - 8) / 4; + if (floor((double)(num_values) / 3) * 3 != num_values) + { + throw std::exception("not enough Data to read xyz"); + return; + } + double xyz[3]; + int tmp; + for (int j = 0; j < 3; ++j) + { + tmp = Conv.ByteToInt(buff, bytesread); + xyz[j] = (double)(tmp) / 65536; + bytesread += 4; + } + XYZ->Set(xyz[0], xyz[1], xyz[2]); + return; +} + +void ColorTable::read_text_type(int offset, int data_size, std::string *textstr, uint8_t *data) +{ + // 0 - 3 'text' + //4 - 7 reserved, must be 0 + //8 - string of(data_size - 8) 7 - bit ASCII characters, including NULL + + std::stringstream strstr; + if (data_size < 8) + { + throw std::exception("invalid Tag Name"); + strstr << ""; + *textstr = strstr.str(); + return; + } + + uint8_t *buff = &(data[offset]); + int bytesread = 0; + NumConversions Conv; + int tmp = Conv.ByteToInt(buff, bytesread); + int n = sizeof(tmp); + //char *tmpC = DBG_NEW char[n]; + char tmpC[sizeof(tmp)+1]; +// char tagtype[sizeof(tmp)+1]; + Conv.getchar(tmp, *tmpC); + + if (strncmp(tmpC, "text", sizeof(tmp)) != 0) + { + throw std::exception("invalid Tag Name"); + strstr << ""; + *textstr = strstr.str(); + return; + } + + bytesread += 8; + uint8_t tmp1; + for (int i = bytesread; i < data_size; ++i) + { + tmp1 = buff[i]; + strstr.put(tmp1); + } + *textstr = strstr.str(); + //return; +} + +void ColorTable::read_text_description_type(int offset, int data_size, std::string *textdescstr, uint8_t *data) +{ + // 0 - 3 'desc' + // 4 - 7 reserved, must be 0 + // 8 - 11 ASCII invariant description count, including terminating NULL + // 12 - ASCII invariant description + std::stringstream strstr; + uint8_t *buff = &(data[offset]); + int bytesread = 0; + NumConversions Conv; + int tmp = Conv.ByteToInt(buff, bytesread); + int n = sizeof(tmp); + //char *tmpC= DBG_NEW char[n]; + char tmpC[sizeof(tmp)+1]; + Conv.getchar(tmp, *tmpC); + //char *tagtype = DBG_NEW char[n + 1]; + + if (strncmp(tmpC, "desc", sizeof(tmp)) != 0) + { + throw std::exception("invalid Tag Name"); + strstr << ""; + *textdescstr = strstr.str(); + return; + } + bytesread += 8; + int count = Conv.ByteToInt(buff, bytesread); + bytesread += 4; + uint8_t tmp1; + for (int i = 0; i < count - 1; ++i) + { + tmp1 = buff[bytesread + i]; + strstr << tmp1; + } + *textdescstr = strstr.str(); + //return; +} + +void ColorTable::SetNormFactor() +{ + if (m_NormFactor == NULL) + m_NormFactor = new double[m_nA2BnSepIn]; + for (int i = 0; i < m_nA2BnSepIn; ++i) + m_NormFactor[i] = m_GamutRegionMaxLim[m_nProcessRanges-1]/ m_CTLiquidFactors[i] ; +} + +void ColorTable::SetInverseNormFactor() +{ + if (m_InvNormFactor == NULL) + m_InvNormFactor = new double[m_nA2BnSepIn]; + for (int i = 0; i < m_nA2BnSepIn; ++i) + { + if (m_NormFactor[i] <= 0) + throw std::exception("NormFactor is zero or Negative"); + else + m_InvNormFactor[i] = 1.0 / m_NormFactor[i]; + } +} + +void ColorTable::NormGamutRegionMaxLim() +{ + double GamutRegionMaxLim0 = m_GamutRegionMaxLim[0]; + if(GamutRegionMaxLim0<=0) + throw std::exception("Gamut Region Max Limit is zero or Negative"); + for (int i = 0; i < m_nProcessRanges; ++i) + m_NormGamutRegionMaxLim[i] = 100 * m_GamutRegionMaxLim[i] / GamutRegionMaxLim0; +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.h new file mode 100644 index 000000000..319e10fb7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTable.h @@ -0,0 +1,94 @@ +#ifndef _COLORTABLE_H_ +#define _COLORTABLE_H_ + +#include "C_RGB_XYZ_Lab.h" +#include "ColorSpace.pb-c.h" +#include "ColorTransf.h" +#include "CT_Header.h" +#include "GBD.h" +#include "Curves.h" +#include "ForwardModel.h" + +typedef enum { + A2B, + A2BR, + B2A, + B2AR, + cprt, + gbd, + gbdR, + wtpt, + desc, + lcrv, + lcrR, + FMCo, + FMCR +}TagList; +class ColorTable { +public: + ColorTable(); + ~ColorTable(); + void InitColorTables(bool has_rddata, uint8_t *data, int nprocessranges); + + int GetnB2AnSepIn( ){ return(m_nB2AnSepIn); }; + int GetnB2AnSepOut() { return(m_nB2AnSepOut); }; + int GetnA2BnSepIn() { return(m_nA2BnSepIn); }; + int GetnA2BnSepOut() { return(m_nA2BnSepOut); }; + int GetnGamutRegions() { return(m_nGamutRegions); }; + double *GetNormFactor() { return(m_NormFactor); }; + double *GetInverseNormFactor() { return(m_InvNormFactor); }; + double *GetNormGamutRegionMaxLim() { return(m_NormGamutRegionMaxLim); }; + double *GetGamutRegionMaxLim() { return(m_GamutRegionMaxLim); }; + double *GetGamutRegionMinLim() { return(m_GamutRegionMinLim); }; + double *GetCTLiquidFactors() { return(m_CTLiquidFactors); }; + C_RGB_XYZ_Lab GetWhitePoint_CT() { return(m_whitepointXYZ_CT); }; + ForwardModel *GetForwardModel() { return(m_forwardmodel); }; + int GetTableVersion() { return(m_TableVersion); }; + int GetTableSubVersion() { return(m_TableSubVersion); }; + ColorTransf *m_B2ATransform; + ColorTransf *m_A2BTransform; + ColorTransf *m_B2ARTransform; + ColorTransf *m_A2BRTransform; + GBD *m_GBD; + GBD *m_GBDR; + Curves *m_LinCurves; + Curves *m_LinCurvesR; + ForwardModel *m_forwardmodel; + ForwardModel *m_forwardmodelR; +private: + void readColorTables(bool has_rddata, uint8_t *data, int nprocessranges); + void SetNormFactor(); + void SetInverseNormFactor(); + void NormGamutRegionMaxLim(); + int m_nB2AnSepIn; + int m_nB2AnSepOut; + int m_nA2BnSepIn; + int m_nA2BnSepOut; + int m_nGamutRegions; + int m_nProcessRanges; + int m_TableVersion; + int m_TableSubVersion; + double *m_NormFactor; + double *m_InvNormFactor; + double *m_GamutRegionMaxLim; + double *m_GamutRegionMinLim; + double*m_NormGamutRegionMaxLim; + double *m_CTLiquidFactors; + C_RGB_XYZ_Lab m_whitepointXYZ_CT; + 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 SetTableVersion(int TableVersion) { m_TableVersion = TableVersion; }; + void SetTableSubVersion(int TableSubVersion) { m_TableSubVersion = TableSubVersion; }; + + CT_Header *read_header(uint8_t* data, int &bytesread); + void read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *xyz, uint8_t *data); + void read_text_type(int offset, int data_size, std::string *textstr, + uint8_t *data); + void read_text_description_type(int offset, int data_size, std::string *textdescstr, + uint8_t *data); +}; + +#endif \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.cpp new file mode 100644 index 000000000..9e59abf4d --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.cpp @@ -0,0 +1,577 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "ColorTransf.h" +#include "C_RGB_XYZ_Lab.h" +#include +#include +#include "NumConversions.h" +#include "Interp.h" + +using namespace std; +#define LFactor 100 +#define abFactor 255 +#define abOffset 128 +#define InkFactor 100 +#define Uint16Factor 65535 + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 */ + + +// NHedral interpolation given the NDimensional LUT. N=3 or N=4 are supported. +//Assumes the right table is loaded + + + ColorTransf::ColorTransf() : + m_MSBShift(0), m_DataBuffer(NULL), m_SeparationsIn(0), + m_SeparationsOut(0), m_nGridPoints(0), m_GamutLimitsNlperCM(NULL), + m_NGamutRegions(0), m_ByteBuffer(NULL), m_InputCurves(NULL), m_OutputCurves(NULL), + m_num_input_table_entries(0), m_num_output_table_entries(0) + { + + } + + ColorTransf::~ColorTransf() + { + if (m_DataBuffer != NULL) + { + delete[] m_DataBuffer; + m_DataBuffer = NULL; + } + if (m_GamutLimitsNlperCM != NULL) + { + 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::free_char_array(char* charname) + { + if (charname != NULL) + { + delete[] charname; + charname = NULL; + } + } + void ColorTransf::InitData(unsigned char *colorTransformBuffer, long colorTransformSize) + { + /* the whole file is now loaded in the memory buffer. */ + /*Parse data*/ + /* + 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; + + // obtain file size: + int lSize = colorTransformSize; + //lSizeHalf = lSize / 2; + // allocate memory to contain the whole file: + 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(tmpB); + //char *tmpC = DBG_NEW char[n] ; +// char tmpC[sizeof((char*)&tmpB)]; + char luttype[sizeof(tmpB)+1]; + Conv.getchar(tmpB, *luttype); + //char *luttype = DBG_NEW char[n + 1]; +// strcpy(luttype,tmpC); + int TablePrecision; + if (strncmp(luttype, "prc1", sizeof(tmpB))==0) + TablePrecision = 1; + else if (strncmp(luttype, "prc2", sizeof(tmpB))==0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in Color Tables"); + return; + } + + // Skip past reserved padding bytes + bytesread += 4; + + uint8_t num_input_channels = buffer[ bytesread]; + SetSeparationsIn((int)num_input_channels); //Numer of Separations In + bytesread += 1; + uint8_t num_output_channels = buffer[ bytesread]; + SetSeparationsOut((int)num_output_channels); //Numer of Separations Out + bytesread += 1; + uint8_t num_clut_grid_points = buffer[ bytesread]; + SetNGridpoints((int)num_clut_grid_points); //Number of Gridpoints + bytesread += 1; + uint8_t num_Sh4MSB = buffer[ bytesread]; + bytesread += 1; + unsigned short checkMSB = 256 >> (num_Sh4MSB); + if (num_clut_grid_points != (checkMSB + 1)) + { + throw std::exception("Wrong Number of MSB's, ColorTransf::InitData"); + } + else + SetMSBShift((int)num_Sh4MSB); //Number of MSB's + + 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); + if(m_InputCurves == NULL) + 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 + { + 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), m_SeparationsIn)* m_SeparationsOut; + // lut8Type and lut16Type + if (TablePrecision == 1) + { +// int lsizeH2 = (lSize - bytesread + 1) / 2; + if(m_ByteBuffer == NULL) + 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; + if(m_DataBuffer == NULL) + 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); + } + + //Read Output Curves + double *xOut = new double[m_num_output_table_entries]; + double *yOut = new double[m_num_output_table_entries]; + if(m_OutputCurves == NULL) + m_OutputCurves = new Interp[m_SeparationsOut]; + //read Input tables + if (TablePrecision == 1) + { + 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) + { + 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); + } + } + 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; + } + +void ColorTransf::SetGamutLimitsNlperCM(double *GamutLimitsNlperCM) +{ + //m_GamutLimitsNlperCM = DBG_NEW double[m_NGamutRegions]; + if(m_GamutLimitsNlperCM == NULL) + m_GamutLimitsNlperCM = new double[m_NGamutRegions]; + + for (int i = 0; i < m_NGamutRegions; ++i) + m_GamutLimitsNlperCM[i] = GamutLimitsNlperCM[i]; +} + +void ColorTransf::evalLab2InkP(double *ColorIn, double *&ColorOut, int &GamutRegion) +{ + //double *tmpColorOut = new double[m_SeparationsOut]; + C_RGB_XYZ_Lab tmpColorOut; + tmpColorOut = tmpColorOut.labdouble_to_labuint16(ColorIn); + /*Convert ColorIn to uint16 */ + uint16_t *iColorIn = new uint16_t[m_SeparationsIn]; + //uint16_t *iColorIn = DBG_NEW uint16_t[m_SeparationsIn]; + iColorIn[0] = uint16_t(tmpColorOut.Get_x()); + iColorIn[1] = uint16_t(tmpColorOut.Get_y()); + 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); + } + 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) + { + ColorOut[i] = tmpColor[i] * InkFactor / Uint16Factor; + ColorOut[i] = min(max(ColorOut[i], 0.0), 100.0); + } + GamutRegion = 0; + if(iColorIn !=NULL) + { + delete[] iColorIn; + iColorIn = NULL; + } + if (tmpColor != NULL) + { + delete[] tmpColor; + tmpColor = NULL; + } + + 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; + double tmpVal = 0.0; + for (int i = 0; i < m_SeparationsIn; ++i) + { + //convert to 16 bits + tmpVal = double(ColorIn[i] / InkFactor)*Uint16Factor; + tmpVal = min(max(tmpVal, 0.0), double(Uint16Factor)); + iColorIn[i] = uint16_t(tmpVal); + //Aply Input Curves + m_InputCurves[i].Eval((double)iColorIn[i], tmpIC); + ColorOut[i] = tmpIC * InkFactor / Uint16Factor; + ColorOut[i] = min(max(ColorOut[i], 0.0), double(InkFactor)); + } + + 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; + double tmpVal = 0.0; + for (int i = 0; i < m_SeparationsOut; ++i) + { + //convert to 16 bits + tmpVal = double(ColorIn[i] / InkFactor)*Uint16Factor; + tmpVal = min(max(tmpVal, 0.0), double(Uint16Factor)); + iColorIn[i] = uint16_t(tmpVal); + //Aply Output Curves + m_OutputCurves[i].Eval((double)iColorIn[i], tmpIC); + ColorOut[i] = tmpIC * InkFactor / Uint16Factor; + ColorOut[i] = min(max(ColorOut[i], 0.0), double(InkFactor)); + } + + if (iColorIn != NULL) + { + delete[] iColorIn; + iColorIn = NULL; + } + + return; +} + + +void ColorTransf::evalInkP2Lab(double *ColorIn, double *&ColorOut, int &GamutRegion) +{ + double *tmpColorOut = new double[m_SeparationsOut]; + //double *tmpColorOut = DBG_NEW double[m_SeparationsOut]; + /*Convert ColorIn to uint16 */ + uint16_t *iColorIn = new uint16_t[m_SeparationsIn]; + //uint16_t *iColorIn = DBG_NEW uint16_t[m_SeparationsIn]; + double tmpIC = 0; + double tmpVal = 0.0; + //convert to 16 bits + for (int i = 0; i < m_SeparationsIn; ++i) + { + tmpVal = min(max(double(ColorIn[i] / InkFactor)*Uint16Factor, 0.0), double(Uint16Factor)); + iColorIn[i] = uint16_t(tmpVal); + } + + //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) + { + tmpColorOut[i] = min(max(tmpColorOut[i], 0.0), double(Uint16Factor)); + m_OutputCurves[i].Eval((double)tmpColorOut[i], tmpIC); + tmpColorOut[i] = (unsigned short)tmpIC; + tmpColorOut[i] = min(max(tmpColorOut[i], 0.0), double(Uint16Factor)); + } + + //Normalize to Lab Space + C_RGB_XYZ_Lab tmpLabOut; + uint16_t int16ColorOut[3]; + for (int i=0; i<3; ++i) + int16ColorOut[i] = (uint16_t )(tmpColorOut[i]); + tmpLabOut = tmpLabOut.labuint16_to_labdouble(int16ColorOut); + ColorOut[0] = tmpLabOut.Get_x(); + ColorOut[1] = tmpLabOut.Get_y(); + ColorOut[2] = tmpLabOut.Get_z(); + //GamutRegion = 0; + if (iColorIn != NULL) + { + delete[] iColorIn; + iColorIn = NULL; + } + if (tmpColorOut != NULL) + { + delete[] tmpColorOut; + tmpColorOut = NULL; + } + + return; +} + +void ColorTransf::evalLinearInkP2Lab(double *ColorIn, double *&ColorOut, int &GamutRegion) +{ + double *tmpColorOut = new double[m_SeparationsOut]; + //double *tmpColorOut = DBG_NEW double[m_SeparationsOut]; + /*Convert ColorIn to uint16 */ + uint16_t *iColorIn = new uint16_t[m_SeparationsIn]; + //uint16_t *iColorIn = DBG_NEW uint16_t[m_SeparationsIn]; + double tmpIC = 0; + double tmpVal = 0.0; + //convert to 16 bits + for (int i = 0; i < m_SeparationsIn; ++i) + { + tmpVal = min(max(double(ColorIn[i] / InkFactor)*Uint16Factor, 0.0), double(Uint16Factor)); + iColorIn[i] = uint16_t(tmpVal); + } + + //Do not apply Input Curves + + 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"); + //Limit Values, do not apply Output Curves + for (int i = 0; i < m_SeparationsOut; ++i) + { + tmpColorOut[i] = min(max(tmpColorOut[i], 0.0), double(Uint16Factor)); + } + + //Normalize to Lab Space + C_RGB_XYZ_Lab tmpLabOut; + uint16_t int16ColorOut[3]; + for (int i = 0; i < 3; ++i) + int16ColorOut[i] = (uint16_t)(tmpColorOut[i]); + tmpLabOut = tmpLabOut.labuint16_to_labdouble(int16ColorOut); + ColorOut[0] = tmpLabOut.Get_x(); + ColorOut[1] = tmpLabOut.Get_y(); + ColorOut[2] = tmpLabOut.Get_z(); + //GamutRegion = 0; + if (iColorIn != NULL) + { + delete[] iColorIn; + iColorIn = NULL; + } + if (tmpColorOut != NULL) + { + delete[] tmpColorOut; + tmpColorOut = NULL; + } + + return; +} + +/* __declspec(dllexport) int ColorTransf::evalCMY2RGB(double *ColorIn, double *ColorOut) + { + //Assumption: ColorIn is in the interval [0,100] + double *tmpColorOut = new double[m_SeparationsIn]; //dimension of RGB + //Apply nonlinear transformation convert to linear, inks are in nonlinear space + double LinTmp = -1; + int ret = evalLinSingleCurve(m_CalCyan, m_nCalCyan, ColorIn[0], &LinTmp); + tmpColorOut[0] = LinTmp; + ret = evalLinSingleCurve(m_CalMagenta, m_nCalMagenta, ColorIn[1], &LinTmp); + tmpColorOut[1] = LinTmp; + ret = evalLinSingleCurve(m_CalYellow, m_nCalYellow, ColorIn[2], &LinTmp); + tmpColorOut[2] = LinTmp; + //tmpColorOut is in the [0,100] interval + + //Convert tmpColorOut to unsigned char + unsigned char *iColorOut = new unsigned char[m_SeparationsIn]; + for (int i = 0; i < m_SeparationsIn; ++i) + { + iColorOut[i] = (unsigned char)(fmin(fmax(round(tmpColorOut[i] * 2.55), 0), 255)); + } + if (m_SeparationsIn == 3) + m_InterpColor.ColorMap3(iColorOut, ColorOut); + else if (m_SeparationsIn == 4) + m_InterpColor.ColorMap4(iColorOut, ColorOut); + + delete[] iColorOut; + delete[] tmpColorOut; + return(0); + } +*/ \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.h new file mode 100644 index 000000000..e61135dae --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ColorTransf.h @@ -0,0 +1,55 @@ +#ifndef _COLORTRANSF_H_ +#define _COLORTRANSF_H_ + +#include +#include "NDInterpUtils.h" +#include "Interp.h" + +class ColorTransf { +public: + ColorTransf(); + ~ColorTransf(); + int GetNGridPoints() { return(m_nGridPoints); }; + int GetSeparationsIn() { return(m_SeparationsIn); }; + int GetSeparationsOut() { return(m_SeparationsOut); }; + int GetMSBShift() { return(m_MSBShift); }; + void evalLab2InkP(double *ColorIn, double *&ColorOut, int &GamutRegion); + void evalInkP2Lab(double *ColorIn, double *&ColorOut, int &GamutRegion); + void evalLinearInkP2Lab(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: + int m_MSBShift; + 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; + void free_char_array(char* charname); + + 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 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); +}; + +#endif diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Curves.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Curves.cpp new file mode 100644 index 000000000..4efd460ae --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Curves.cpp @@ -0,0 +1,155 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 +#include +#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), + m_InvInterpCurves(NULL) +{ + +} + +Curves::~Curves() +{ + if (m_InterpCurves != NULL) + { + delete[] m_InterpCurves; + m_InterpCurves = NULL; + } + if (m_InvInterpCurves != NULL) + { + delete[] m_InvInterpCurves; + m_InvInterpCurves = 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; + + //char *tmpC = DBG_NEW char[n] ; +// char tmpC[sizeof((char*)&tmpB)]; + //char Curvetype[sizeof((char*)&tmpB)+1]; + char Curvetype[sizeof(tmpB) + 1]; + Conv.getchar(tmpB, *Curvetype); + //char *luttype = DBG_NEW char[n + 1]; +// strcpy(Curvetype, tmpC); + int TablePrecision; + if (strncmp(Curvetype, "prc1", sizeof(tmpB)) == 0) + TablePrecision = 1; + else if (strncmp(Curvetype, "prc2", sizeof(tmpB)) == 0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in Color Tables"); + return; + } + + + // 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); + if(m_InterpCurves == NULL) + m_InterpCurves = new Interp[m_nChannels]; + if (m_InvInterpCurves == NULL) + m_InvInterpCurves = 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 +#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; + Interp *m_InvInterpCurves; +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/ColorLib/Tango.ColorLib_v6/Utils/GBD.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.cpp new file mode 100644 index 000000000..3e4f49878 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.cpp @@ -0,0 +1,340 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 "GBD.h" +#include +#include +#include "NumConversions.h" +#include "C_RGB_XYZ_Lab.h" + +using namespace std; + +#define eps 1.0e-05 +#define dE_Tol 2.0 +#define LargeNumber 1.0e+10 + +typedef enum { + TwoSided, + OneSided +}RTRI; + +typedef enum { + Line, + Ray, + Segment +}LineType; + +GBD::GBD() : + m_prec(0), m_nPCSChan(0), + m_nDevChan(0), m_CenterLab(0), m_nVertices(0), m_Vertices(NULL), + m_nTriangles(0), m_vert0(NULL), m_vert1(NULL), m_vert2(NULL) +{ + +} + +GBD::~GBD() +{ + if (m_vert0 != NULL) + { + for (int i = 0; i < m_nTriangles; ++i) + delete[] m_vert0[i]; + delete[] m_vert0; + m_vert0 = NULL; + } + if (m_vert1 != NULL) + { + for (int i = 0; i < m_nTriangles; ++i) + delete[] m_vert1[i]; + delete[] m_vert1; + m_vert1 = NULL; + } + if (m_vert2 != NULL) + { + for (int i = 0; i < m_nTriangles; ++i) + delete[] m_vert2[i]; + delete[] m_vert2; + m_vert2 = NULL; + } + if (m_Vertices != NULL) + { + delete[] m_Vertices; + m_Vertices = NULL; + } + +} + +void GBD::TriangleRayIntersection(double *origin, double *direction, bool &intersect, double *xCoor) +{ + int i, j; + + RTRI rtri = TwoSided; + LineType lt = Segment; + bool ok = false; + double border = eps; + double t = LargeNumber; + double u = t; + double v = t; + //double *edge1 = new double[3]; + //double *edge2 = new double[3]; + VectorXd tvec(3); + VectorXd qvec(3); + VectorXd pvec(3); + VectorXd edge1(3); + VectorXd edge2(3); + VectorXd VDirection(3); + VDirection << direction[0], direction[1], direction[2]; + //double *tvec = new double[3]; // vector from vert0 to ray origin + //double *pvec = new double[3]; + //double *qvec = new double[3]; + double det = 0; + bool angleOK = false; + for (i = 0; i < m_nTriangles; ++i) + { + for (j = 0; j < 3; ++j) + { + edge1(j)= m_vert1[i][j] - m_vert0[i][j]; + edge2(j) = m_vert2[i][j] - m_vert0[i][j]; + tvec(j) = origin[j] - m_vert0[i][j]; + } + crossProduct(VDirection, edge2, pvec); + det = dotProduct(edge1, pvec); + // std::cout << "edge1 " << edge1(0) <<" "<< edge1(1) <<" "<< edge1(2) << "\n"; + // std::cout << "edge2 " << edge2(0) << " " << edge2(1) << " " << edge2(2)<< "\n"; + // std::cout << "tvec " << tvec(0) << " " << tvec(1) << " " << tvec(2) << "\n"; + // std::cout << "crossProduct " << pvec(0) << " " << pvec(1) << " " << pvec(2)<< "\n"; + // std::cout << "Det " << det << "\n"; + + switch (rtri) + { + case TwoSided: + if (std::abs(det) > eps) + angleOK = true; + break; + case OneSided: + if (det > eps) + angleOK = true; + break; + default: + throw std::exception("Wrong Parameterin Ray-TriageIntersetion"); + } + //determinant GT 0 + if (std::abs(det) > eps) + { + u = dotProduct(tvec, pvec) / det; + crossProduct(tvec, edge1, qvec); + v = dotProduct(VDirection, qvec) / det; + t = dotProduct(edge2, qvec) / det; + ok = (angleOK && (u >= -eps) && (v >= -eps) && ((u + v) <= 1 + eps)); + // std::cout << "u " << u << "\n"; + // std::cout << "v " << v << "\n"; + // std::cout << "Qvec " << qvec(0) << " " << qvec(1) << " " << qvec(2) << "\n"; + // std::cout << "t " << t << "\n"; + // std::cout << "OK " << ok << "\n"; + } + else + ok = false; + + switch (lt) + { + case Line: + intersect = ok; + break; + case Ray: + intersect = ok && (t >= -eps); + break; + case Segment: + intersect = ok && (t >= -eps) && (t <= 1 + eps); + break; + default: + throw std::exception("Wrong Line Type"); + break; + } + if (intersect) + { + for (j = 0; j < 3; ++j) + xCoor[j] = m_vert0[i][j] + edge1(j) * u + edge2(j) * v; + return; + } + } + + return; +} + +void GBD::InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize) +{ + // 0-3 prec + //4-7 reserved, must be 0 + // 8-9 number of vertices, uint16 + // 10-11 number of triangles, uint16 + // 12 number of PCS Channels, uint8 + // 13 number of device channels (0, no device data) + // prec 2 (16bit) + // 14-n triangle vertices arranged as vert0 -> vert1->vert2 + // each vert is a matrix of size (number of vertices)x3 + // Gamut is stored in Ciecam02 color space + // prec 1 + // 14-n CLUT values, uint8 + + if (colorTransformFileSize < 32) + { + throw std::exception("Init GB, invalid size"); + } + + // Check for signature + unsigned char *buffer = colorTransformBuffer; + if (buffer == NULL) + { + throw std::exception("Memory Error, ColorTransf::InitData"); + } + + int i, j; + NumConversions Conv; + int bytesread = 0; + int tmpB = Conv.ByteToInt(buffer, 0); + bytesread += 4; + + int n = sizeof(tmpB); + //char *tmpC = DBG_NEW char[n]; + //char tmpC[sizeof((char*)&tmpB)]; + char tableType[sizeof(tmpB)+1]; + Conv.getchar(tmpB, *tableType); + //char *tableType = DBG_NEW char[n + 1]; +// strcpy(tableType, tmpC); + + int TablePrecision; + if (strncmp(tableType, "prc1", sizeof(tmpB)) == 0) + TablePrecision = 1; + else if (strncmp(tableType, "prc2", sizeof(tmpB)) == 0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in gbd tables"); + return; + } + + // Skip past reserved padding bytes + bytesread += 4; + uint16_t num_gbd_points = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + SetNVertices((int)num_gbd_points); + uint16_t num_triangles = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + SetNTriangles((int)num_triangles); + uint8_t num_PCSChan = buffer[bytesread]; + bytesread += 1; + SetNPCS_Channels((int)num_PCSChan); + bytesread += 1; + uint8_t num_DevChan = buffer[bytesread]; + SetNDev_Channels((int)num_DevChan); + uint16_t ILab[3]; + for (j = 0; j < 3; ++j) + { + ILab[j] = (uint16_t)Conv.ByteToInt(buffer, bytesread); + bytesread += 4; + } + C_RGB_XYZ_Lab tmpCenter; + m_CenterLab = tmpCenter.labuint16_to_labdouble(ILab); + + // lut8Type and lut16Type + int remsize = colorTransformFileSize - bytesread; + int Bsize = (int)((int)(num_gbd_points) * (int)num_PCSChan); + if (remsize != Bsize * (int)TablePrecision) + { + throw std::exception("GBD size missmatch"); + return; + } + + if(m_vert0 == NULL) + m_vert0 = new double*[m_nTriangles]; + if (m_vert1 == NULL) + m_vert1 = new double*[m_nTriangles]; + if (m_vert2 == NULL) + m_vert2 = new double*[m_nTriangles]; + + /*m_vert0 = DBG_NEW double*[m_nTriangles]; + m_vert1 = DBG_NEW double*[m_nTriangles]; + m_vert2 = DBG_NEW double*[m_nTriangles];*/ + uint16_t tmp[3]; + C_RGB_XYZ_Lab tmp1; + for (i = 0; i < m_nTriangles; ++i) + { + m_vert0[i] = new double[m_nPCSChan]; + //m_vert0[i] = DBG_NEW double[m_nPCSChan]; + for (j = 0; j < m_nPCSChan; ++j) + { + tmp[j] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + } + tmp1 = tmp1.labuint16_to_labdouble(tmp); + m_vert0[i][0] = tmp1.Get_x(); + m_vert0[i][1] = tmp1.Get_y(); + m_vert0[i][2] = tmp1.Get_z(); + } + for (i = 0; i < m_nTriangles; ++i) + { + m_vert1[i] = new double[m_nPCSChan]; + //m_vert1[i] = DBG_NEW double[m_nPCSChan]; + + for (j = 0; j < m_nPCSChan; ++j) + { + tmp[j] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + } + tmp1 = tmp1.labuint16_to_labdouble(tmp); + m_vert1[i][0] = tmp1.Get_x(); + m_vert1[i][1] = tmp1.Get_y(); + m_vert1[i][2] = tmp1.Get_z(); + } + for (i = 0; i < m_nTriangles; ++i) + { + m_vert2[i] = new double[m_nPCSChan]; + //m_vert2[i] = DBG_NEW double[m_nPCSChan]; + for (j = 0; j < m_nPCSChan; ++j) + { + tmp[j] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + } + tmp1 = tmp1.labuint16_to_labdouble(tmp); + m_vert2[i][0] = tmp1.Get_x(); + m_vert2[i][1] = tmp1.Get_y(); + m_vert2[i][2] = tmp1.Get_z(); + } +} + + +// dot product of two vectors. +double GBD::dotProduct(VectorXd vect_A, VectorXd vect_B) +{ + double product = 0.0; + // Loop for calculate dot product + + int n = vect_A.size(); + for (int i = 0; i < n; i++) + product = product + vect_A(i) * vect_B(i); + return (product); +} + + +// cross product of two vectors +void GBD::crossProduct(VectorXd vect_A, VectorXd vect_B, VectorXd &cross_P) +{ + cross_P(0) = vect_A(1) * vect_B(2) - vect_A(2) * vect_B(1); + cross_P(1) = -vect_A(0) * vect_B(2) + vect_A(2) * vect_B(0); + cross_P(2) = vect_A(0) * vect_B(1) - vect_A(1) * vect_B(0); + return; +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.h new file mode 100644 index 000000000..61aadf37a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/GBD.h @@ -0,0 +1,38 @@ +#ifndef _GBD_H_ +#define _GBD_H_ + +#include +#include "C_RGB_XYZ_Lab.h" + +class GBD { +public: + GBD(); + ~GBD(); + int GetNVertices() { return(m_nVertices); }; + int GetNPCS_Channels() { return(m_nPCSChan); }; + int GetDev_Channels() { return(m_nDevChan); }; + int GetNTriangles() { return(m_nTriangles); }; + C_RGB_XYZ_Lab getCenter(){ return(m_CenterLab);}; + void InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize); + void TriangleRayIntersection(double *origin, double *direction, bool &intersect, double *xCoor); +private: + int m_prec; + int m_nDevChan; + int m_nPCSChan; + int m_nVertices; + int m_nTriangles; + C_RGB_XYZ_Lab m_CenterLab; + C_RGB_XYZ_Lab *m_Vertices; + double **m_vert0; + double **m_vert1; + double **m_vert2; + void SetNVertices(int nVertices) { m_nVertices = nVertices; }; + void SetNPCS_Channels(int nPCSChan) { m_nPCSChan = nPCSChan; }; + void SetNDev_Channels(int nDevChan) { m_nDevChan = nDevChan; }; + void SetNTriangles(int nTriangles) { m_nTriangles = nTriangles; }; + //void SetCenter( C_RGB_XYZ_Lab CenterLab); + double dotProduct(VectorXd vect_A, VectorXd vect_B); + void crossProduct(VectorXd vect_A, VectorXd vect_B, VectorXd &cross_P); +}; + +#endif diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.cpp new file mode 100644 index 000000000..c2878d156 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.cpp @@ -0,0 +1,45 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "Gradient.h" + +using namespace std; +Gradient::Gradient() : + m_Lab(0), m_RGB(0), + m_Volume(NULL), m_GamutRegion(0), m_Offset(0.0), m_colorspace(COLOR_SPACE__RGB), + m_InGamut(true), m_CatalogInks(NULL) +{ + +} + + +Gradient::~Gradient() +{ + if (m_Volume != NULL) + { + delete[] m_Volume; + m_Volume = NULL; + } + if (m_CatalogInks != NULL) + { + delete[] m_CatalogInks; + m_CatalogInks = NULL; + } +} + +void Gradient::SetVolumeSize(int nchannels) +{ + if(m_Volume == NULL) + m_Volume = new double[nchannels]; +} + +void Gradient::SetVolumeValue(double val, int ind) +{ + m_Volume[ind] = val; +} + +void Gradient::SetCatalogInkValues(double val, int ind) +{ + m_Volume[ind] = val; +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.h new file mode 100644 index 000000000..92e66bb18 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Gradient.h @@ -0,0 +1,39 @@ +#ifndef _GRADIENT_H_ +#define _GRADIENT_H_ + +#include "C_RGB_XYZ_Lab.h" +#include "ColorSpace.pb-c.h" +class Gradient { +public: + Gradient(); + ~Gradient(); + int Get_GamutRegion() { return(m_GamutRegion); }; + double Get_Offset() { return(m_Offset); }; + ColorSpace Get_ColorSpace() {return(m_colorspace);}; + C_RGB_XYZ_Lab Get_Lab() { return(m_Lab); }; + C_RGB_XYZ_Lab Get_RGB() { return(m_RGB); }; + bool Get_InGamut() { return(m_InGamut); }; + void Set_GamutRegion(int GamutRegion) { m_GamutRegion = GamutRegion; }; + void Set_Lab(C_RGB_XYZ_Lab Lab) { m_Lab = Lab; }; + void Set_RGB(C_RGB_XYZ_Lab RGB) { m_RGB = RGB; }; + void Set_Offset(double Offset) { m_Offset = Offset; }; + void Set_ColorSpace(ColorSpace colorspace) { m_colorspace = colorspace; }; + void SetVolumeSize(int nchannels); + void SetVolumeValue(double val, int ind); + void SetInGamut(bool InGamut) { m_InGamut = InGamut; }; + void SetCatalogInkValues(double val, int ind); + void SetInRGBLimits(bool InRGBLimits) { m_InRGBLimits = InRGBLimits; }; + bool Get_InRGBLimits() { return(m_InRGBLimits); }; +private: + C_RGB_XYZ_Lab m_Lab; + C_RGB_XYZ_Lab m_RGB; + double *m_Volume; + int m_GamutRegion; + double m_Offset; + ColorSpace m_colorspace; + bool m_InGamut; + bool m_InRGBLimits; + double *m_CatalogInks; +}; + +#endif \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.cpp new file mode 100644 index 000000000..ba66ca114 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.cpp @@ -0,0 +1,127 @@ +#include "Interp.h" +#include +#include +#include +#include +#include + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 */ + +#define epsTol 0.05 + +Interp::Interp(void):m_xValues(NULL), m_yValues(NULL) , m_length(0) +{ +} + +Interp::Interp(const Interp &rhs):m_xValues(NULL), m_yValues(NULL), m_length(0) +{ +} + +Interp::~Interp() +{ + if (m_xValues != NULL) + { + delete[] m_xValues; + m_xValues = NULL; + } + if (m_yValues != NULL) + { + delete[] m_yValues; + m_yValues = NULL; + } +} + +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]; + if (m_yValues == NULL) + //m_yValues = DBG_NEW double(m_length); + m_yValues = new double[m_length]; + + for (int i=0; im_xValues[m_length - 1] + epsTol)) + throw std::exception("Interp Eval: Value out of Bounds"); + if ((InValue > m_xValues[0] - epsTol) && (InValue < m_xValues[0])) + InValue = m_xValues[0]; + + if ((InValue > m_xValues[m_length - 1] ) && (InValue < m_xValues[m_length - 1]+ epsTol)) + InValue = m_xValues[m_length - 1]; + + for (m = 0; m < m_length - 1; ++m) + { + if (m_xValues[m] <= InValue && m_xValues[m + 1] >= InValue) + { + ind = m; + break; + } + } + if (ind == -1) + { + throw std::exception ("Could not find interpolation interval"); + } + OutValue = ((InValue - m_xValues[m])*m_yValues[m + 1] + (m_xValues[m + 1] - InValue)*m_yValues[m]) + / (m_xValues[m + 1] - m_xValues[m]); + return; +} + +void Interp::Eval(int InValue, int &OutValue) +{ + int m; + int errType = 0; + int ind = 0; + double d_InValue; + + ind = -1; + d_InValue = (double)InValue; + //Check Bounds + if ((d_InValuem_xValues[m_length - 1] + epsTol)) + throw std::exception("Interp Eval: Value out of Bounds"); + if ((d_InValue > m_xValues[0] - epsTol) && (d_InValue < m_xValues[0])) + d_InValue = m_xValues[0]; + + if ((d_InValue > m_xValues[m_length - 1]) && (d_InValue < m_xValues[m_length - 1] + epsTol)) + d_InValue = m_xValues[m_length - 1]; + for (m = 0; m < m_length - 1; ++m) + { + if (m_xValues[m] <= d_InValue && m_xValues[m + 1] >= d_InValue) + { + ind = m; + break; + } + } + if (ind == -1) + { + throw std::exception("Could not find interpolation interval"); + } + OutValue= (int)round(((d_InValue - m_xValues[m])*m_yValues[m + 1] + (m_xValues[m + 1] - d_InValue)*m_yValues[m]) + / (m_xValues[m + 1] - m_xValues[m])); + return; + +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.h new file mode 100644 index 000000000..eef16546e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/Interp.h @@ -0,0 +1,24 @@ +#ifndef __INTERP_H__ +#define __INTERP_H__ + +class Interp +{ + public: + Interp(void); + Interp(const Interp &rhs); + ~Interp(); + void Eval(double InValue, double &OutValue); + void Eval(int InValue, int &OutValue); + void Init(double *xValues, double *yValues, int nlength); + void SetXCoords(double* xCoords) {m_xValues = xCoords;}; + void SetYCoords(double * yCoords) { m_yValues = yCoords; }; + void SetNPoints(int npts) { m_length = npts; }; + private: + double *m_xValues; + double* m_yValues; + int m_length; + +}; +#endif // __INTERP_H__ + + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.cpp new file mode 100644 index 000000000..4d33ca9b9 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.cpp @@ -0,0 +1,129 @@ +#include +#include "LULinearSolver.h" +#include + +LULinearSolver::LULinearSolver() +{ + +} + +LULinearSolver::~LULinearSolver() +{ + +} + +void LULinearSolver::LUBacksubstitution(double **a, int *indx, double *b, int nSize) +{ + int i, ii = 0, ip, j; + double sum; + + for (i = 0; i < nSize; i++) { + ip = indx[i]; + sum = b[ip]; + b[ip] = b[i]; + if (ii != 0) { + for (j = ii - 1; j < i; j++) { + sum -= a[i][j] * b[j]; + } + } + else if (sum != 0.0) { + ii = i + 1; + } + b[i] = sum; + } + for (i = nSize - 1; i >= 0; i--) { + sum = b[i]; + for (j = i + 1; j < nSize; j++) { + sum -= a[i][j] * b[j]; + } + b[i] = sum / a[i][i]; + } + return; +} + + + +bool LULinearSolver::LUDecomposition(double **a, int *indx, int nSize) +{ + const double k_dTiny = 1.0e-20; + int i, imax = 0, j, k; + double d, big, dum, sum, temp; + + double *vv = new double[nSize]; + d = 1.0; + for (i = 0; i < nSize; i++) { + big = 0.0; + for (j = 0; j < nSize; j++) { + if ((temp = fabs(a[i][j])) > big) { + big = temp; + } + } + if (big == 0.0) { + // matrix is singular or nearly so + if (vv != NULL) + delete[] vv; + return (false); + } + vv[i] = 1.0 / big; + } + for (j = 0; j < nSize; j++) { + for (i = 0; i < j; i++) { + sum = a[i][j]; + for (k = 0; k < i; k++) { + sum -= a[i][k] * a[k][j]; + } + a[i][j] = sum; + } + big = 0.0; + for (i = j; i < nSize; i++) { + sum = a[i][j]; + for (k = 0; k < j; k++) { + sum -= a[i][k] * a[k][j]; + } + a[i][j] = sum; + if ((dum = vv[i] * fabs(sum)) >= big) { + big = dum; + imax = i; + } + } + if (j != imax) { + for (k = 0; k < nSize; k++) { + dum = a[imax][k]; + a[imax][k] = a[j][k]; + a[j][k] = dum; + } + d = -d; + vv[imax] = vv[j]; + } + indx[j] = imax; + if (a[j][j] == 0.0) { + a[j][j] = k_dTiny; + } + if (j != nSize - 1) { + dum = 1.0 / (a[j][j]); + for (i = j + 1; i < nSize; i++) { + a[i][j] *= dum; + } + } + } + if (vv != NULL) + delete[] vv; + return(true); +} + + + +// Solve linear system A.x=b based on L-U decomposition. A and b are destroyed in the process. x is returned in b. +bool LULinearSolver::LUSolver(double **A, double *b, unsigned int nSize) +{ + int *indx = new int[nSize]; + if (!LUDecomposition(A, indx, nSize)) { + if (indx != NULL) + delete[] indx; + return(false); + } + LUBacksubstitution(A, indx, b, nSize); + if (indx != NULL) + delete[] indx; + return(true); +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.h new file mode 100644 index 000000000..c3d13be27 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LULinearSolver.h @@ -0,0 +1,13 @@ +#ifndef __LULINEARSOLVER_H__ +#define __LULINEARSOLVER_H__ + +class LULinearSolver +{ +public: + LULinearSolver(); + ~LULinearSolver(); + void LUBacksubstitution(double **a, int *indx, double *b, int nSize); + bool LUDecomposition(double **a, int *indx, int nSize); + bool LUSolver(double **A, double *b, unsigned int nSize); +}; +#endif // __LULINEARSOLVER_H__ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.cpp new file mode 100644 index 000000000..865713737 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.cpp @@ -0,0 +1,457 @@ +#include "LevMar.h" +#include "C_RGB_XYZ_Lab.h" +#include "ObjectiveFunction.h" +#include "LULinearSolver.h" +#include +#include +#include +#include +#include + +const double kLarge = 1e+20; +const double kTiny = 1e-20; +const double kIllegalValue = -1.0; +const double kLimitFraction = (0.9); + +#define MaxNumIterations 100 +#define InitialLamda 0.001 +#define Delta 5.0E-4 + +LevMar::LevMar(ObjectiveFunction *func) : + m_InitialLamda(0.001), + m_NData(0), + m_Delta(5.0E-4), + m_Epsilon(1.0E-1), + m_Iterations(0), + m_nFreeParams(0), + m_nFixedParams(0), + m_FreeParams(NULL), + m_FixedParams(NULL), + m_FreeParamIndex(NULL), + m_FixedParamIndex(NULL), + m_Params(NULL), + m_Ycalc(NULL), + m_YRef(NULL), + m_beta(NULL), + m_RHS(NULL), + m_alpha(NULL), + m_Matrix(NULL), + m_currentVec(NULL), + m_tryVec(NULL), + m_UpperBound(NULL), + m_LowerBound(NULL), + m_PartialDerivatives(NULL), + m_func(func), + m_LULS(NULL) +{ + SetMaxIterations(100); // useid in Minimization + SetTolerance(1.0E-6); // Convergence tolerance +} + + +LevMar::~LevMar() +{ + if (m_beta != NULL) { + delete[] m_beta; + m_beta = NULL; + } + if (m_RHS != NULL) { + delete[] m_RHS; + m_RHS = NULL; + } + if(m_alpha != NULL) + { + for (int i = 0; i < (int)m_nFreeParams; i++) + { + delete[] m_alpha[i]; + } + delete[] m_alpha; + m_alpha = NULL; + } + if (m_Matrix != NULL) + { + for (int i = 0; i < (int)m_nFreeParams; i++) + { + delete[] m_Matrix[i]; + } + delete[] m_Matrix; + m_Matrix = NULL; + } + + if (m_Ycalc != NULL) { + delete[] m_Ycalc; + m_Ycalc = NULL; + } + if (m_Params != NULL) { + delete[] m_Params; + m_Params = NULL; + } + if (m_currentVec != NULL) { + delete[] m_currentVec; + m_currentVec = NULL; + } + if (m_tryVec != NULL) { + delete[] m_tryVec; + m_tryVec = NULL; + } + if (m_YRef != NULL) { + delete[] m_YRef; + m_YRef = NULL; + } + if (m_PartialDerivatives != NULL) { + for (int i = 0; i < (int)m_nFreeParams; i++) + delete[] m_PartialDerivatives[i]; + delete[] m_PartialDerivatives; + m_PartialDerivatives = NULL; + } + if (m_LULS != NULL) + { + delete[] m_LULS; + m_LULS = NULL; + } +} + +void LevMar::Init() +{ + //Set parameters + int i = 0; + m_nFreeParams = m_func->GetNumFreeParams(); + m_nFixedParams = m_func->GetNumFixedParams(); + m_FreeParams = NULL; + m_NData = m_func->GetNumOutResult(); + m_Ycalc = new double[m_NData]; + m_Params = new double[m_nFixedParams + m_nFreeParams]; + m_FreeParamIndex = m_func->GetFreeParamsIndex(); + m_FixedParamIndex = m_func->GetFixedParamsIndex(); + m_LULS = new LULinearSolver(); + //allocate work arrays + m_currentVec = new double[m_nFreeParams]; + m_tryVec = new double[m_nFreeParams]; + m_YRef = new double[m_NData]; + //Upper and Lower Bounds +#if 0 + m_UpperBound = new double[m_numFreeParams]; + m_LowerBound = new double[m_numFreeParams]; +#endif + // Partial Derivatives + m_PartialDerivatives = new double*[m_nFreeParams]; + for (i = 0; i < (int)m_nFreeParams; i++) + m_PartialDerivatives[i] = new double[m_NData]; + + m_UpperBound = m_func->GetUpperBound(); + m_LowerBound = m_func->GetLowerBound(); + + m_beta = new double[m_nFreeParams]; + m_RHS = new double[m_nFreeParams]; + m_alpha = new double*[m_nFreeParams]; + m_Matrix = new double*[m_nFreeParams]; + for (i = 0; i < (int)m_nFreeParams; i++) + { + m_alpha[i] = new double[m_nFreeParams]; + m_Matrix[i] = new double[m_nFreeParams]; + } +} + +double LevMar::ResidualSumSquares() +{ + int i; + double fVal = 0.0; // objective function + + // Limit Parameters to Upper and Lower Bounds + for (i = 0; i < (int)m_nFreeParams; i++) + { + m_tryVec[i] = m_currentVec[i] + m_RHS[i]; //m_RHS contains the solution to the system of linear equations + //Check Lower Bound + if (m_tryVec[i] < m_LowerBound[i]) + { + m_tryVec[i] = m_currentVec[i] - kLimitFraction * (m_currentVec[i] - m_LowerBound[i]); + m_RHS[i] = m_tryVec[i] - m_currentVec[i]; + } + // Check Upper Bound + if (m_tryVec[i] > m_UpperBound[i]) + { + m_tryVec[i] = m_currentVec[i] + kLimitFraction * (m_UpperBound[i] - m_currentVec[i]); + m_RHS[i] = m_tryVec[i] - m_currentVec[i]; + } + } + //Set parameters values + for (i = 0; i < (int)m_nFreeParams; ++i) + m_Params[m_FreeParamIndex[i]] = m_tryVec[i]; + m_func->EvaluateObjectiveFunction(m_Params, m_Ycalc); + + for (i = 0; i < (int)m_NData; i++) + m_YRef[i] = m_Ycalc[i]; + + // Sum up squares + for (i = 0; i < (int)m_NData; i++) + fVal += m_Ycalc[i] * m_Ycalc[i]; + + return (fVal); +} + + +void LevMar::Eval_alpha_and_beta() +{ + int iRows, jCols, k; + double dx; //used to calculate the partial derivatives + + // zero out matrix Alpha and Vector Beta + for (iRows = 0; iRows < (int)m_nFreeParams; iRows++) + { + for (jCols = 0; jCols < (int)m_nFreeParams; jCols++) + m_alpha[iRows][jCols] = 0.0; + m_beta[iRows] = 0.0; + } + + // Calculate Partial Derivatives + for (iRows = 0; iRows < (int)m_nFreeParams; iRows++) { + // avoid upper and lower bounds + dx = fabs(m_currentVec[iRows] - m_LowerBound[iRows]) < fabs(m_UpperBound[iRows] - m_currentVec[iRows]) ? + m_Epsilon : -m_Epsilon; + + for (jCols = 0; jCols < (int)m_nFreeParams; jCols++) + { + m_Params[jCols] = m_currentVec[jCols]; + } + m_Params[iRows] += dx; // add dx to the ith parameter + + m_func->EvaluateObjectiveFunction(m_Params, m_Ycalc); + + // Calculate the derivative in the ith direction + for (k = 0; k < (int)m_NData; k++) { + m_PartialDerivatives[iRows][k] = (m_Ycalc[k] - m_YRef[k]) / dx; //Partial Derivative of individual Components + for (jCols = 0; jCols <= iRows; jCols++) { //Fill up the lower triangle + m_alpha[iRows][jCols] += m_PartialDerivatives[iRows][k] * m_PartialDerivatives[jCols][k]; //Sum up the elements + } + m_beta[iRows] -= m_PartialDerivatives[iRows][k] * m_YRef[k]; //Sum up the elements + } + } // iRows + + + // check for ill-behaved matrix components to avoid matrix-inversion problems + for (iRows = 0; iRows < (int)m_nFreeParams; iRows++) { + // ~zero slope = local minimum in this parameter + // --> set up mAlpha, mBeta for a ~zero-length parameter step + if (fabs(m_beta[iRows]) < kTiny) { + m_alpha[iRows][iRows] = 1.0; + } + + // ~infinite slope = objective function is 'hypersensitive' to this parameter + // --> set up mAlpha, mBeta for parameter step that changes parameter value + // by one order of magnitude in the appropriate direction + if (fabs(m_beta[iRows]) > kLarge) { + m_beta[iRows] = ((m_beta[iRows] > 0.0 ? 10.0 : 0.1) - 1.0) * m_currentVec[iRows]; + for (jCols = 0; jCols < iRows; ++jCols); + m_alpha[iRows][jCols] = 0.0; + m_alpha[iRows][iRows] = kIllegalValue; + } + } + + // Complete the Upper triangular side of m_Alpha + for (iRows = 1; iRows < (int)m_nFreeParams; iRows++) + for (jCols = 0; jCols < iRows; jCols++) + m_alpha[jCols][iRows] = m_alpha[iRows][jCols]; +} + +double LevMar::IncreaseStep() +{ + int i; + //Calculate the angle between the Search Direction and Negative Gradient, if there is good agreement, + //the angle is zero and cos(angle)=1, set the stepsize factor 2, + //if there is no agreement, cos(angle) = -1, + //set the stepsize factor to 2*10^2, a very large step + double innerProd = 0.0; + double StepLength2 = 0.0; + double GradLength2 = 0.0; + double cos_angle; + + for (i = 0; i < (int)m_nFreeParams; i++) + { + StepLength2 += m_RHS[i] * m_RHS[i] * m_alpha[i][i]; + GradLength2 += 4.0 * m_beta[i] * m_beta[i]/ m_alpha[i][i]; + innerProd += m_RHS[i] * 2.0 * m_beta[i]; + } + cos_angle = innerProd / sqrt(StepLength2 * GradLength2); + + return (2.0 * pow(10.0, 1.0 - cos_angle)); +} + + +double LevMar::ReduceStep(const double &d_f, const double &uphill, const double &downhill) const +{ +// extend step by making lambda smaller according to how well f approximates +// a quadratic; +//calculate the reduction factor for lambda + int i, j; + double d_f_quadr_proj = 0.0; // d_f predicted by quadratic extrapolation + double match; // indicates deviation from quadratic shape + + // check how well f matches a quadratic function over last step + for (i = 0; i < (int)m_nFreeParams; i++) + { + d_f_quadr_proj += -2.0 * m_beta[i] * m_RHS[i]; + for (j = 0; j < (int)m_nFreeParams; j++) + { + d_f_quadr_proj += m_alpha[i][j] * m_RHS[i] * m_RHS[j]; + } + } + + // match gains in significance as lambda-->small, i.e, for large steps + match = d_f_quadr_proj / d_f; + if (fabs(match) > 1.0) + { + match = 1.0 / match; // 0 < match <= 1 + } + + // decrease lambda according to-- + // (1) how well the minimization went on average over the last few iterations + // (2) how well f approximates a quadratic over the last step + return (pow(downhill / uphill, -match)); +} + + +double LevMar::MinimizationAlgorithm(double *FreeParams, double *FixedParams, unsigned int &n_iterations) +{ + + int i, j; + double fmin = kLarge; + double fRSS; + double Lambda; + double uphill = 0.1, downhill = 1.0; // moving averages tracking recent history + double fbest = kLarge; + bool improved = true; + m_FreeParams = FreeParams; + m_FixedParams = FixedParams; + for (i = 0; i < (int)m_nFreeParams; ++i) + m_Params[m_FreeParamIndex[i]] = FreeParams[i]; + for (i = 0; i < (int)m_nFixedParams; ++i) + m_Params[m_FixedParamIndex[i]] = FixedParams[i]; + + //Evaluate Function + m_Iterations = 0; +//double funVal; +// funVal = m_func->EvaluateObjectiveFunction(m_Params, m_Ycalc); + +// for (j = 0; j < (int)m_NData; j++) +// m_YRef[j] = 0.0; + + // Init Partial Derivatives + for (i = 0; i < (int)m_nFreeParams; i++) + { + for (j = 0; j < (int)m_NData; j++) + m_PartialDerivatives[i][j] = 0; + } + // Init Alpha, Beta, Matrix and Right Hand Side (see Numerical Recipes) + + for (i = 0; i < (int)m_nFreeParams; i++) + { + for (j = 0; j < (int)m_nFreeParams; j++) + { + m_alpha[i][j] = 0.0; + m_Matrix[i][j] = 0.0; + } + m_currentVec[i] = 0.0; + m_tryVec[i] = 0.0; + m_beta[i] = 0.0; + m_RHS[i] = 0.0; + } + + double df; + + while (fabs(fmin) > m_Tolerance && improved && m_Iterations < m_MaxNumIterations) + { + for (i = 0; i < (int)m_nFreeParams; ++i) + m_currentVec[i] = m_Params[m_FreeParamIndex[i]]; + //zero out Right Hand Side of the equation + for (i = 0; i < (int)m_nFreeParams; i++) + m_RHS[i] = 0.0; + fmin = ResidualSumSquares(); + Lambda = m_InitialLamda; + improved = false; + //Eval alpha and Beta at initial point + Eval_alpha_and_beta(); + //Iterate + while (m_Iterations < m_MaxNumIterations) + { + m_Iterations++; + //Prepare data for Solution of Linear Equations + for (i = 0; i < (int)m_nFreeParams; ++i) + m_RHS[i] = m_beta[i]; + //prepare m_Matrix matrix = Alpha.(1+Lambda.I) + for (i = 0; i < (int)m_nFreeParams; i++) + { + for (j = 0; j < (int)m_nFreeParams; j++) + { + if (i == j) + { + if (m_alpha[i][i] == kIllegalValue) + m_Matrix[i][i] = 1.0; + else + m_Matrix[i][i] = m_alpha[i][i] * (1 + Lambda); + } + else + m_Matrix[i][j] = m_alpha[i][j]; + } + } + + bool bRet = m_LULS->LUSolver(m_Matrix, m_RHS, m_nFreeParams); + if (bRet != true) + return(-1); + + uphill *= 0.8; + downhill *= 0.8; // update moving averages + fRSS = ResidualSumSquares(); + if (fRSS > fmin) + { + //increase step Lambda + uphill += 0.2; + double Factor = IncreaseStep(); + Lambda *= Factor; + } + else + { + //update data, check convergence, calculate next step + downhill += 0.2; + df = fRSS - fmin; // d_f is <= 0. + fmin = fRSS; + for (i = 0; i < (int)m_nFreeParams; i++) + m_currentVec[i] = m_tryVec[i]; + + // check if done + if (((2.0 * fabs(df)) <= (m_Delta * (fabs(fRSS) + fabs(fmin)))) || (fabs(fmin) < m_Tolerance)) { + break; // exit after convergence + } + + // if not done yet, try a bolder step-- + // decrease lambda according to how well f approximates a quadratic + Lambda *= ReduceStep(df, uphill, downhill); + + // get curvature matrix mAlpha and vector mBeta at new minimum + Eval_alpha_and_beta(); + } + }//end iterations + // Save in parameter vectors + for (i = 0; i < (int)m_nFreeParams; ++i) + m_Params[m_FreeParamIndex[i]] = m_currentVec[i]; + + if (fabs(fmin) < fabs(fbest)) { + for (i = 0; i < (int)m_nFreeParams; ++i) + FreeParams[i] = m_currentVec[m_FreeParamIndex[i]]; + } + + if ((fbest - fmin) > (m_Delta * fabs(fmin))) { + fbest = fmin; + improved = true; + } + } //end outer loop + n_iterations = m_Iterations; + return (fmin); +} + +void LevMar::SetLabIn(double * LabIn) +{ + for (int i = 0; i < 3; ++i) + m_YRef[i] = LabIn[i]; +} + + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.h new file mode 100644 index 000000000..fff02fe0a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/LevMar.h @@ -0,0 +1,66 @@ +#ifndef __LEVMAR_H__ +#define __LEVMAR_H__ +#include "C_RGB_XYZ_Lab.h" +#include "ColorTable.h" +#include "ObjectiveFunction.h" +#include "LULinearSolver.h" + +class LevMar +{ +public: + LevMar(ObjectiveFunction *func); + ~LevMar(); + double MinimizationAlgorithm(double *FreeParams, double *Fixedparams, unsigned int &n_iterations); + void SetMaxIterations(unsigned int MaxIterations) { m_MaxNumIterations = MaxIterations; }; + void SetTolerance(const double &Tol) { m_Tolerance = Tol; }; + void SetDerivH(double Epsilon) { m_Epsilon = Epsilon; }; + double *GetLabOut() { return(m_Ycalc); }; + void SetLabIn(double * LabIn); + void Init(); + void SetInverseFunction(ObjectiveFunction *func) { m_func = func; }; + +private: + double m_Tolerance; + unsigned int m_MaxNumIterations; + unsigned int m_Iterations; + unsigned int m_NData; + double m_InitialLamda; + double m_Delta; + double m_Epsilon; + + unsigned int m_nFreeParams; + unsigned int m_nFixedParams; + unsigned int m_nParams; + unsigned int *m_FreeParamIndex; + unsigned int * m_FixedParamIndex; + double *m_UpperBound; + double *m_LowerBound; + double *m_FreeParams; + double *m_FixedParams; + double *m_Params; + double *m_Ycalc; + double *m_YRef; + double *m_beta; + double *m_RHS; + double ** m_alpha; + double **m_Matrix; + double *m_currentVec; + double *m_tryVec; + double **m_PartialDerivatives; + ObjectiveFunction *m_func; + C_RGB_XYZ_Lab m_WPLabRel; + C_RGB_XYZ_Lab m_WPTarget; + VectorXd m_distWeights; + ColorTable m_ColorTable; + double *m_ValsIn; + double *m_Lab_Iter; + double *m_difLab; + LULinearSolver *m_LULS; + + double ReduceStep(const double &d_f, const double &uphill, const double &downhill)const; + double ResidualSumSquares(void); + double IncreaseStep(); + + void Eval_alpha_and_beta(); +}; +#endif // __LEVMAR_H__ \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.cpp new file mode 100644 index 000000000..ccdff3e9d --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.cpp @@ -0,0 +1,333 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "NDInterpUtils.h" +#include + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 */ + +extern "C" +{ + + NDInterpUtils::NDInterpUtils() : + m_MSBShift(Sh4MSB), m_DataBuffer(NULL), m_nSeparationsIn(nSeparationsIn), m_Point(NULL), + m_nSeparationsOut(nSeparationsOut), m_nGridPoints(0), m_SubCubeSize(0), m_LastCubeComp(0), + m_tmpResult(NULL) + { + } + + /*__declspec(dllexport) */void NDInterpUtils::InitData(unsigned short *DataBuffer, int SeparationsIn, int SeparationsOut, int nGridPoints, int MSBShift) + { + SetMSBShift(MSBShift); + SetNDData(DataBuffer); + SetSeparationsIn(SeparationsIn); + SetSeparationsOut(SeparationsOut); + SetNGridpoints(nGridPoints); + SetSubCubeSize(); + SetLastCubeComp(); + if(m_Point == NULL) + m_Point = new unsigned short[m_nSeparationsIn + 1]; + if(m_tmpResult == NULL) + m_tmpResult = new int[m_nSeparationsOut]; + //m_Point = DBG_NEW unsigned short[m_nSeparationsIn + 1]; + //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(); + if(m_Point == NULL) + m_Point = new unsigned short[m_nSeparationsIn + 1]; + if(m_tmpResult == NULL) + 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) + delete m_Point; + if (m_tmpResult != NULL) + delete m_tmpResult; + + } + + + + void NDInterpUtils::ColorMap4(const unsigned short * ValIn, double * ValOut) + { + //ValIn is in 8 bits, ValOut is floating point, scale 256 + unsigned short iC, iM, iY, iK; //input values + unsigned char HC, HM, HY, HK; //subcube coordinates + unsigned char LC, LM, LY, LK; // position within subcube + int p0, p1, p2, p3, p4; //position + int w0, w1, w2, w3, w4; //weights + + int maxVal, midVal1, midVal2, minVal; + int maxPos, midPos1, midPos2, minPos; + + // Extract Input Pixel + iC = ValIn[0]; + iM = ValIn[1]; + iY = ValIn[2]; + iK = ValIn[3]; + + // Extract MSB for LUT access + unsigned char MSBShift = m_MSBShift + 8; + HC = iC >> MSBShift; + HM = iM >> MSBShift; + HY = iY >> MSBShift; + HK = iK >> MSBShift; + + // Extract LSB for interpolation + LC = iC & m_SubCubeSize; + LM = iM & m_SubCubeSize; + LY = iY & m_SubCubeSize; + LK = iK & m_SubCubeSize; + + // Last cube compensation + if (iC >= m_LastCubeComp) LC++; + if (iM >= m_LastCubeComp) LM++; + if (iY >= m_LastCubeComp) LY++; + if (iK >= m_LastCubeComp) LK++; + + //get minimum, mid & maximum LSBs + getOrdering4((int)LC, (int)LM, (int)LY, (int)LK, maxVal, midVal1, midVal2, minVal, + maxPos, midPos1, midPos2, minPos); + + // Lut position for the vertices + p0 = (HC*m_nGridPoints*m_nGridPoints*m_nGridPoints) + (HM*m_nGridPoints*m_nGridPoints) + (HY*m_nGridPoints) + HK; + + p1 = (maxPos == 3) ? (p0 + m_nGridPoints*m_nGridPoints*m_nGridPoints) : ((maxPos == 2) ? p0 + m_nGridPoints*m_nGridPoints : + (maxPos == 1) ? p0 + m_nGridPoints : p0 + 1); + + p2 = (midPos1 == 3) ? (p1 + m_nGridPoints*m_nGridPoints*m_nGridPoints) : ((midPos1 == 2) ? p1 + m_nGridPoints*m_nGridPoints : + (midPos1 == 1) ? p1 + m_nGridPoints : p1 + 1); + + p3 = (midPos2 == 3) ? (p2 + m_nGridPoints*m_nGridPoints*m_nGridPoints) : ((midPos2 == 2) ? p2 + m_nGridPoints*m_nGridPoints : + (midPos2 == 1) ? p2 + m_nGridPoints : p2 + 1); + + p4 = (minPos == 3) ? (p3 + m_nGridPoints*m_nGridPoints*m_nGridPoints) : ((minPos == 2) ? p3 + m_nGridPoints*m_nGridPoints : + (minPos == 1) ? p3 + m_nGridPoints : p3 + 1); + + p0 *= m_nSeparationsOut; + p1 *= m_nSeparationsOut; + p2 *= m_nSeparationsOut; + p3 *= m_nSeparationsOut; + p4 *= m_nSeparationsOut; + + // Calculate weights + w0 = m_SubCubeSize + 1 - maxVal; + w1 = maxVal - midVal1; + w2 = midVal1 - midVal2; + w3 = midVal2 - minVal; + w4 = minVal; + + for (int p = 0; p < m_nSeparationsOut; p++) + { + // Extract vertices from LUT + m_Point[0] = m_DataBuffer[p0 + p]; + m_Point[1] = m_DataBuffer[p1 + p]; + m_Point[2] = m_DataBuffer[p2 + p]; + m_Point[3] = m_DataBuffer[p3 + p]; + m_Point[4] = m_DataBuffer[p4 + p]; + // Compute output + m_tmpResult[p] = w0*m_Point[0] + w1*m_Point[1] + w2*m_Point[2] + w3*m_Point[3] + w4*m_Point[4]; + m_tmpResult[p] = m_tmpResult[p] >> m_MSBShift; + + if (m_tmpResult[p] >= 0x10000) + { + m_tmpResult[p] = 0xFFFF; + } + + ValOut[p] = m_tmpResult[p]; + + + // if (debug) + // { + // logger.note(" COLORMAP: plane=%d, cmyk=(0x%0x,0x%0x,0x%0x,0x%0x) Addr=(0x%0x,0x%0x,0x%0x,0x%0x,0x%0x) Lut=(0x%0x,0x%0x,0x%0x,0x%0x, 0x%0x) Weight=(0x%0x,0x%0x,0x%0x,0x%0x,0x%0x), out=0x%0x", + // p, iC, iM, iY, iK + // p0, p1, p2, p3, p4, Point[0], Point[1], Point[2], + // Point[3], Point[4], w0, w1, w2, w3, w4, ValOut[p]); + // } + } + } + + void NDInterpUtils::ColorMap3(const unsigned short * ValIn, double * ValOut) + { + //ValIn is in 8 bits, ValOut is floating point, scale 256 + unsigned short iC, iM, iY; //input values + unsigned char HC, HM, HY; //subcube coordinates + unsigned char LC, LM, LY; // position within subcube + int p0, p1, p2, p3; //position + int w0, w1, w2, w3; //weights + + int maxVal, midVal1, minVal; + int maxPos, midPos1, minPos; + // Extract Input Pixel + iC = ValIn[0]; + iM = ValIn[1]; + iY = ValIn[2]; + + // Extract MSB for LUT access + unsigned char MSBShift = m_MSBShift + 8; + HC = iC >> MSBShift; + HM = iM >> MSBShift; + HY = iY >> MSBShift; + + // Extract LSB for interpolation + LC = (iC>> 8)& m_SubCubeSize; + LM = (iM>>8) & m_SubCubeSize; + LY =( iY>>8) & m_SubCubeSize; + + // Last cube compensation + if ((iC >> 8) >= m_LastCubeComp) LC++; + if ((iM >> 8) >= m_LastCubeComp) LM++; + if ((iY >> 8) >= m_LastCubeComp) LY++; + + //get minimum, mid & maximum LSBs + getOrdering3((int)LC, (int)LM, (int)LY, maxVal, midVal1, minVal, + maxPos, midPos1, minPos); + + // Lut position for the vertices + p0 = (HC*m_nGridPoints*m_nGridPoints) + (HM*m_nGridPoints) + HY; + + p1 = (maxPos == 2) ? (p0 + m_nGridPoints*m_nGridPoints) : ((maxPos == 1) ? p0 + m_nGridPoints : p0 + 1); + + p2 = (midPos1 == 2) ? (p1 + m_nGridPoints*m_nGridPoints) : ((midPos1 == 1) ? p1 + m_nGridPoints : p1 + 1); + + p3 = (minPos == 2) ? (p2 + m_nGridPoints*m_nGridPoints) : ((minPos == 1) ? p2 + m_nGridPoints : p2 + 1); + + p0 *= m_nSeparationsOut; + p1 *= m_nSeparationsOut; + p2 *= m_nSeparationsOut; + p3 *= m_nSeparationsOut; + + // Calculate weights + w0 = m_SubCubeSize + 1 - maxVal; + w1 = maxVal - midVal1; + w2 = midVal1 - minVal; + w3 = minVal; + + for (int p = 0; p < m_nSeparationsOut; p++) + { + // Extract vertices from LUT + m_Point[0] = m_DataBuffer[p0 + p]; + m_Point[1] = m_DataBuffer[p1 + p]; + m_Point[2] = m_DataBuffer[p2 + p]; + m_Point[3] = m_DataBuffer[p3 + p]; + // Compute output + m_tmpResult[p] = w0*m_Point[0] + w1*m_Point[1] + w2*m_Point[2] + w3*m_Point[3]; + m_tmpResult[p] = m_tmpResult[p] >> m_MSBShift; + // Store result in units of 2^16 same as LUT + if (m_tmpResult[p] >= 0x10000) + { + m_tmpResult[p] = 0xFFFF; + } + + ValOut[p] = m_tmpResult[p]; + } + } + + + + void NDInterpUtils::getMax4(int a, int b, int c, int d, int &max, int &pos) + { + if ((a >= b) && (a >= c) && (a >= d)) + { + max = a; + pos = 3; + } + else if ((b >= a) && (b >= c) && (b >= d)) + { + max = b; + pos = 2; + } + else if ((c >= a) && (c >= b) && (c >= d)) + { + max = c; + pos = 1; + } + else + { + max = d; + pos = 0; + } + } + + void NDInterpUtils::getMax3(int a, int b, int c, int &max, int &pos) + { + if ((a >= b) && (a >= c)) + { + max = a; + pos = 2; + } + else if ((b >= a) && (b >= c)) + { + max = b; + pos = 1; + } + else + { + max = c; + pos = 0; + } + } + void NDInterpUtils::getOrdering4(int a, int b, int c, int d, + int &max, int &mid1, int &mid2, int &min, int &maxPos, + int &midPos1, int &midPos2, int &minPos) + { + int v[4] = { d, c, b, a }; + getMax4(v[3], v[2], v[1], v[0], max, maxPos); + v[maxPos] = -1; + getMax4(v[3], v[2], v[1], v[0], mid1, midPos1); + v[midPos1] = -1; + getMax4(v[3], v[2], v[1], v[0], mid2, midPos2); + v[midPos2] = -1; + getMax4(v[3], v[2], v[1], v[0], min, minPos); + } + + void NDInterpUtils::getOrdering3(int a, int b, int c, + int &max, int &mid1, int &min, int &maxPos, + int &midPos1, int &minPos) + { + int v[4] = { c, b, a }; + getMax3(v[2], v[1], v[0], max, maxPos); + v[maxPos] = -1; + getMax3(v[2], v[1], v[0], mid1, midPos1); + v[midPos1] = -1; + getMax3(v[2], v[1], v[0], min, minPos); + } + + + void NDInterpUtils::SetSubCubeSize() + { + int SubCubeSize = (unsigned char)pow((double)2, (int)m_MSBShift); + if (SubCubeSize == 16) + m_SubCubeSize = 0x0F; + else if (SubCubeSize == 32) + m_SubCubeSize = 0x1F; + else if (SubCubeSize == 8) + m_SubCubeSize = 0x07; + + } +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.h new file mode 100644 index 000000000..992de082c --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NDInterpUtils.h @@ -0,0 +1,60 @@ + +#ifndef _NDINTERP_H_ +#define _NDINTERP_H_ + +#include +#include + +#ifndef nSeparationsIn +#define nSeparationsIn 4 +#endif + +#ifndef nSeparationsOut +#define nSeparationsOut 4 +#endif + + +#ifndef Sh4MSB +#define Sh4MSB 4 // for 17 gridpoints table +#endif + +//Assumption: Table used for interpolation is saved in 16 bits accuracy. Number of nodes per channel can vary +//Interpolation suports 3 or 4 input channels and 3 or 4 output channels +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); +private: + unsigned char m_MSBShift; + unsigned char m_SubCubeSize; + unsigned char m_LastCubeComp; + int m_nSeparationsIn; + int m_nSeparationsOut; + int m_nGridPoints; + unsigned short *m_DataBuffer; + unsigned short *m_Point; + int *m_tmpResult; + void SetSubCubeSize(); + void SetMSBShift(unsigned char ShMSB) { m_MSBShift = ShMSB; }; + void SetLastCubeComp() { m_LastCubeComp = 0xFF - m_SubCubeSize / 2; }; + void SetdataBuffer(unsigned short *DataBuffer) { m_DataBuffer = DataBuffer; }; + void getMax4(int a, int b, int c, int d, int &max, int &pos); + void getOrdering4(int a, int b, int c, int d, + int &max, int &mid1, int &mid2, int &min, int &maxPos, + int &midPos1, int &midPos2, int &minPos); + void getMax3(int a, int b, int c, int &max, int &pos); + void getOrdering3(int a, int b, int c, + int &max, int &mid1, int &min, int &maxPos, + int &midPos1, int &minPos); + void SetMSBShift(int MSBShift) { m_MSBShift = MSBShift; }; + void SetNDData(unsigned short *DataBuffer) { m_DataBuffer = DataBuffer; }; + void SetSeparationsIn(int SeparationsIn) { m_nSeparationsIn = SeparationsIn; }; + void SetSeparationsOut(int SeparationsOut) { m_nSeparationsOut = SeparationsOut; }; + void SetNGridpoints(int nGridPoints) { m_nGridPoints = nGridPoints; }; +}; + +#endif \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NumConversions.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NumConversions.cpp new file mode 100644 index 000000000..f541b370c --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/NumConversions.cpp @@ -0,0 +1,85 @@ +#include "NumConversions.h" +#include +#include +#include +#include +#include + +/*#define _CRTDBG_MAP_ALLOC +#include +#include +#include + +#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 */ + +NumConversions::NumConversions(void) +{ +} + +NumConversions::NumConversions(const NumConversions &rhs) +{ +} + +NumConversions::~NumConversions() +{ + +} +int NumConversions::ByteToInt(uint8_t *byteN, int start) +{ + int res; + res = (int)((unsigned int)byteN[start] << 24 | + (unsigned int)byteN[start + 1] << 16 | + (unsigned int)byteN[start + 2] << 8 | + (unsigned int)byteN[start + 3]); + return(res); +} + +uint16_t NumConversions::ByteToShort(uint8_t *byteN, int start) +{ + uint16_t res; + res = (uint16_t)((unsigned short)byteN[start] << 8 | + (unsigned short)byteN[start + 1]); + return(res); +} + +void NumConversions::getchar(uint32_t num, char &tmpC) +{ + char getChar[sizeof(uint32_t)]; + getChar[0] = num >> 24; + getChar[1] = num >> 16; + getChar[2] = num >> 8; + getChar[3] = num; + strncpy_s(&tmpC, sizeof(uint32_t)+1, getChar, sizeof(uint32_t) ); + + //reverse order + //char *tmp = new char[nlen]; + //char *tmp = DBG_NEW char[nlen]; + /*for (int i = 0; i < nlen; ++i) + { + tmpC[i] = getChar[nlen - 1 - i]; + }*/ +} + +void NumConversions::DecToBinary(int DecNumber, int *&BinOut, int nsize) +{ + //Store in reverse order, meaning the way it comes out of the calculation + // array to store binary number + + // counter for binary array + int i = 0; + for (int i = 0; i < nsize; ++i) + BinOut[i] = 0; + while (DecNumber > 0 && i +#include + +class NumConversions +{ + public: + NumConversions(void); + NumConversions(const NumConversions &rhs); + ~NumConversions(); + int ByteToInt(uint8_t *byteN, int Start); + uint16_t ByteToShort(uint8_t *byteN, int Start); + void getchar(uint32_t num, char &tmpC); + void DecToBinary(int DecNumber,int *&BinOut, int nsize); + private: +}; +#endif //__NUMCONVERSIONS_H__ \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.cpp new file mode 100644 index 000000000..2e746f09b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.cpp @@ -0,0 +1,142 @@ + +#include // for fabs() + +#include "ObjectiveFunction.h" +#include "C_RGB_XYZ_Lab.h" +#include "ColorTable.h" +#include "Dense" + +using Eigen::MatrixXd; +using Eigen::VectorXd; +using Eigen::VectorXi; + +ObjectiveFunction::ObjectiveFunction(void) : m_FreeParamIndex(NULL), +m_FixedParamIndex(NULL), +m_ZeroValues(NULL), +m_ValsIn(NULL), +m_LabOut(NULL), +m_dLabOut(NULL), +m_nFreeParams(0), +m_nFixedParams(0), +m_nParams(0), +m_forwardmodel(NULL), +m_LabGoal(NULL) +{ +} + +ObjectiveFunction::~ObjectiveFunction(void) +{ + if (m_FreeParamIndex != NULL) + { + delete[] m_FreeParamIndex; + m_FreeParamIndex = NULL; + } + if (m_FixedParamIndex != NULL) + { + delete[] m_FixedParamIndex; + m_FixedParamIndex = NULL; + } + + if (m_ZeroValues != NULL) + { + delete[] m_ZeroValues; + m_ZeroValues = NULL; + } + if (m_ValsIn != NULL) + { + delete[] m_ValsIn; + m_ValsIn = NULL; + } + + if (m_UpperBound != NULL) + { + delete[] m_UpperBound; + m_UpperBound = NULL; + } + if (m_LowerBound != NULL) + { + delete[] m_LowerBound; + m_LowerBound = NULL; + } +} + +ObjectiveFunction::ObjectiveFunction(ForwardModel *forwardmodel): m_FreeParamIndex(NULL), +m_FixedParamIndex(NULL), +m_ZeroValues(NULL), +m_ValsIn(NULL), +m_LabOut(NULL), +m_nFreeParams(0), +m_nFixedParams(0), +m_nParams(0) +{ + m_forwardmodel = forwardmodel; +} + + +int ObjectiveFunction::EvaluateObjectiveFunction(double *params, double *retVector) +{ + for (int i = 0; i<(int)m_nFreeParams; ++i) + m_ValsIn[m_FreeParamIndex[i]] = params[m_FreeParamIndex[i]]; + for (int i = 0; i < (int)m_nFixedParams; ++i) + m_ValsIn[m_FixedParamIndex[i]]= params[m_FixedParamIndex[i]]; //Units of [0-100] + m_dLabOut[0] = m_LabOut.Get_x(); + m_dLabOut[1] = m_LabOut.Get_y(); + m_dLabOut[2] = m_LabOut.Get_z(); + int GamutRegion = 0; + m_forwardmodel->CalcFM(m_ValsIn, m_dLabOut); + + m_LabOut.Set(m_dLabOut[0], m_dLabOut[1], m_dLabOut[2]); + retVector[0] = m_LabOut.Get_x() - m_LabGoal.Get_x(); + retVector[1] = m_LabOut.Get_y() - m_LabGoal.Get_y(); + retVector[2] = m_LabOut.Get_z()- m_LabGoal.Get_z(); + + return(0); + +} + +void ObjectiveFunction::SetLabGoal(double *LabIn) +{ + m_LabGoal.Set(LabIn[0], LabIn[1], LabIn[2]); +} + +void ObjectiveFunction::SetParameters(unsigned int nFreeParams, unsigned int nFixedParams, unsigned int *FreeParamIndex, + unsigned int *FixedParamIndex, double*UpperBound, double *LowerBound) +{ + m_nFreeParams =nFreeParams; + m_nFixedParams = nFixedParams; + m_nParams = m_nFreeParams + m_nFixedParams; + m_nOut = (unsigned int)3; + m_FreeParamIndex = FreeParamIndex; + m_FixedParamIndex = FixedParamIndex; + m_UpperBound = UpperBound; + m_LowerBound = LowerBound; + if (m_ValsIn == NULL) + m_ValsIn = new double[(int)m_nParams]; + + for (int i = 0; i < (int)m_nParams; ++i) + m_ValsIn[i] = 0.0; + + m_LabOut.Set(0.0, 0.0, 0.0); + m_LabGoal.Set(0.0, 0.0, 0.0); + + for (int i = 0; i < (int)m_nFreeParams; ++i) + { + m_FreeParamIndex[i] = FreeParamIndex[i]; + m_UpperBound[i] = UpperBound[i]; + m_LowerBound[i] = LowerBound[i]; + } + + for (int i = 0; i < (int)m_nFixedParams; ++i) + m_FixedParamIndex[i] = FixedParamIndex[i]; + + m_ZeroValues = new double[m_nParams]; + for (int i = 0; i < (int)m_nParams; ++i) + m_ZeroValues[i] = 0.0; + + if (m_dLabOut != NULL) + m_dLabOut = new double[m_nOut]; + for (int i = 0; i < (int)m_nOut; ++i) + m_dLabOut[i] = 0.0; + +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.h new file mode 100644 index 000000000..2e2da1f64 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/Utils/ObjectiveFunction.h @@ -0,0 +1,49 @@ + +#ifndef _OBJECTIVEFUNCTION_H_ +#define _OBJECTIVEFUNCTION_H_ + +#include "C_RGB_XYZ_Lab.h" +#include "ColorTable.h" + +class ObjectiveFunction +{ +public: + ObjectiveFunction(void); + ~ObjectiveFunction(void); + ObjectiveFunction(ForwardModel *forwardmodel); + + int EvaluateObjectiveFunction(double *params, double*retVector); + void SetLabGoal(double *LabIn); + void ObjectiveFunction::SetParameters(unsigned int nFreeParams, unsigned int nFixedParams, unsigned int *FreeParamIndex, + unsigned int *FixedParamIndex, double *UpperBound, double *LowerBound); + unsigned int GetNumFreeParams() {return(m_nFreeParams);}; + unsigned int GetNumFixedParams() {return(m_nFixedParams);}; + unsigned int GetNumOutResult() {return(m_nOut);}; + unsigned int *GetFreeParamsIndex() {return (m_FreeParamIndex);}; + unsigned int *GetFixedParamsIndex() {return (m_FixedParamIndex);}; + double *GetLowerBound() {return(m_LowerBound);}; + double *GetUpperBound() {return(m_UpperBound);}; + +protected: + +private: + + ForwardModel *m_forwardmodel; + double *m_ValsIn; + C_RGB_XYZ_Lab m_LabOut; + C_RGB_XYZ_Lab m_LabGoal; + + unsigned int *m_FreeParamIndex; + unsigned int *m_FixedParamIndex; + double *m_ZeroValues; + unsigned int m_nFreeParams; + unsigned int m_nFixedParams; + unsigned int m_nParams; + unsigned int m_nOut; + double *m_UpperBound; + double *m_LowerBound; + double *m_dLabOut; +}; + +#endif // _OBJECTIVEFUNCTION_H_ + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.c new file mode 100644 index 000000000..5debac820 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.c @@ -0,0 +1,3642 @@ +/* + * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * Support library for `protoc-c` generated code. + * + * This file implements the public API used by the code generated + * by `protoc-c`. + * + * \authors Dave Benson and the protobuf-c authors + * + * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. + */ + +/** + * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math + * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64). + * + * \todo Use size_t consistently. + */ + +#include /* for malloc, free */ +#include /* for strcmp, strlen, memcpy, memmove, memset */ + +#include "protobuf-c.h" + +#define TRUE 1 +#define FALSE 0 + +#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0) + +/* Workaround for Microsoft compilers. */ +#ifdef _MSC_VER +# define inline __inline +#endif + +/** + * \defgroup internal Internal functions and macros + * + * These are not exported by the library but are useful to developers working + * on `libprotobuf-c` itself. + */ + +/** + * \defgroup macros Utility macros for manipulating structures + * + * Macros and constants used to manipulate the base "classes" generated by + * `protobuf-c`. They also define limits and check correctness. + * + * \ingroup internal + * @{ + */ + +/** The maximum length of a 64-bit integer in varint encoding. */ +#define MAX_UINT64_ENCODED_SIZE 10 + +#ifndef PROTOBUF_C_UNPACK_ERROR +# define PROTOBUF_C_UNPACK_ERROR(...) +#endif + +const char protobuf_c_empty_string[] = ""; + +/** + * Internal `ProtobufCMessage` manipulation macro. + * + * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and + * STRUCT_MEMBER_PTR(). + */ +#define STRUCT_MEMBER_P(struct_p, struct_offset) \ + ((void *) ((uint8_t *) (struct_p) + (struct_offset))) + +/** + * Return field in a `ProtobufCMessage` based on offset. + * + * Take a pointer to a `ProtobufCMessage` and find the field at the offset. + * Cast it to the passed type. + */ +#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ + (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) + +/** + * Return field in a `ProtobufCMessage` based on offset. + * + * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast + * it to a pointer to the passed type. + */ +#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \ + ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) + +/* Assertions for magic numbers. */ + +#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC) + +#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) + +#define ASSERT_IS_MESSAGE(message) \ + ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor) + +#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \ + assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC) + +/**@}*/ + +/* --- version --- */ + +const char * +protobuf_c_version(void) +{ + return PROTOBUF_C_VERSION; +} + +uint32_t +protobuf_c_version_number(void) +{ + return PROTOBUF_C_VERSION_NUMBER; +} + +/* --- allocator --- */ + +static void * +system_alloc(void *allocator_data, size_t size) +{ + return malloc(size); +} + +static void +system_free(void *allocator_data, void *data) +{ + free(data); +} + +static inline void * +do_alloc(ProtobufCAllocator *allocator, size_t size) +{ + return allocator->alloc(allocator->allocator_data, size); +} + +static inline void +do_free(ProtobufCAllocator *allocator, void *data) +{ + if (data != NULL) + allocator->free(allocator->allocator_data, data); +} + +/* + * This allocator uses the system's malloc() and free(). It is the default + * allocator used if NULL is passed as the ProtobufCAllocator to an exported + * function. + */ +static ProtobufCAllocator protobuf_c__allocator = { + .alloc = &system_alloc, + .free = &system_free, + .allocator_data = NULL, +}; + +/* === buffer-simple === */ + +void +protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, + size_t len, const uint8_t *data) +{ + ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer; + size_t new_len = simp->len + len; + + if (new_len > simp->alloced) { + ProtobufCAllocator *allocator = simp->allocator; + size_t new_alloced = simp->alloced * 2; + uint8_t *new_data; + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + while (new_alloced < new_len) + new_alloced += new_alloced; + new_data = do_alloc(allocator, new_alloced); + if (!new_data) + return; + memcpy(new_data, simp->data, simp->len); + if (simp->must_free_data) + do_free(allocator, simp->data); + else + simp->must_free_data = TRUE; + simp->data = new_data; + simp->alloced = new_alloced; + } + memcpy(simp->data + simp->len, data, len); + simp->len = new_len; +} + +/** + * \defgroup packedsz protobuf_c_message_get_packed_size() implementation + * + * Routines mainly used by protobuf_c_message_get_packed_size(). + * + * \ingroup internal + * @{ + */ + +/** + * Return the number of bytes required to store the tag for the field. Includes + * 3 bits for the wire-type, and a single bit that denotes the end-of-tag. + * + * \param number + * Field tag to encode. + * \return + * Number of bytes required. + */ +static inline size_t +get_tag_size(uint32_t number) +{ + if (number < (1UL << 4)) { + return 1; + } else if (number < (1UL << 11)) { + return 2; + } else if (number < (1UL << 18)) { + return 3; + } else if (number < (1UL << 25)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the number of bytes required to store a variable-length unsigned + * 32-bit integer in base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +uint32_size(uint32_t v) +{ + if (v < (1UL << 7)) { + return 1; + } else if (v < (1UL << 14)) { + return 2; + } else if (v < (1UL << 21)) { + return 3; + } else if (v < (1UL << 28)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the number of bytes required to store a variable-length signed 32-bit + * integer in base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +int32_size(int32_t v) +{ + if (v < 0) { + return 10; + } else if (v < (1L << 7)) { + return 1; + } else if (v < (1L << 14)) { + return 2; + } else if (v < (1L << 21)) { + return 3; + } else if (v < (1L << 28)) { + return 4; + } else { + return 5; + } +} + +/** + * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed + * integer. + * + * \param v + * Value to encode. + * \return + * ZigZag encoded integer. + */ +static inline uint32_t +zigzag32(int32_t v) +{ + if (v < 0) + return (-(uint32_t)v) * 2 - 1; + else + return (uint32_t)(v) * 2; +} + +/** + * Return the number of bytes required to store a signed 32-bit integer, + * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128 + * varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +sint32_size(int32_t v) +{ + return uint32_size(zigzag32(v)); +} + +/** + * Return the number of bytes required to store a 64-bit unsigned integer in + * base-128 varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +uint64_size(uint64_t v) +{ + uint32_t upper_v = (uint32_t) (v >> 32); + + if (upper_v == 0) { + return uint32_size((uint32_t) v); + } else if (upper_v < (1UL << 3)) { + return 5; + } else if (upper_v < (1UL << 10)) { + return 6; + } else if (upper_v < (1UL << 17)) { + return 7; + } else if (upper_v < (1UL << 24)) { + return 8; + } else if (upper_v < (1UL << 31)) { + return 9; + } else { + return 10; + } +} + +/** + * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed + * integer. + * + * \param v + * Value to encode. + * \return + * ZigZag encoded integer. + */ +static inline uint64_t +zigzag64(int64_t v) +{ + if (v < 0) + return (-(uint64_t)v) * 2 - 1; + else + return (uint64_t)(v) * 2; +} + +/** + * Return the number of bytes required to store a signed 64-bit integer, + * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128 + * varint encoding. + * + * \param v + * Value to encode. + * \return + * Number of bytes required. + */ +static inline size_t +sint64_size(int64_t v) +{ + return uint64_size(zigzag64(v)); +} + +/** + * Calculate the serialized size of a single required message field, including + * the space needed by the preceding tag. + * + * \param field + * Field descriptor for member. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +required_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const void *member) +{ + size_t rv = get_tag_size(field->id); + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + return rv + sint32_size(*(const int32_t *) member); + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + return rv + int32_size(*(const int32_t *) member); + case PROTOBUF_C_TYPE_UINT32: + return rv + uint32_size(*(const uint32_t *) member); + case PROTOBUF_C_TYPE_SINT64: + return rv + sint64_size(*(const int64_t *) member); + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + return rv + uint64_size(*(const uint64_t *) member); + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + return rv + 4; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + return rv + 8; + case PROTOBUF_C_TYPE_BOOL: + return rv + 1; + case PROTOBUF_C_TYPE_FLOAT: + return rv + 4; + case PROTOBUF_C_TYPE_DOUBLE: + return rv + 8; + case PROTOBUF_C_TYPE_STRING: { + const char *str = *(char * const *) member; + size_t len = str ? strlen(str) : 0; + return rv + uint32_size(len) + len; + } + case PROTOBUF_C_TYPE_BYTES: { + size_t len = ((const ProtobufCBinaryData *) member)->len; + return rv + uint32_size(len) + len; + } + case PROTOBUF_C_TYPE_MESSAGE: { + const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; + size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0; + return rv + uint32_size(subrv) + subrv; + } + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Calculate the serialized size of a single oneof message field, including + * the space needed by the preceding tag. Returns 0 if the oneof field isn't + * selected or is not set. + * + * \param field + * Field descriptor for member. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_get_packed_size(field, member); +} + +/** + * Calculate the serialized size of a single optional message field, including + * the space needed by the preceding tag. Returns 0 if the optional field isn't + * set. + * + * \param field + * Field descriptor for member. + * \param has + * True if the field exists, false if not. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +optional_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_get_packed_size(field, member); +} + +static protobuf_c_boolean +field_is_zeroish(const ProtobufCFieldDescriptor *field, + const void *member) +{ + protobuf_c_boolean ret = FALSE; + + switch (field->type) { + case PROTOBUF_C_TYPE_BOOL: + ret = (0 == *(const protobuf_c_boolean *) member); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + ret = (0 == *(const uint32_t *) member); + break; + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + ret = (0 == *(const uint64_t *) member); + break; + case PROTOBUF_C_TYPE_FLOAT: + ret = (0 == *(const float *) member); + break; + case PROTOBUF_C_TYPE_DOUBLE: + ret = (0 == *(const double *) member); + break; + case PROTOBUF_C_TYPE_STRING: + ret = (NULL == *(const char * const *) member) || + ('\0' == **(const char * const *) member); + break; + case PROTOBUF_C_TYPE_BYTES: + case PROTOBUF_C_TYPE_MESSAGE: + ret = (NULL == *(const void * const *) member); + break; + default: + ret = TRUE; + break; + } + + return ret; +} + +/** + * Calculate the serialized size of a single unlabeled message field, including + * the space needed by the preceding tag. Returns 0 if the field isn't set or + * if it is set to a "zeroish" value (null pointer or 0 for numerical values). + * Unlabeled fields are supported only in proto3. + * + * \param field + * Field descriptor for member. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field, + const void *member) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_get_packed_size(field, member); +} + +/** + * Calculate the serialized size of repeated message fields, which may consist + * of any number of values (including 0). Includes the space needed by the + * preceding tags (as needed). + * + * \param field + * Field descriptor for member. + * \param count + * Number of repeated field members. + * \param member + * Field to encode. + * \return + * Number of bytes required. + */ +static size_t +repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field, + size_t count, const void *member) +{ + size_t header_size; + size_t rv = 0; + unsigned i; + void *array = *(void * const *) member; + + if (count == 0) + return 0; + header_size = get_tag_size(field->id); + if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) + header_size *= count; + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + for (i = 0; i < count; i++) + rv += sint32_size(((int32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + for (i = 0; i < count; i++) + rv += int32_size(((int32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_UINT32: + for (i = 0; i < count; i++) + rv += uint32_size(((uint32_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_SINT64: + for (i = 0; i < count; i++) + rv += sint64_size(((int64_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + for (i = 0; i < count; i++) + rv += uint64_size(((uint64_t *) array)[i]); + break; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + rv += 4 * count; + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + rv += 8 * count; + break; + case PROTOBUF_C_TYPE_BOOL: + rv += count; + break; + case PROTOBUF_C_TYPE_STRING: + for (i = 0; i < count; i++) { + size_t len = strlen(((char **) array)[i]); + rv += uint32_size(len) + len; + } + break; + case PROTOBUF_C_TYPE_BYTES: + for (i = 0; i < count; i++) { + size_t len = ((ProtobufCBinaryData *) array)[i].len; + rv += uint32_size(len) + len; + } + break; + case PROTOBUF_C_TYPE_MESSAGE: + for (i = 0; i < count; i++) { + size_t len = protobuf_c_message_get_packed_size( + ((ProtobufCMessage **) array)[i]); + rv += uint32_size(len) + len; + } + break; + } + + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) + header_size += uint32_size(rv); + return header_size + rv; +} + +/** + * Calculate the serialized size of an unknown field, i.e. one that is passed + * through mostly uninterpreted. This is required for forward compatibility if + * new fields are added to the message descriptor. + * + * \param field + * Unknown field type. + * \return + * Number of bytes required. + */ +static inline size_t +unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field) +{ + return get_tag_size(field->tag) + field->len; +} + +/**@}*/ + +/* + * Calculate the serialized size of the message. + */ +size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = + ((const char *) message) + field->offset; + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_get_packed_size(field, member); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_get_packed_size( + field, + *(const uint32_t *) qmember, + member + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_get_packed_size( + field, + *(protobuf_c_boolean *) qmember, + member + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_get_packed_size( + field, + member + ); + } else { + rv += repeated_field_get_packed_size( + field, + *(const size_t *) qmember, + member + ); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_get_packed_size(&message->unknown_fields[i]); + return rv; +} + +/** + * \defgroup pack protobuf_c_message_pack() implementation + * + * Routines mainly used by protobuf_c_message_pack(). + * + * \ingroup internal + * @{ + */ + +/** + * Pack an unsigned 32-bit integer in base-128 varint encoding and return the + * number of bytes written, which must be 5 or less. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +uint32_pack(uint32_t value, uint8_t *out) +{ + unsigned rv = 0; + + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + if (value >= 0x80) { + out[rv++] = value | 0x80; + value >>= 7; + } + } + } + } + /* assert: value<128 */ + out[rv++] = value; + return rv; +} + +/** + * Pack a signed 32-bit integer and return the number of bytes written. + * Negative numbers are encoded as two's complement 64-bit integers. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +int32_pack(int32_t value, uint8_t *out) +{ + if (value < 0) { + out[0] = value | 0x80; + out[1] = (value >> 7) | 0x80; + out[2] = (value >> 14) | 0x80; + out[3] = (value >> 21) | 0x80; + out[4] = (value >> 28) | 0x80; + out[5] = out[6] = out[7] = out[8] = 0xff; + out[9] = 0x01; + return 10; + } else { + return uint32_pack(value, out); + } +} + +/** + * Pack a signed 32-bit integer using ZigZag encoding and return the number of + * bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +sint32_pack(int32_t value, uint8_t *out) +{ + return uint32_pack(zigzag32(value), out); +} + +/** + * Pack a 64-bit unsigned integer using base-128 varint encoding and return the + * number of bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +uint64_pack(uint64_t value, uint8_t *out) +{ + uint32_t hi = (uint32_t) (value >> 32); + uint32_t lo = (uint32_t) value; + unsigned rv; + + if (hi == 0) + return uint32_pack((uint32_t) lo, out); + out[0] = (lo) | 0x80; + out[1] = (lo >> 7) | 0x80; + out[2] = (lo >> 14) | 0x80; + out[3] = (lo >> 21) | 0x80; + if (hi < 8) { + out[4] = (hi << 4) | (lo >> 28); + return 5; + } else { + out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80; + hi >>= 3; + } + rv = 5; + while (hi >= 128) { + out[rv++] = hi | 0x80; + hi >>= 7; + } + out[rv++] = hi; + return rv; +} + +/** + * Pack a 64-bit signed integer in ZigZag encoding and return the number of + * bytes written. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +sint64_pack(int64_t value, uint8_t *out) +{ + return uint64_pack(zigzag64(value), out); +} + +/** + * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire + * types fixed32, sfixed32, float. Similar to "htole32". + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +fixed32_pack(uint32_t value, void *out) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, &value, 4); +#else + uint8_t *buf = out; + + buf[0] = value; + buf[1] = value >> 8; + buf[2] = value >> 16; + buf[3] = value >> 24; +#endif + return 4; +} + +/** + * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire + * types fixed64, sfixed64, double. Similar to "htole64". + * + * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit + * version would be appreciated, plus a way to decide to use 64-bit math where + * convenient. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +fixed64_pack(uint64_t value, void *out) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, &value, 8); +#else + fixed32_pack(value, out); + fixed32_pack(value >> 32, ((char *) out) + 4); +#endif + return 8; +} + +/** + * Pack a boolean value as an integer and return the number of bytes written. + * + * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c + * that is idiomatic C++ in some STL implementations. + * + * \param value + * Value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +boolean_pack(protobuf_c_boolean value, uint8_t *out) +{ + *out = value ? TRUE : FALSE; + return 1; +} + +/** + * Pack a NUL-terminated C string and return the number of bytes written. The + * output includes a length delimiter. + * + * The NULL pointer is treated as an empty string. This isn't really necessary, + * but it allows people to leave required strings blank. (See Issue #13 in the + * bug tracker for a little more explanation). + * + * \param str + * String to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +string_pack(const char *str, uint8_t *out) +{ + if (str == NULL) { + out[0] = 0; + return 1; + } else { + size_t len = strlen(str); + size_t rv = uint32_pack(len, out); + memcpy(out + rv, str, len); + return rv + len; + } +} + +/** + * Pack a ProtobufCBinaryData and return the number of bytes written. The output + * includes a length delimiter. + * + * \param bd + * ProtobufCBinaryData to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out) +{ + size_t len = bd->len; + size_t rv = uint32_pack(len, out); + memcpy(out + rv, bd->data, len); + return rv + len; +} + +/** + * Pack a ProtobufCMessage and return the number of bytes written. The output + * includes a length delimiter. + * + * \param message + * ProtobufCMessage object to pack. + * \param[out] out + * Packed message. + * \return + * Number of bytes written to `out`. + */ +static inline size_t +prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out) +{ + if (message == NULL) { + out[0] = 0; + return 1; + } else { + size_t rv = protobuf_c_message_pack(message, out + 1); + uint32_t rv_packed_size = uint32_size(rv); + if (rv_packed_size != 1) + memmove(out + rv_packed_size, out + 1, rv); + return uint32_pack(rv, out) + rv; + } +} + +/** + * Pack a field tag. + * + * Wire-type will be added in required_field_pack(). + * + * \todo Just call uint64_pack on 64-bit platforms. + * + * \param id + * Tag value to encode. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +tag_pack(uint32_t id, uint8_t *out) +{ + if (id < (1UL << (32 - 3))) + return uint32_pack(id << 3, out); + else + return uint64_pack(((uint64_t) id) << 3, out); +} + +/** + * Pack a required field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +required_field_pack(const ProtobufCFieldDescriptor *field, + const void *member, uint8_t *out) +{ + size_t rv = tag_pack(field->id, out); + + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + sint32_pack(*(const int32_t *) member, out + rv); + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + int32_pack(*(const int32_t *) member, out + rv); + case PROTOBUF_C_TYPE_UINT32: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + uint32_pack(*(const uint32_t *) member, out + rv); + case PROTOBUF_C_TYPE_SINT64: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + sint64_pack(*(const int64_t *) member, out + rv); + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + uint64_pack(*(const uint64_t *) member, out + rv); + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; + return rv + fixed32_pack(*(const uint32_t *) member, out + rv); + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; + return rv + fixed64_pack(*(const uint64_t *) member, out + rv); + case PROTOBUF_C_TYPE_BOOL: + out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv); + case PROTOBUF_C_TYPE_STRING: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + string_pack(*(char *const *) member, out + rv); + case PROTOBUF_C_TYPE_BYTES: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv); + case PROTOBUF_C_TYPE_MESSAGE: + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv); + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Pack a oneof field and return the number of bytes written. Only packs the + * field that is selected by the case enum. + * + * \param field + * Field descriptor. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +oneof_field_pack(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member, uint8_t *out) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_pack(field, member, out); +} + +/** + * Pack an optional field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param has + * Whether the field is set. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +optional_field_pack(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member, uint8_t *out) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void * const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_pack(field, member, out); +} + +/** + * Pack an unlabeled field and return the number of bytes written. + * + * \param field + * Field descriptor. + * \param member + * The field member. + * \param[out] out + * Packed value. + * \return + * Number of bytes written to `out`. + */ +static size_t +unlabeled_field_pack(const ProtobufCFieldDescriptor *field, + const void *member, uint8_t *out) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_pack(field, member, out); +} + +/** + * Given a field type, return the in-memory size. + * + * \todo Implement as a table lookup. + * + * \param type + * Field type. + * \return + * Size of the field. + */ +static inline size_t +sizeof_elt_in_repeated_array(ProtobufCType type) +{ + switch (type) { + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + case PROTOBUF_C_TYPE_ENUM: + return 4; + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + return 8; + case PROTOBUF_C_TYPE_BOOL: + return sizeof(protobuf_c_boolean); + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_MESSAGE: + return sizeof(void *); + case PROTOBUF_C_TYPE_BYTES: + return sizeof(ProtobufCBinaryData); + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Pack an array of 32-bit quantities. + * + * \param[out] out + * Destination. + * \param[in] in + * Source. + * \param[in] n + * Number of elements in the source array. + */ +static void +copy_to_little_endian_32(void *out, const void *in, const unsigned n) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, in, n * 4); +#else + unsigned i; + const uint32_t *ini = in; + for (i = 0; i < n; i++) + fixed32_pack(ini[i], (uint32_t *) out + i); +#endif +} + +/** + * Pack an array of 64-bit quantities. + * + * \param[out] out + * Destination. + * \param[in] in + * Source. + * \param[in] n + * Number of elements in the source array. + */ +static void +copy_to_little_endian_64(void *out, const void *in, const unsigned n) +{ +#if !defined(WORDS_BIGENDIAN) + memcpy(out, in, n * 8); +#else + unsigned i; + const uint64_t *ini = in; + for (i = 0; i < n; i++) + fixed64_pack(ini[i], (uint64_t *) out + i); +#endif +} + +/** + * Get the minimum number of bytes required to pack a field value of a + * particular type. + * + * \param type + * Field type. + * \return + * Number of bytes. + */ +static unsigned +get_type_min_size(ProtobufCType type) +{ + if (type == PROTOBUF_C_TYPE_SFIXED32 || + type == PROTOBUF_C_TYPE_FIXED32 || + type == PROTOBUF_C_TYPE_FLOAT) + { + return 4; + } + if (type == PROTOBUF_C_TYPE_SFIXED64 || + type == PROTOBUF_C_TYPE_FIXED64 || + type == PROTOBUF_C_TYPE_DOUBLE) + { + return 8; + } + return 1; +} + +/** + * Packs the elements of a repeated field and returns the serialised field and + * its length. + * + * \param field + * Field descriptor. + * \param count + * Number of elements in the repeated field array. + * \param member + * Pointer to the elements for this repeated field. + * \param[out] out + * Serialised representation of the repeated field. + * \return + * Number of bytes serialised to `out`. + */ +static size_t +repeated_field_pack(const ProtobufCFieldDescriptor *field, + size_t count, const void *member, uint8_t *out) +{ + void *array = *(void * const *) member; + unsigned i; + + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { + unsigned header_len; + unsigned len_start; + unsigned min_length; + unsigned payload_len; + unsigned length_size_min; + unsigned actual_length_size; + uint8_t *payload_at; + + if (count == 0) + return 0; + header_len = tag_pack(field->id, out); + out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + len_start = header_len; + min_length = get_type_min_size(field->type) * count; + length_size_min = uint32_size(min_length); + header_len += length_size_min; + payload_at = out + header_len; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + copy_to_little_endian_32(payload_at, array, count); + payload_at += count * 4; + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + copy_to_little_endian_64(payload_at, array, count); + payload_at += count * 8; + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + payload_at += int32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_SINT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + payload_at += sint32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_SINT64: { + const int64_t *arr = (const int64_t *) array; + for (i = 0; i < count; i++) + payload_at += sint64_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_UINT32: { + const uint32_t *arr = (const uint32_t *) array; + for (i = 0; i < count; i++) + payload_at += uint32_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: { + const uint64_t *arr = (const uint64_t *) array; + for (i = 0; i < count; i++) + payload_at += uint64_pack(arr[i], payload_at); + break; + } + case PROTOBUF_C_TYPE_BOOL: { + const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array; + for (i = 0; i < count; i++) + payload_at += boolean_pack(arr[i], payload_at); + break; + } + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + + payload_len = payload_at - (out + header_len); + actual_length_size = uint32_size(payload_len); + if (length_size_min != actual_length_size) { + assert(actual_length_size == length_size_min + 1); + memmove(out + header_len + 1, out + header_len, + payload_len); + header_len++; + } + uint32_pack(payload_len, out + len_start); + return header_len + payload_len; + } else { + /* not "packed" cased */ + /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ + size_t rv = 0; + unsigned siz = sizeof_elt_in_repeated_array(field->type); + + for (i = 0; i < count; i++) { + rv += required_field_pack(field, array, out + rv); + array = (char *)array + siz; + } + return rv; + } +} + +static size_t +unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out) +{ + size_t rv = tag_pack(field->tag, out); + out[0] |= field->wire_type; + memcpy(out + rv, field->data, field->len); + return rv + field->len; +} + +/**@}*/ + +size_t +protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = ((const char *) message) + field->offset; + + /* + * It doesn't hurt to compute qmember (a pointer to the + * quantifier field of the structure), but the pointer is only + * valid if the field is: + * - a repeated field, or + * - a field that is part of a oneof + * - an optional field that isn't a pointer type + * (Meaning: not a message or a string). + */ + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_pack(field, member, out + rv); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_pack( + field, + *(const uint32_t *) qmember, + member, + out + rv + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_pack( + field, + *(const protobuf_c_boolean *) qmember, + member, + out + rv + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_pack(field, member, out + rv); + } else { + rv += repeated_field_pack(field, *(const size_t *) qmember, + member, out + rv); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_pack(&message->unknown_fields[i], out + rv); + return rv; +} + +/** + * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation + * + * Routines mainly used by protobuf_c_message_pack_to_buffer(). + * + * \ingroup internal + * @{ + */ + +/** + * Pack a required field to a virtual buffer. + * + * \param field + * Field descriptor. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes packed. + */ +static size_t +required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const void *member, ProtobufCBuffer *buffer) +{ + size_t rv; + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; + + rv = tag_pack(field->id, scratch); + switch (field->type) { + case PROTOBUF_C_TYPE_SINT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += sint32_pack(*(const int32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += int32_pack(*(const int32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_UINT32: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += uint32_pack(*(const uint32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SINT64: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += sint64_pack(*(const int64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += uint64_pack(*(const uint64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; + rv += fixed32_pack(*(const uint32_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; + rv += fixed64_pack(*(const uint64_t *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_BOOL: + scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; + rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv); + buffer->append(buffer, rv, scratch); + break; + case PROTOBUF_C_TYPE_STRING: { + const char *str = *(char *const *) member; + size_t sublen = str ? strlen(str) : 0; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, (const uint8_t *) str); + rv += sublen; + break; + } + case PROTOBUF_C_TYPE_BYTES: { + const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member); + size_t sublen = bd->len; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, bd->data); + rv += sublen; + break; + } + case PROTOBUF_C_TYPE_MESSAGE: { + uint8_t simple_buffer_scratch[256]; + size_t sublen; + const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; + ProtobufCBufferSimple simple_buffer = + PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch); + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + if (msg == NULL) + sublen = 0; + else + sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base); + rv += uint32_pack(sublen, scratch + rv); + buffer->append(buffer, rv, scratch); + buffer->append(buffer, sublen, simple_buffer.data); + rv += sublen; + PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer); + break; + } + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; +} + +/** + * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum. + * + * \param field + * Field descriptor. + * \param oneof_case + * Enum value that selects the field in the oneof. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + uint32_t oneof_case, + const void *member, ProtobufCBuffer *buffer) +{ + if (oneof_case != field->id) { + return 0; + } + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void *const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Pack an optional field to a buffer. + * + * \param field + * Field descriptor. + * \param has + * Whether the field is set. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const protobuf_c_boolean has, + const void *member, ProtobufCBuffer *buffer) +{ + if (field->type == PROTOBUF_C_TYPE_MESSAGE || + field->type == PROTOBUF_C_TYPE_STRING) + { + const void *ptr = *(const void *const *) member; + if (ptr == NULL || ptr == field->default_value) + return 0; + } else { + if (!has) + return 0; + } + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Pack an unlabeled field to a buffer. + * + * \param field + * Field descriptor. + * \param member + * The element to be packed. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes serialised to `buffer`. + */ +static size_t +unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + const void *member, ProtobufCBuffer *buffer) +{ + if (field_is_zeroish(field, member)) + return 0; + return required_field_pack_to_buffer(field, member, buffer); +} + +/** + * Get the packed size of an array of same field type. + * + * \param field + * Field descriptor. + * \param count + * Number of elements of this type. + * \param array + * The elements to get the size of. + * \return + * Number of bytes required. + */ +static size_t +get_packed_payload_length(const ProtobufCFieldDescriptor *field, + unsigned count, const void *array) +{ + unsigned rv = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + return count * 4; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + return count * 8; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + rv += int32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_SINT32: { + const int32_t *arr = (const int32_t *) array; + for (i = 0; i < count; i++) + rv += sint32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_UINT32: { + const uint32_t *arr = (const uint32_t *) array; + for (i = 0; i < count; i++) + rv += uint32_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_SINT64: { + const int64_t *arr = (const int64_t *) array; + for (i = 0; i < count; i++) + rv += sint64_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: { + const uint64_t *arr = (const uint64_t *) array; + for (i = 0; i < count; i++) + rv += uint64_size(arr[i]); + break; + } + case PROTOBUF_C_TYPE_BOOL: + return count; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; +} + +/** + * Pack an array of same field type to a virtual buffer. + * + * \param field + * Field descriptor. + * \param count + * Number of elements of this type. + * \param array + * The elements to get the size of. + * \param[out] buffer + * Virtual buffer to append data to. + * \return + * Number of bytes packed. + */ +static size_t +pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field, + unsigned count, const void *array, + ProtobufCBuffer *buffer) +{ + uint8_t scratch[16]; + size_t rv = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: +#if !defined(WORDS_BIGENDIAN) + rv = count * 4; + goto no_packing_needed; +#else + for (i = 0; i < count; i++) { + unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; +#endif + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: +#if !defined(WORDS_BIGENDIAN) + rv = count * 8; + goto no_packing_needed; +#else + for (i = 0; i < count; i++) { + unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; +#endif + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + for (i = 0; i < count; i++) { + unsigned len = int32_pack(((int32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_SINT32: + for (i = 0; i < count; i++) { + unsigned len = sint32_pack(((int32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_UINT32: + for (i = 0; i < count; i++) { + unsigned len = uint32_pack(((uint32_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_SINT64: + for (i = 0; i < count; i++) { + unsigned len = sint64_pack(((int64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + for (i = 0; i < count; i++) { + unsigned len = uint64_pack(((uint64_t *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + break; + case PROTOBUF_C_TYPE_BOOL: + for (i = 0; i < count; i++) { + unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch); + buffer->append(buffer, len, scratch); + rv += len; + } + return count; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + return rv; + +#if !defined(WORDS_BIGENDIAN) +no_packing_needed: + buffer->append(buffer, rv, array); + return rv; +#endif +} + +static size_t +repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, + unsigned count, const void *member, + ProtobufCBuffer *buffer) +{ + char *array = *(char * const *) member; + + if (count == 0) + return 0; + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; + size_t rv = tag_pack(field->id, scratch); + size_t payload_len = get_packed_payload_length(field, count, array); + size_t tmp; + + scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + rv += uint32_pack(payload_len, scratch + rv); + buffer->append(buffer, rv, scratch); + tmp = pack_buffer_packed_payload(field, count, array, buffer); + assert(tmp == payload_len); + return rv + payload_len; + } else { + size_t siz; + unsigned i; + /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ + unsigned rv = 0; + + siz = sizeof_elt_in_repeated_array(field->type); + for (i = 0; i < count; i++) { + rv += required_field_pack_to_buffer(field, array, buffer); + array += siz; + } + return rv; + } +} + +static size_t +unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field, + ProtobufCBuffer *buffer) +{ + uint8_t header[MAX_UINT64_ENCODED_SIZE]; + size_t rv = tag_pack(field->tag, header); + + header[0] |= field->wire_type; + buffer->append(buffer, rv, header); + buffer->append(buffer, field->len, field->data); + return rv + field->len; +} + +/**@}*/ + +size_t +protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message, + ProtobufCBuffer *buffer) +{ + unsigned i; + size_t rv = 0; + + ASSERT_IS_MESSAGE(message); + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *field = + message->descriptor->fields + i; + const void *member = + ((const char *) message) + field->offset; + const void *qmember = + ((const char *) message) + field->quantifier_offset; + + if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + rv += required_field_pack_to_buffer(field, member, buffer); + } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL || + field->label == PROTOBUF_C_LABEL_NONE) && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) { + rv += oneof_field_pack_to_buffer( + field, + *(const uint32_t *) qmember, + member, + buffer + ); + } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { + rv += optional_field_pack_to_buffer( + field, + *(const protobuf_c_boolean *) qmember, + member, + buffer + ); + } else if (field->label == PROTOBUF_C_LABEL_NONE) { + rv += unlabeled_field_pack_to_buffer( + field, + member, + buffer + ); + } else { + rv += repeated_field_pack_to_buffer( + field, + *(const size_t *) qmember, + member, + buffer + ); + } + } + for (i = 0; i < message->n_unknown_fields; i++) + rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer); + + return rv; +} + +/** + * \defgroup unpack unpacking implementation + * + * Routines mainly used by the unpacking functions. + * + * \ingroup internal + * @{ + */ + +static inline int +int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value) +{ + unsigned n; + unsigned start; + + if (n_ranges == 0) + return -1; + start = 0; + n = n_ranges; + while (n > 1) { + unsigned mid = start + n / 2; + + if (value < ranges[mid].start_value) { + n = mid - start; + } else if (value >= ranges[mid].start_value + + (int) (ranges[mid + 1].orig_index - + ranges[mid].orig_index)) + { + unsigned new_start = mid + 1; + n = start + n - new_start; + start = new_start; + } else + return (value - ranges[mid].start_value) + + ranges[mid].orig_index; + } + if (n > 0) { + unsigned start_orig_index = ranges[start].orig_index; + unsigned range_size = + ranges[start + 1].orig_index - start_orig_index; + + if (ranges[start].start_value <= value && + value < (int) (ranges[start].start_value + range_size)) + { + return (value - ranges[start].start_value) + + start_orig_index; + } + } + return -1; +} + +static size_t +parse_tag_and_wiretype(size_t len, + const uint8_t *data, + uint32_t *tag_out, + ProtobufCWireType *wiretype_out) +{ + unsigned max_rv = len > 5 ? 5 : len; + uint32_t tag = (data[0] & 0x7f) >> 3; + unsigned shift = 4; + unsigned rv; + + *wiretype_out = data[0] & 7; + if ((data[0] & 0x80) == 0) { + *tag_out = tag; + return 1; + } + for (rv = 1; rv < max_rv; rv++) { + if (data[rv] & 0x80) { + tag |= (data[rv] & 0x7f) << shift; + shift += 7; + } else { + tag |= data[rv] << shift; + *tag_out = tag; + return rv + 1; + } + } + return 0; /* error: bad header */ +} + +/* sizeof(ScannedMember) must be <= (1UL< len) { + PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val); + return 0; + } + return hdr_len + val; +} + +static size_t +max_b128_numbers(size_t len, const uint8_t *data) +{ + size_t rv = 0; + while (len--) + if ((*data++ & 0x80) == 0) + ++rv; + return rv; +} + +/**@}*/ + +/** + * Merge earlier message into a latter message. + * + * For numeric types and strings, if the same value appears multiple + * times, the parser accepts the last value it sees. For embedded + * message fields, the parser merges multiple instances of the same + * field. That is, all singular scalar fields in the latter instance + * replace those in the former, singular embedded messages are merged, + * and repeated fields are concatenated. + * + * The earlier message should be freed after calling this function, as + * some of its fields may have been reused and changed to their default + * values during the merge. + */ +static protobuf_c_boolean +merge_messages(ProtobufCMessage *earlier_msg, + ProtobufCMessage *latter_msg, + ProtobufCAllocator *allocator) +{ + unsigned i; + const ProtobufCFieldDescriptor *fields = + latter_msg->descriptor->fields; + for (i = 0; i < latter_msg->descriptor->n_fields; i++) { + if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) { + size_t *n_earlier = + STRUCT_MEMBER_PTR(size_t, earlier_msg, + fields[i].quantifier_offset); + uint8_t **p_earlier = + STRUCT_MEMBER_PTR(uint8_t *, earlier_msg, + fields[i].offset); + size_t *n_latter = + STRUCT_MEMBER_PTR(size_t, latter_msg, + fields[i].quantifier_offset); + uint8_t **p_latter = + STRUCT_MEMBER_PTR(uint8_t *, latter_msg, + fields[i].offset); + + if (*n_earlier > 0) { + if (*n_latter > 0) { + /* Concatenate the repeated field */ + size_t el_size = + sizeof_elt_in_repeated_array(fields[i].type); + uint8_t *new_field; + + new_field = do_alloc(allocator, + (*n_earlier + *n_latter) * el_size); + if (!new_field) + return FALSE; + + memcpy(new_field, *p_earlier, + *n_earlier * el_size); + memcpy(new_field + + *n_earlier * el_size, + *p_latter, + *n_latter * el_size); + + do_free(allocator, *p_latter); + do_free(allocator, *p_earlier); + *p_latter = new_field; + *n_latter = *n_earlier + *n_latter; + } else { + /* Zero copy the repeated field from the earlier message */ + *n_latter = *n_earlier; + *p_latter = *p_earlier; + } + /* Make sure the field does not get double freed */ + *n_earlier = 0; + *p_earlier = 0; + } + } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL || + fields[i].label == PROTOBUF_C_LABEL_NONE) { + const ProtobufCFieldDescriptor *field; + uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t, + earlier_msg, + fields[i]. + quantifier_offset); + uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t, + latter_msg, + fields[i]. + quantifier_offset); + protobuf_c_boolean need_to_merge = FALSE; + void *earlier_elem; + void *latter_elem; + const void *def_val; + + if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) { + if (*latter_case_p == 0) { + /* lookup correct oneof field */ + int field_index = + int_range_lookup( + latter_msg->descriptor + ->n_field_ranges, + latter_msg->descriptor + ->field_ranges, + *earlier_case_p); + field = latter_msg->descriptor->fields + + field_index; + } else { + /* Oneof is present in the latter message, move on */ + continue; + } + } else { + field = &fields[i]; + } + + earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset); + latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset); + def_val = field->default_value; + + switch (field->type) { + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem; + ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem; + if (em != NULL) { + if (lm != NULL) { + if (!merge_messages(em, lm, allocator)) + return FALSE; + /* Already merged */ + need_to_merge = FALSE; + } else { + /* Zero copy the message */ + need_to_merge = TRUE; + } + } + break; + } + case PROTOBUF_C_TYPE_BYTES: { + uint8_t *e_data = + ((ProtobufCBinaryData *) earlier_elem)->data; + uint8_t *l_data = + ((ProtobufCBinaryData *) latter_elem)->data; + const ProtobufCBinaryData *d_bd = + (ProtobufCBinaryData *) def_val; + + need_to_merge = + (e_data != NULL && + (d_bd == NULL || + e_data != d_bd->data)) && + (l_data == NULL || + (d_bd != NULL && + l_data == d_bd->data)); + break; + } + case PROTOBUF_C_TYPE_STRING: { + char *e_str = *(char **) earlier_elem; + char *l_str = *(char **) latter_elem; + const char *d_str = def_val; + + need_to_merge = e_str != d_str && l_str == d_str; + break; + } + default: { + /* Could be has field or case enum, the logic is + * equivalent, since 0 (FALSE) means not set for + * oneof */ + need_to_merge = (*earlier_case_p != 0) && + (*latter_case_p == 0); + break; + } + } + + if (need_to_merge) { + size_t el_size = + sizeof_elt_in_repeated_array(field->type); + memcpy(latter_elem, earlier_elem, el_size); + /* + * Reset the element from the old message to 0 + * to make sure earlier message deallocation + * doesn't corrupt zero-copied data in the new + * message, earlier message will be freed after + * this function is called anyway + */ + memset(earlier_elem, 0, el_size); + + if (field->quantifier_offset != 0) { + /* Set the has field or the case enum, + * if applicable */ + *latter_case_p = *earlier_case_p; + *earlier_case_p = 0; + } + } + } + } + return TRUE; +} + +/** + * Count packed elements. + * + * Given a raw slab of packed-repeated values, determine the number of + * elements. This function detects certain kinds of errors but not + * others; the remaining error checking is done by + * parse_packed_repeated_member(). + */ +static protobuf_c_boolean +count_packed_elements(ProtobufCType type, + size_t len, const uint8_t *data, size_t *count_out) +{ + switch (type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + if (len % 4 != 0) { + PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types"); + return FALSE; + } + *count_out = len / 4; + return TRUE; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + if (len % 8 != 0) { + PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types"); + return FALSE; + } + *count_out = len / 8; + return TRUE; + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_UINT64: + *count_out = max_b128_numbers(len, data); + return TRUE; + case PROTOBUF_C_TYPE_BOOL: + *count_out = len; + return TRUE; + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_BYTES: + case PROTOBUF_C_TYPE_MESSAGE: + default: + PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type); + return FALSE; + } +} + +static inline uint32_t +parse_uint32(unsigned len, const uint8_t *data) +{ + uint32_t rv = data[0] & 0x7f; + if (len > 1) { + rv |= ((uint32_t) (data[1] & 0x7f) << 7); + if (len > 2) { + rv |= ((uint32_t) (data[2] & 0x7f) << 14); + if (len > 3) { + rv |= ((uint32_t) (data[3] & 0x7f) << 21); + if (len > 4) + rv |= ((uint32_t) (data[4]) << 28); + } + } + } + return rv; +} + +static inline uint32_t +parse_int32(unsigned len, const uint8_t *data) +{ + return parse_uint32(len, data); +} + +static inline int32_t +unzigzag32(uint32_t v) +{ + if (v & 1) + return -(v >> 1) - 1; + else + return v >> 1; +} + +static inline uint32_t +parse_fixed_uint32(const uint8_t *data) +{ +#if !defined(WORDS_BIGENDIAN) + uint32_t t; + memcpy(&t, data, 4); + return t; +#else + return data[0] | + ((uint32_t) (data[1]) << 8) | + ((uint32_t) (data[2]) << 16) | + ((uint32_t) (data[3]) << 24); +#endif +} + +static uint64_t +parse_uint64(unsigned len, const uint8_t *data) +{ + unsigned shift, i; + uint64_t rv; + + if (len < 5) + return parse_uint32(len, data); + rv = ((uint64_t) (data[0] & 0x7f)) | + ((uint64_t) (data[1] & 0x7f) << 7) | + ((uint64_t) (data[2] & 0x7f) << 14) | + ((uint64_t) (data[3] & 0x7f) << 21); + shift = 28; + for (i = 4; i < len; i++) { + rv |= (((uint64_t) (data[i] & 0x7f)) << shift); + shift += 7; + } + return rv; +} + +static inline int64_t +unzigzag64(uint64_t v) +{ + if (v & 1) + return -(v >> 1) - 1; + else + return v >> 1; +} + +static inline uint64_t +parse_fixed_uint64(const uint8_t *data) +{ +#if !defined(WORDS_BIGENDIAN) + uint64_t t; + memcpy(&t, data, 8); + return t; +#else + return (uint64_t) parse_fixed_uint32(data) | + (((uint64_t) parse_fixed_uint32(data + 4)) << 32); +#endif +} + +static protobuf_c_boolean +parse_boolean(unsigned len, const uint8_t *data) +{ + unsigned i; + for (i = 0; i < len; i++) + if (data[i] & 0x7f) + return TRUE; + return FALSE; +} + +static protobuf_c_boolean +parse_required_member(ScannedMember *scanned_member, + void *member, + ProtobufCAllocator *allocator, + protobuf_c_boolean maybe_clear) +{ + unsigned len = scanned_member->len; + const uint8_t *data = scanned_member->data; + ProtobufCWireType wire_type = scanned_member->wire_type; + + switch (scanned_member->field->type) { + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int32_t *) member = parse_int32(len, data); + return TRUE; + case PROTOBUF_C_TYPE_UINT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(uint32_t *) member = parse_uint32(len, data); + return TRUE; + case PROTOBUF_C_TYPE_SINT32: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int32_t *) member = unzigzag32(parse_uint32(len, data)); + return TRUE; + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT) + return FALSE; + *(uint32_t *) member = parse_fixed_uint32(data); + return TRUE; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(uint64_t *) member = parse_uint64(len, data); + return TRUE; + case PROTOBUF_C_TYPE_SINT64: + if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) + return FALSE; + *(int64_t *) member = unzigzag64(parse_uint64(len, data)); + return TRUE; + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT) + return FALSE; + *(uint64_t *) member = parse_fixed_uint64(data); + return TRUE; + case PROTOBUF_C_TYPE_BOOL: + *(protobuf_c_boolean *) member = parse_boolean(len, data); + return TRUE; + case PROTOBUF_C_TYPE_STRING: { + char **pstr = member; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + if (maybe_clear && *pstr != NULL) { + const char *def = scanned_member->field->default_value; + if (*pstr != NULL && *pstr != def) + do_free(allocator, *pstr); + } + *pstr = do_alloc(allocator, len - pref_len + 1); + if (*pstr == NULL) + return FALSE; + memcpy(*pstr, data + pref_len, len - pref_len); + (*pstr)[len - pref_len] = 0; + return TRUE; + } + case PROTOBUF_C_TYPE_BYTES: { + ProtobufCBinaryData *bd = member; + const ProtobufCBinaryData *def_bd; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + def_bd = scanned_member->field->default_value; + if (maybe_clear && + bd->data != NULL && + (def_bd == NULL || bd->data != def_bd->data)) + { + do_free(allocator, bd->data); + } + if (len - pref_len > 0) { + bd->data = do_alloc(allocator, len - pref_len); + if (bd->data == NULL) + return FALSE; + memcpy(bd->data, data + pref_len, len - pref_len); + } else { + bd->data = NULL; + } + bd->len = len - pref_len; + return TRUE; + } + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage **pmessage = member; + ProtobufCMessage *subm; + const ProtobufCMessage *def_mess; + protobuf_c_boolean merge_successful = TRUE; + unsigned pref_len = scanned_member->length_prefix_len; + + if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) + return FALSE; + + def_mess = scanned_member->field->default_value; + subm = protobuf_c_message_unpack(scanned_member->field->descriptor, + allocator, + len - pref_len, + data + pref_len); + + if (maybe_clear && + *pmessage != NULL && + *pmessage != def_mess) + { + if (subm != NULL) + merge_successful = merge_messages(*pmessage, subm, allocator); + /* Delete the previous message */ + protobuf_c_message_free_unpacked(*pmessage, allocator); + } + *pmessage = subm; + if (subm == NULL || !merge_successful) + return FALSE; + return TRUE; + } + } + return FALSE; +} + +static protobuf_c_boolean +parse_oneof_member (ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message, + scanned_member->field->quantifier_offset); + + /* If we have already parsed a member of this oneof, free it. */ + if (*oneof_case != 0) { + /* lookup field */ + int field_index = + int_range_lookup(message->descriptor->n_field_ranges, + message->descriptor->field_ranges, + *oneof_case); + const ProtobufCFieldDescriptor *old_field = + message->descriptor->fields + field_index; + size_t el_size = sizeof_elt_in_repeated_array(old_field->type); + + switch (old_field->type) { + case PROTOBUF_C_TYPE_STRING: { + char **pstr = member; + const char *def = old_field->default_value; + if (*pstr != NULL && *pstr != def) + do_free(allocator, *pstr); + break; + } + case PROTOBUF_C_TYPE_BYTES: { + ProtobufCBinaryData *bd = member; + const ProtobufCBinaryData *def_bd = old_field->default_value; + if (bd->data != NULL && + (def_bd == NULL || bd->data != def_bd->data)) + { + do_free(allocator, bd->data); + } + break; + } + case PROTOBUF_C_TYPE_MESSAGE: { + ProtobufCMessage **pmessage = member; + const ProtobufCMessage *def_mess = old_field->default_value; + if (*pmessage != NULL && *pmessage != def_mess) + protobuf_c_message_free_unpacked(*pmessage, allocator); + break; + } + default: + break; + } + + memset (member, 0, el_size); + } + if (!parse_required_member (scanned_member, member, allocator, TRUE)) + return FALSE; + + *oneof_case = scanned_member->tag; + return TRUE; +} + + +static protobuf_c_boolean +parse_optional_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + if (!parse_required_member(scanned_member, member, allocator, TRUE)) + return FALSE; + if (scanned_member->field->quantifier_offset != 0) + STRUCT_MEMBER(protobuf_c_boolean, + message, + scanned_member->field->quantifier_offset) = TRUE; + return TRUE; +} + +static protobuf_c_boolean +parse_repeated_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); + size_t siz = sizeof_elt_in_repeated_array(field->type); + char *array = *(char **) member; + + if (!parse_required_member(scanned_member, array + siz * (*p_n), + allocator, FALSE)) + { + return FALSE; + } + *p_n += 1; + return TRUE; +} + +static unsigned +scan_varint(unsigned len, const uint8_t *data) +{ + unsigned i; + if (len > 10) + len = 10; + for (i = 0; i < len; i++) + if ((data[i] & 0x80) == 0) + break; + if (i == len) + return 0; + return i + 1; +} + +static protobuf_c_boolean +parse_packed_repeated_member(ScannedMember *scanned_member, + void *member, + ProtobufCMessage *message) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); + size_t siz = sizeof_elt_in_repeated_array(field->type); + void *array = *(char **) member + siz * (*p_n); + const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len; + size_t rem = scanned_member->len - scanned_member->length_prefix_len; + size_t count = 0; + unsigned i; + + switch (field->type) { + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + count = (scanned_member->len - scanned_member->length_prefix_len) / 4; +#if !defined(WORDS_BIGENDIAN) + goto no_unpacking_needed; +#else + for (i = 0; i < count; i++) { + ((uint32_t *) array)[i] = parse_fixed_uint32(at); + at += 4; + } + break; +#endif + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + count = (scanned_member->len - scanned_member->length_prefix_len) / 8; +#if !defined(WORDS_BIGENDIAN) + goto no_unpacking_needed; +#else + for (i = 0; i < count; i++) { + ((uint64_t *) array)[i] = parse_fixed_uint64(at); + at += 8; + } + break; +#endif + case PROTOBUF_C_TYPE_ENUM: + case PROTOBUF_C_TYPE_INT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value"); + return FALSE; + } + ((int32_t *) array)[count++] = parse_int32(s, at); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_SINT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value"); + return FALSE; + } + ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at)); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_UINT32: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value"); + return FALSE; + } + ((uint32_t *) array)[count++] = parse_uint32(s, at); + at += s; + rem -= s; + } + break; + + case PROTOBUF_C_TYPE_SINT64: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value"); + return FALSE; + } + ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at)); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_UINT64: + while (rem > 0) { + unsigned s = scan_varint(rem, at); + if (s == 0) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value"); + return FALSE; + } + ((int64_t *) array)[count++] = parse_uint64(s, at); + at += s; + rem -= s; + } + break; + case PROTOBUF_C_TYPE_BOOL: + count = rem; + for (i = 0; i < count; i++) { + if (at[i] > 1) { + PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value"); + return FALSE; + } + ((protobuf_c_boolean *) array)[i] = at[i]; + } + break; + default: + PROTOBUF_C__ASSERT_NOT_REACHED(); + } + *p_n += count; + return TRUE; + +#if !defined(WORDS_BIGENDIAN) +no_unpacking_needed: + memcpy(array, at, count * siz); + *p_n += count; + return TRUE; +#endif +} + +static protobuf_c_boolean +is_packable_type(ProtobufCType type) +{ + return + type != PROTOBUF_C_TYPE_STRING && + type != PROTOBUF_C_TYPE_BYTES && + type != PROTOBUF_C_TYPE_MESSAGE; +} + +static protobuf_c_boolean +parse_member(ScannedMember *scanned_member, + ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCFieldDescriptor *field = scanned_member->field; + void *member; + + if (field == NULL) { + ProtobufCMessageUnknownField *ufield = + message->unknown_fields + + (message->n_unknown_fields++); + ufield->tag = scanned_member->tag; + ufield->wire_type = scanned_member->wire_type; + ufield->len = scanned_member->len; + ufield->data = do_alloc(allocator, scanned_member->len); + if (ufield->data == NULL) + return FALSE; + memcpy(ufield->data, scanned_member->data, ufield->len); + return TRUE; + } + member = (char *) message + field->offset; + switch (field->label) { + case PROTOBUF_C_LABEL_REQUIRED: + return parse_required_member(scanned_member, member, + allocator, TRUE); + case PROTOBUF_C_LABEL_OPTIONAL: + case PROTOBUF_C_LABEL_NONE: + if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) { + return parse_oneof_member(scanned_member, member, + message, allocator); + } else { + return parse_optional_member(scanned_member, member, + message, allocator); + } + case PROTOBUF_C_LABEL_REPEATED: + if (scanned_member->wire_type == + PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || + is_packable_type(field->type))) + { + return parse_packed_repeated_member(scanned_member, + member, message); + } else { + return parse_repeated_member(scanned_member, + member, message, + allocator); + } + } + PROTOBUF_C__ASSERT_NOT_REACHED(); + return 0; +} + +/** + * Initialise messages generated by old code. + * + * This function is used if desc->message_init == NULL (which occurs + * for old code, and which would be useful to support allocating + * descriptors dynamically). + */ +static void +message_init_generic(const ProtobufCMessageDescriptor *desc, + ProtobufCMessage *message) +{ + unsigned i; + + memset(message, 0, desc->sizeof_message); + message->descriptor = desc; + for (i = 0; i < desc->n_fields; i++) { + if (desc->fields[i].default_value != NULL && + desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED) + { + void *field = + STRUCT_MEMBER_P(message, desc->fields[i].offset); + const void *dv = desc->fields[i].default_value; + + switch (desc->fields[i].type) { + case PROTOBUF_C_TYPE_INT32: + case PROTOBUF_C_TYPE_SINT32: + case PROTOBUF_C_TYPE_SFIXED32: + case PROTOBUF_C_TYPE_UINT32: + case PROTOBUF_C_TYPE_FIXED32: + case PROTOBUF_C_TYPE_FLOAT: + case PROTOBUF_C_TYPE_ENUM: + memcpy(field, dv, 4); + break; + case PROTOBUF_C_TYPE_INT64: + case PROTOBUF_C_TYPE_SINT64: + case PROTOBUF_C_TYPE_SFIXED64: + case PROTOBUF_C_TYPE_UINT64: + case PROTOBUF_C_TYPE_FIXED64: + case PROTOBUF_C_TYPE_DOUBLE: + memcpy(field, dv, 8); + break; + case PROTOBUF_C_TYPE_BOOL: + memcpy(field, dv, sizeof(protobuf_c_boolean)); + break; + case PROTOBUF_C_TYPE_BYTES: + memcpy(field, dv, sizeof(ProtobufCBinaryData)); + break; + + case PROTOBUF_C_TYPE_STRING: + case PROTOBUF_C_TYPE_MESSAGE: + /* + * The next line essentially implements a cast + * from const, which is totally unavoidable. + */ + *(const void **) field = dv; + break; + } + } + } +} + +/**@}*/ + +/* + * ScannedMember slabs (an unpacking implementation detail). Before doing real + * unpacking, we first scan through the elements to see how many there are (for + * repeated fields), and which field to use (for non-repeated fields given + * twice). + * + * In order to avoid allocations for small messages, we keep a stack-allocated + * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we + * fill that up, we allocate each slab twice as large as the previous one. + */ +#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4 + +/* + * The number of slabs, including the stack-allocated ones; choose the number so + * that we would overflow if we needed a slab larger than provided. + */ +#define MAX_SCANNED_MEMBER_SLAB \ + (sizeof(unsigned int)*8 - 1 \ + - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \ + - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2) + +#define REQUIRED_FIELD_BITMAP_SET(index) \ + (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8))) + +#define REQUIRED_FIELD_BITMAP_IS_SET(index) \ + (required_fields_bitmap[(index)/8] & (1UL<<((index)%8))) + +ProtobufCMessage * +protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc, + ProtobufCAllocator *allocator, + size_t len, const uint8_t *data) +{ + ProtobufCMessage *rv; + size_t rem = len; + const uint8_t *at = data; + const ProtobufCFieldDescriptor *last_field = desc->fields + 0; + ScannedMember first_member_slab[1UL << + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2]; + + /* + * scanned_member_slabs[i] is an array of arrays of ScannedMember. + * The first slab (scanned_member_slabs[0] is just a pointer to + * first_member_slab), above. All subsequent slabs will be allocated + * using the allocator. + */ + ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1]; + unsigned which_slab = 0; /* the slab we are currently populating */ + unsigned in_slab_index = 0; /* number of members in the slab */ + size_t n_unknown = 0; + unsigned f; + unsigned j; + unsigned i_slab; + unsigned last_field_index = 0; + unsigned required_fields_bitmap_len; + unsigned char required_fields_bitmap_stack[16]; + unsigned char *required_fields_bitmap = required_fields_bitmap_stack; + protobuf_c_boolean required_fields_bitmap_alloced = FALSE; + + ASSERT_IS_MESSAGE_DESCRIPTOR(desc); + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + + rv = do_alloc(allocator, desc->sizeof_message); + if (!rv) + return (NULL); + scanned_member_slabs[0] = first_member_slab; + + required_fields_bitmap_len = (desc->n_fields + 7) / 8; + if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) { + required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len); + if (!required_fields_bitmap) { + do_free(allocator, rv); + return (NULL); + } + required_fields_bitmap_alloced = TRUE; + } + memset(required_fields_bitmap, 0, required_fields_bitmap_len); + + /* + * Generated code always defines "message_init". However, we provide a + * fallback for (1) users of old protobuf-c generated-code that do not + * provide the function, and (2) descriptors constructed from some other + * source (most likely, direct construction from the .proto file). + */ + if (desc->message_init != NULL) + protobuf_c_message_init(desc, rv); + else + message_init_generic(desc, rv); + + while (rem > 0) { + uint32_t tag; + ProtobufCWireType wire_type; + size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type); + const ProtobufCFieldDescriptor *field; + ScannedMember tmp; + + if (used == 0) { + PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + /* + * \todo Consider optimizing for field[1].id == tag, if field[1] + * exists! + */ + if (last_field == NULL || last_field->id != tag) { + /* lookup field */ + int field_index = + int_range_lookup(desc->n_field_ranges, + desc->field_ranges, + tag); + if (field_index < 0) { + field = NULL; + n_unknown++; + } else { + field = desc->fields + field_index; + last_field = field; + last_field_index = field_index; + } + } else { + field = last_field; + } + + if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED) + REQUIRED_FIELD_BITMAP_SET(last_field_index); + + at += used; + rem -= used; + tmp.tag = tag; + tmp.wire_type = wire_type; + tmp.field = field; + tmp.data = at; + tmp.length_prefix_len = 0; + + switch (wire_type) { + case PROTOBUF_C_WIRE_TYPE_VARINT: { + unsigned max_len = rem < 10 ? rem : 10; + unsigned i; + + for (i = 0; i < max_len; i++) + if ((at[i] & 0x80) == 0) + break; + if (i == max_len) { + PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = i + 1; + break; + } + case PROTOBUF_C_WIRE_TYPE_64BIT: + if (rem < 8) { + PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = 8; + break; + case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: { + size_t pref_len; + + tmp.len = scan_length_prefixed_data(rem, at, &pref_len); + if (tmp.len == 0) { + /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */ + goto error_cleanup_during_scan; + } + tmp.length_prefix_len = pref_len; + break; + } + case PROTOBUF_C_WIRE_TYPE_32BIT: + if (rem < 4) { + PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u", + (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + tmp.len = 4; + break; + default: + PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u", + wire_type, (unsigned) (at - data)); + goto error_cleanup_during_scan; + } + + if (in_slab_index == (1UL << + (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2))) + { + size_t size; + + in_slab_index = 0; + if (which_slab == MAX_SCANNED_MEMBER_SLAB) { + PROTOBUF_C_UNPACK_ERROR("too many fields"); + goto error_cleanup_during_scan; + } + which_slab++; + size = sizeof(ScannedMember) + << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2); + scanned_member_slabs[which_slab] = do_alloc(allocator, size); + if (scanned_member_slabs[which_slab] == NULL) + goto error_cleanup_during_scan; + } + scanned_member_slabs[which_slab][in_slab_index++] = tmp; + + if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) { + size_t *n = STRUCT_MEMBER_PTR(size_t, rv, + field->quantifier_offset); + if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && + (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || + is_packable_type(field->type))) + { + size_t count; + if (!count_packed_elements(field->type, + tmp.len - + tmp.length_prefix_len, + tmp.data + + tmp.length_prefix_len, + &count)) + { + PROTOBUF_C_UNPACK_ERROR("counting packed elements"); + goto error_cleanup_during_scan; + } + *n += count; + } else { + *n += 1; + } + } + + at += tmp.len; + rem -= tmp.len; + } + + /* allocate space for repeated fields, also check that all required fields have been set */ + for (f = 0; f < desc->n_fields; f++) { + const ProtobufCFieldDescriptor *field = desc->fields + f; + if (field->label == PROTOBUF_C_LABEL_REPEATED) { + size_t siz = + sizeof_elt_in_repeated_array(field->type); + size_t *n_ptr = + STRUCT_MEMBER_PTR(size_t, rv, + field->quantifier_offset); + if (*n_ptr != 0) { + unsigned n = *n_ptr; + void *a; + *n_ptr = 0; + assert(rv->descriptor != NULL); +#define CLEAR_REMAINING_N_PTRS() \ + for(f++;f < desc->n_fields; f++) \ + { \ + field = desc->fields + f; \ + if (field->label == PROTOBUF_C_LABEL_REPEATED) \ + STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \ + } + a = do_alloc(allocator, siz * n); + if (!a) { + CLEAR_REMAINING_N_PTRS(); + goto error_cleanup; + } + STRUCT_MEMBER(void *, rv, field->offset) = a; + } + } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { + if (field->default_value == NULL && + !REQUIRED_FIELD_BITMAP_IS_SET(f)) + { + CLEAR_REMAINING_N_PTRS(); + PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'", + desc->name, field->name); + goto error_cleanup; + } + } + } +#undef CLEAR_REMAINING_N_PTRS + + /* allocate space for unknown fields */ + if (n_unknown) { + rv->unknown_fields = do_alloc(allocator, + n_unknown * sizeof(ProtobufCMessageUnknownField)); + if (rv->unknown_fields == NULL) + goto error_cleanup; + } + + /* do real parsing */ + for (i_slab = 0; i_slab <= which_slab; i_slab++) { + unsigned max = (i_slab == which_slab) ? + in_slab_index : (1UL << (i_slab + 4)); + ScannedMember *slab = scanned_member_slabs[i_slab]; + + for (j = 0; j < max; j++) { + if (!parse_member(slab + j, rv, allocator)) { + PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s", + slab->field ? slab->field->name : "*unknown-field*", + desc->name); + goto error_cleanup; + } + } + } + + /* cleanup */ + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return rv; + +error_cleanup: + protobuf_c_message_free_unpacked(rv, allocator); + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return NULL; + +error_cleanup_during_scan: + do_free(allocator, rv); + for (j = 1; j <= which_slab; j++) + do_free(allocator, scanned_member_slabs[j]); + if (required_fields_bitmap_alloced) + do_free(allocator, required_fields_bitmap); + return NULL; +} + +void +protobuf_c_message_free_unpacked(ProtobufCMessage *message, + ProtobufCAllocator *allocator) +{ + const ProtobufCMessageDescriptor *desc; + unsigned f; + + if (message == NULL) + return; + + desc = message->descriptor; + + ASSERT_IS_MESSAGE(message); + + if (allocator == NULL) + allocator = &protobuf_c__allocator; + message->descriptor = NULL; + for (f = 0; f < desc->n_fields; f++) { + if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) && + desc->fields[f].id != + STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset)) + { + /* This is not the selected oneof, skip it */ + continue; + } + + if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) { + size_t n = STRUCT_MEMBER(size_t, + message, + desc->fields[f].quantifier_offset); + void *arr = STRUCT_MEMBER(void *, + message, + desc->fields[f].offset); + + if (arr != NULL) { + if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { + unsigned i; + for (i = 0; i < n; i++) + do_free(allocator, ((char **) arr)[i]); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { + unsigned i; + for (i = 0; i < n; i++) + do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { + unsigned i; + for (i = 0; i < n; i++) + protobuf_c_message_free_unpacked( + ((ProtobufCMessage **) arr)[i], + allocator + ); + } + do_free(allocator, arr); + } + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { + char *str = STRUCT_MEMBER(char *, message, + desc->fields[f].offset); + + if (str && str != desc->fields[f].default_value) + do_free(allocator, str); + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { + void *data = STRUCT_MEMBER(ProtobufCBinaryData, message, + desc->fields[f].offset).data; + const ProtobufCBinaryData *default_bd; + + default_bd = desc->fields[f].default_value; + if (data != NULL && + (default_bd == NULL || + default_bd->data != data)) + { + do_free(allocator, data); + } + } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage *sm; + + sm = STRUCT_MEMBER(ProtobufCMessage *, message, + desc->fields[f].offset); + if (sm && sm != desc->fields[f].default_value) + protobuf_c_message_free_unpacked(sm, allocator); + } + } + + for (f = 0; f < message->n_unknown_fields; f++) + do_free(allocator, message->unknown_fields[f].data); + if (message->unknown_fields != NULL) + do_free(allocator, message->unknown_fields); + + do_free(allocator, message); +} + +void +protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor, + void *message) +{ + descriptor->message_init((ProtobufCMessage *) (message)); +} + +protobuf_c_boolean +protobuf_c_message_check(const ProtobufCMessage *message) +{ + unsigned i; + + if (!message || + !message->descriptor || + message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) + { + return FALSE; + } + + for (i = 0; i < message->descriptor->n_fields; i++) { + const ProtobufCFieldDescriptor *f = message->descriptor->fields + i; + ProtobufCType type = f->type; + ProtobufCLabel label = f->label; + void *field = STRUCT_MEMBER_P (message, f->offset); + + if (label == PROTOBUF_C_LABEL_REPEATED) { + size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset); + + if (*quantity > 0 && *(void **) field == NULL) { + return FALSE; + } + + if (type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage **submessage = *(ProtobufCMessage ***) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (!protobuf_c_message_check(submessage[j])) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_STRING) { + char **string = *(char ***) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (!string[j]) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_BYTES) { + ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field; + unsigned j; + for (j = 0; j < *quantity; j++) { + if (bd[j].len > 0 && bd[j].data == NULL) + return FALSE; + } + } + + } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */ + + if (type == PROTOBUF_C_TYPE_MESSAGE) { + ProtobufCMessage *submessage = *(ProtobufCMessage **) field; + if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) { + if (!protobuf_c_message_check(submessage)) + return FALSE; + } + } else if (type == PROTOBUF_C_TYPE_STRING) { + char *string = *(char **) field; + if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL) + return FALSE; + } else if (type == PROTOBUF_C_TYPE_BYTES) { + protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset); + ProtobufCBinaryData *bd = field; + if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) { + if (bd->len > 0 && bd->data == NULL) + return FALSE; + } + } + } + } + + return TRUE; +} + +/* === services === */ + +typedef void (*GenericHandler) (void *service, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); +void +protobuf_c_service_invoke_internal(ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data) +{ + GenericHandler *handlers; + GenericHandler handler; + + /* + * Verify that method_index is within range. If this fails, you are + * likely invoking a newly added method on an old service. (Although + * other memory corruption bugs can cause this assertion too.) + */ + assert(method_index < service->descriptor->n_methods); + + /* + * Get the array of virtual methods (which are enumerated by the + * generated code). + */ + handlers = (GenericHandler *) (service + 1); + + /* + * Get our method and invoke it. + * \todo Seems like handler == NULL is a situation that needs handling. + */ + handler = handlers[method_index]; + (*handler)(service, input, closure, closure_data); +} + +void +protobuf_c_service_generated_init(ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy) +{ + ASSERT_IS_SERVICE_DESCRIPTOR(descriptor); + service->descriptor = descriptor; + service->destroy = destroy; + service->invoke = protobuf_c_service_invoke_internal; + memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler)); +} + +void protobuf_c_service_destroy(ProtobufCService *service) +{ + service->destroy(service); +} + +/* --- querying the descriptors --- */ + +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + + if (desc == NULL || desc->values_by_name == NULL) + return NULL; + + count = desc->n_value_names; + + while (count > 1) { + unsigned mid = start + count / 2; + int rv = strcmp(desc->values_by_name[mid].name, name); + if (rv == 0) + return desc->values + desc->values_by_name[mid].index; + else if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else + count = mid - start; + } + if (count == 0) + return NULL; + if (strcmp(desc->values_by_name[start].name, name) == 0) + return desc->values + desc->values_by_name[start].index; + return NULL; +} + +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc, + int value) +{ + int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value); + if (rv < 0) + return NULL; + return desc->values + rv; +} + +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + const ProtobufCFieldDescriptor *field; + + if (desc == NULL || desc->fields_sorted_by_name == NULL) + return NULL; + + count = desc->n_fields; + + while (count > 1) { + unsigned mid = start + count / 2; + int rv; + field = desc->fields + desc->fields_sorted_by_name[mid]; + rv = strcmp(field->name, name); + if (rv == 0) + return field; + else if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else + count = mid - start; + } + if (count == 0) + return NULL; + field = desc->fields + desc->fields_sorted_by_name[start]; + if (strcmp(field->name, name) == 0) + return field; + return NULL; +} + +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc, + unsigned value) +{ + int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value); + if (rv < 0) + return NULL; + return desc->fields + rv; +} + +const ProtobufCMethodDescriptor * +protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc, + const char *name) +{ + unsigned start = 0; + unsigned count; + + if (desc == NULL || desc->method_indices_by_name == NULL) + return NULL; + + count = desc->n_methods; + + while (count > 1) { + unsigned mid = start + count / 2; + unsigned mid_index = desc->method_indices_by_name[mid]; + const char *mid_name = desc->methods[mid_index].name; + int rv = strcmp(mid_name, name); + + if (rv == 0) + return desc->methods + desc->method_indices_by_name[mid]; + if (rv < 0) { + count = start + count - (mid + 1); + start = mid + 1; + } else { + count = mid - start; + } + } + if (count == 0) + return NULL; + if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0) + return desc->methods + desc->method_indices_by_name[start]; + return NULL; +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.h new file mode 100644 index 000000000..c8fa4fc2a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/protobuf-c/protobuf-c.h @@ -0,0 +1,1106 @@ +/* + * Copyright (c) 2008-2017, Dave Benson and the protobuf-c authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! \file + * \mainpage Introduction + * + * This is [protobuf-c], a C implementation of [Protocol Buffers]. + * + * This file defines the public API for the `libprotobuf-c` support library. + * This API includes interfaces that can be used directly by client code as well + * as the interfaces used by the code generated by the `protoc-c` compiler. + * + * The `libprotobuf-c` support library performs the actual serialization and + * deserialization of Protocol Buffers messages. It interacts with structures, + * definitions, and metadata generated by the `protoc-c` compiler from .proto + * files. + * + * \authors Dave Benson and the `protobuf-c` authors. + * + * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. + * + * [protobuf-c]: https://github.com/protobuf-c/protobuf-c + * [Protocol Buffers]: https://developers.google.com/protocol-buffers/ + * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause + * + * \page gencode Generated Code + * + * For each enum, we generate a C enum. For each message, we generate a C + * structure which can be cast to a `ProtobufCMessage`. + * + * For each enum and message, we generate a descriptor object that allows us to + * implement a kind of reflection on the structures. + * + * First, some naming conventions: + * + * - The name of the type for enums and messages and services is camel case + * (meaning WordsAreCrammedTogether) except that double underscores are used + * to delimit scopes. For example, the following `.proto` file: + * +~~~{.proto} + package foo.bar; + message BazBah { + optional int32 val = 1; + } +~~~ + * + * would generate a C type `Foo__Bar__BazBah`. + * + * - Identifiers for functions and globals are all lowercase, with camel case + * words separated by single underscores. For example, one of the function + * prototypes generated by `protoc-c` for the above example: + * +~~~{.c} +Foo__Bar__BazBah * + foo__bar__baz_bah__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +~~~ + * + * - Identifiers for enum values contain an uppercase prefix which embeds the + * package name and the enum type name. + * + * - A double underscore is used to separate further components of identifier + * names. + * + * For example, in the name of the unpack function above, the package name + * `foo.bar` has become `foo__bar`, the message name BazBah has become + * `baz_bah`, and the method name is `unpack`. These are all joined with double + * underscores to form the C identifier `foo__bar__baz_bah__unpack`. + * + * We also generate descriptor objects for messages and enums. These are + * declared in the `.pb-c.h` files: + * +~~~{.c} +extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor; +~~~ + * + * The message structures all begin with `ProtobufCMessageDescriptor *` which is + * sufficient to allow them to be cast to `ProtobufCMessage`. + * + * For each message defined in a `.proto` file, we generate a number of + * functions and macros. Each function name contains a prefix based on the + * package name and message name in order to make it a unique C identifier. + * + * - `INIT`. Statically initializes a message object, initializing its + * descriptor and setting its fields to default values. Uninitialized + * messages cannot be processed by the protobuf-c library. + * +~~~{.c} +#define FOO__BAR__BAZ_BAH__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&foo__bar__baz_bah__descriptor), 0 } +~~~ + * - `init()`. Initializes a message object, initializing its descriptor and + * setting its fields to default values. Uninitialized messages cannot be + * processed by the protobuf-c library. + * +~~~{.c} +void foo__bar__baz_bah__init + (Foo__Bar__BazBah *message); +~~~ + * - `unpack()`. Unpacks data for a particular message format. Note that the + * `allocator` parameter is usually `NULL` to indicate that the system's + * `malloc()` and `free()` functions should be used for dynamically allocating + * memory. + * +~~~{.c} +Foo__Bar__BazBah * + foo__bar__baz_bah__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +~~~ + * + * - `free_unpacked()`. Frees a message object obtained with the `unpack()` + * method. Freeing `NULL` is allowed (the same as with `free()`). + * +~~~{.c} +void foo__bar__baz_bah__free_unpacked + (Foo__Bar__BazBah *message, + ProtobufCAllocator *allocator); +~~~ + * + * - `get_packed_size()`. Calculates the length in bytes of the serialized + * representation of the message object. + * +~~~{.c} +size_t foo__bar__baz_bah__get_packed_size + (const Foo__Bar__BazBah *message); +~~~ + * + * - `pack()`. Pack a message object into a preallocated buffer. Assumes that + * the buffer is large enough. (Use `get_packed_size()` first.) + * +~~~{.c} +size_t foo__bar__baz_bah__pack + (const Foo__Bar__BazBah *message, + uint8_t *out); +~~~ + * + * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an + * object which defines an "append bytes" callback to consume data as it is + * serialized. + * +~~~{.c} +size_t foo__bar__baz_bah__pack_to_buffer + (const Foo__Bar__BazBah *message, + ProtobufCBuffer *buffer); +~~~ + * + * \page pack Packing and unpacking messages + * + * To pack a message, first compute the packed size of the message with + * protobuf_c_message_get_packed_size(), then allocate a buffer of at least + * that size, then call protobuf_c_message_pack(). + * + * Alternatively, a message can be serialized without calculating the final size + * first. Use the protobuf_c_message_pack_to_buffer() function and provide a + * ProtobufCBuffer object which implements an "append" method that consumes + * data. + * + * To unpack a message, call the protobuf_c_message_unpack() function. The + * result can be cast to an object of the type that matches the descriptor for + * the message. + * + * The result of unpacking a message should be freed with + * protobuf_c_message_free_unpacked(). + */ + +#ifndef PROTOBUF_C_H +#define PROTOBUF_C_H + +#include +#include +#include +#include + +#ifdef __cplusplus +# define PROTOBUF_C__BEGIN_DECLS extern "C" { +# define PROTOBUF_C__END_DECLS } +#else +# define PROTOBUF_C__BEGIN_DECLS +# define PROTOBUF_C__END_DECLS +#endif + +PROTOBUF_C__BEGIN_DECLS + +#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB) +# ifdef PROTOBUF_C_EXPORT +# define PROTOBUF_C__API __declspec(dllexport) +# else +# define PROTOBUF_C__API __declspec(dllimport) +# endif +#else +# define PROTOBUF_C__API +#endif + +#if !defined(PROTOBUF_C__NO_DEPRECATED) && \ + ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__)) +#else +# define PROTOBUF_C__DEPRECATED +#endif + +#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE + #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \ + , _##enum_name##_IS_INT_SIZE = INT_MAX +#endif + +#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3 +#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9 +#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af + +/* Empty string used for initializers */ +extern const char protobuf_c_empty_string[]; + +/** + * \defgroup api Public API + * + * This is the public API for `libprotobuf-c`. These interfaces are stable and + * subject to Semantic Versioning guarantees. + * + * @{ + */ + +/** + * Values for the `flags` word in `ProtobufCFieldDescriptor`. + */ +typedef enum { + /** Set if the field is repeated and marked with the `packed` option. */ + PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0), + + /** Set if the field is marked with the `deprecated` option. */ + PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1), + + /** Set if the field is a member of a oneof (union). */ + PROTOBUF_C_FIELD_FLAG_ONEOF = (1 << 2), +} ProtobufCFieldFlag; + +/** + * Message field rules. + * + * \see [Defining A Message Type] in the Protocol Buffers documentation. + * + * [Defining A Message Type]: + * https://developers.google.com/protocol-buffers/docs/proto#simple + */ +typedef enum { + /** A well-formed message must have exactly one of this field. */ + PROTOBUF_C_LABEL_REQUIRED, + + /** + * A well-formed message can have zero or one of this field (but not + * more than one). + */ + PROTOBUF_C_LABEL_OPTIONAL, + + /** + * This field can be repeated any number of times (including zero) in a + * well-formed message. The order of the repeated values will be + * preserved. + */ + PROTOBUF_C_LABEL_REPEATED, + + /** + * This field has no label. This is valid only in proto3 and is + * equivalent to OPTIONAL but no "has" quantifier will be consulted. + */ + PROTOBUF_C_LABEL_NONE, +} ProtobufCLabel; + +/** + * Field value types. + * + * \see [Scalar Value Types] in the Protocol Buffers documentation. + * + * [Scalar Value Types]: + * https://developers.google.com/protocol-buffers/docs/proto#scalar + */ +typedef enum { + PROTOBUF_C_TYPE_INT32, /**< int32 */ + PROTOBUF_C_TYPE_SINT32, /**< signed int32 */ + PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */ + PROTOBUF_C_TYPE_INT64, /**< int64 */ + PROTOBUF_C_TYPE_SINT64, /**< signed int64 */ + PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */ + PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */ + PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */ + PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */ + PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */ + PROTOBUF_C_TYPE_FLOAT, /**< float */ + PROTOBUF_C_TYPE_DOUBLE, /**< double */ + PROTOBUF_C_TYPE_BOOL, /**< boolean */ + PROTOBUF_C_TYPE_ENUM, /**< enumerated type */ + PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */ + PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */ + PROTOBUF_C_TYPE_MESSAGE, /**< nested message */ +} ProtobufCType; + +/** + * Field wire types. + * + * \see [Message Structure] in the Protocol Buffers documentation. + * + * [Message Structure]: + * https://developers.google.com/protocol-buffers/docs/encoding#structure + */ +typedef enum { + PROTOBUF_C_WIRE_TYPE_VARINT = 0, + PROTOBUF_C_WIRE_TYPE_64BIT = 1, + PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2, + /* "Start group" and "end group" wire types are unsupported. */ + PROTOBUF_C_WIRE_TYPE_32BIT = 5, +} ProtobufCWireType; + +struct ProtobufCAllocator; +struct ProtobufCBinaryData; +struct ProtobufCBuffer; +struct ProtobufCBufferSimple; +struct ProtobufCEnumDescriptor; +struct ProtobufCEnumValue; +struct ProtobufCEnumValueIndex; +struct ProtobufCFieldDescriptor; +struct ProtobufCIntRange; +struct ProtobufCMessage; +struct ProtobufCMessageDescriptor; +struct ProtobufCMessageUnknownField; +struct ProtobufCMethodDescriptor; +struct ProtobufCService; +struct ProtobufCServiceDescriptor; + +typedef struct ProtobufCAllocator ProtobufCAllocator; +typedef struct ProtobufCBinaryData ProtobufCBinaryData; +typedef struct ProtobufCBuffer ProtobufCBuffer; +typedef struct ProtobufCBufferSimple ProtobufCBufferSimple; +typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor; +typedef struct ProtobufCEnumValue ProtobufCEnumValue; +typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex; +typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor; +typedef struct ProtobufCIntRange ProtobufCIntRange; +typedef struct ProtobufCMessage ProtobufCMessage; +typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor; +typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField; +typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor; +typedef struct ProtobufCService ProtobufCService; +typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor; + +/** Boolean type. */ +typedef int protobuf_c_boolean; + +typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data); +typedef void (*ProtobufCMessageInit)(ProtobufCMessage *); +typedef void (*ProtobufCServiceDestroy)(ProtobufCService *); + +/** + * Structure for defining a custom memory allocator. + */ +struct ProtobufCAllocator { + /** Function to allocate memory. */ + void *(*alloc)(void *allocator_data, size_t size); + + /** Function to free memory. */ + void (*free)(void *allocator_data, void *pointer); + + /** Opaque pointer passed to `alloc` and `free` functions. */ + void *allocator_data; +}; + +/** + * Structure for the protobuf `bytes` scalar type. + * + * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of + * bytes. It may contain embedded `NUL` characters and is not required to be + * `NUL`-terminated. + */ +struct ProtobufCBinaryData { + size_t len; /**< Number of bytes in the `data` field. */ + uint8_t *data; /**< Data bytes. */ +}; + +/** + * Structure for defining a virtual append-only buffer. Used by + * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized + * bytes. + * + * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to + * write to a `FILE` object: + * +~~~{.c} +typedef struct { + ProtobufCBuffer base; + FILE *fp; +} BufferAppendToFile; + +static void +my_buffer_file_append(ProtobufCBuffer *buffer, + size_t len, + const uint8_t *data) +{ + BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer; + fwrite(data, len, 1, file_buf->fp); // XXX: No error handling! +} +~~~ + * + * To use this new type of ProtobufCBuffer, it could be called as follows: + * +~~~{.c} +... +BufferAppendToFile tmp = {0}; +tmp.base.append = my_buffer_file_append; +tmp.fp = fp; +protobuf_c_message_pack_to_buffer(&message, &tmp); +... +~~~ + */ +struct ProtobufCBuffer { + /** Append function. Consumes the `len` bytes stored at `data`. */ + void (*append)(ProtobufCBuffer *buffer, + size_t len, + const uint8_t *data); +}; + +/** + * Simple buffer "subclass" of `ProtobufCBuffer`. + * + * A `ProtobufCBufferSimple` object is declared on the stack and uses a + * scratch buffer provided by the user for the initial allocation. It performs + * exponential resizing, using dynamically allocated memory. A + * `ProtobufCBufferSimple` object can be created and used as follows: + * +~~~{.c} +uint8_t pad[128]; +ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad); +ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple; +~~~ + * + * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a + * message has been serialized to a `ProtobufCBufferSimple` object, the + * serialized data bytes can be accessed from the `.data` field. + * + * To free the memory allocated by a `ProtobufCBufferSimple` object, if any, + * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example: + * +~~~{.c} +PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple); +~~~ + * + * \see PROTOBUF_C_BUFFER_SIMPLE_INIT + * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR + */ +struct ProtobufCBufferSimple { + /** "Base class". */ + ProtobufCBuffer base; + /** Number of bytes allocated in `data`. */ + size_t alloced; + /** Number of bytes currently stored in `data`. */ + size_t len; + /** Data bytes. */ + uint8_t *data; + /** Whether `data` must be freed. */ + protobuf_c_boolean must_free_data; + /** Allocator to use. May be NULL to indicate the system allocator. */ + ProtobufCAllocator *allocator; +}; + +/** + * Describes an enumeration as a whole, with all of its values. + */ +struct ProtobufCEnumDescriptor { + /** Magic value checked to ensure that the API is used correctly. */ + uint32_t magic; + + /** The qualified name (e.g., "namespace.Type"). */ + const char *name; + /** The unqualified name as given in the .proto file (e.g., "Type"). */ + const char *short_name; + /** Identifier used in generated C code. */ + const char *c_name; + /** The dot-separated namespace. */ + const char *package_name; + + /** Number elements in `values`. */ + unsigned n_values; + /** Array of distinct values, sorted by numeric value. */ + const ProtobufCEnumValue *values; + + /** Number of elements in `values_by_name`. */ + unsigned n_value_names; + /** Array of named values, including aliases, sorted by name. */ + const ProtobufCEnumValueIndex *values_by_name; + + /** Number of elements in `value_ranges`. */ + unsigned n_value_ranges; + /** Value ranges, for faster lookups by numeric value. */ + const ProtobufCIntRange *value_ranges; + + /** Reserved for future use. */ + void *reserved1; + /** Reserved for future use. */ + void *reserved2; + /** Reserved for future use. */ + void *reserved3; + /** Reserved for future use. */ + void *reserved4; +}; + +/** + * Represents a single value of an enumeration. + */ +struct ProtobufCEnumValue { + /** The string identifying this value in the .proto file. */ + const char *name; + + /** The string identifying this value in generated C code. */ + const char *c_name; + + /** The numeric value assigned in the .proto file. */ + int value; +}; + +/** + * Used by `ProtobufCEnumDescriptor` to look up enum values. + */ +struct ProtobufCEnumValueIndex { + /** Name of the enum value. */ + const char *name; + /** Index into values[] array. */ + unsigned index; +}; + +/** + * Describes a single field in a message. + */ +struct ProtobufCFieldDescriptor { + /** Name of the field as given in the .proto file. */ + const char *name; + + /** Tag value of the field as given in the .proto file. */ + uint32_t id; + + /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */ + ProtobufCLabel label; + + /** The type of the field. */ + ProtobufCType type; + + /** + * The offset in bytes of the message's C structure's quantifier field + * (the `has_MEMBER` field for optional members or the `n_MEMBER` field + * for repeated members or the case enum for oneofs). + */ + unsigned quantifier_offset; + + /** + * The offset in bytes into the message's C structure for the member + * itself. + */ + unsigned offset; + + /** + * A type-specific descriptor. + * + * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the + * corresponding `ProtobufCEnumDescriptor`. + * + * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to + * the corresponding `ProtobufCMessageDescriptor`. + * + * Otherwise this field is NULL. + */ + const void *descriptor; /* for MESSAGE and ENUM types */ + + /** The default value for this field, if defined. May be NULL. */ + const void *default_value; + + /** + * A flag word. Zero or more of the bits defined in the + * `ProtobufCFieldFlag` enum may be set. + */ + uint32_t flags; + + /** Reserved for future use. */ + unsigned reserved_flags; + /** Reserved for future use. */ + void *reserved2; + /** Reserved for future use. */ + void *reserved3; +}; + +/** + * Helper structure for optimizing int => index lookups in the case + * where the keys are mostly consecutive values, as they presumably are for + * enums and fields. + * + * The data structures requires that the values in the original array are + * sorted. + */ +struct ProtobufCIntRange { + int start_value; + unsigned orig_index; + /* + * NOTE: the number of values in the range can be inferred by looking + * at the next element's orig_index. A dummy element is added to make + * this simple. + */ +}; + +/** + * An instance of a message. + * + * `ProtobufCMessage` is a light-weight "base class" for all messages. + * + * In particular, `ProtobufCMessage` doesn't have any allocation policy + * associated with it. That's because it's common to create `ProtobufCMessage` + * objects on the stack. In fact, that's what we recommend for sending messages. + * If the object is allocated from the stack, you can't really have a memory + * leak. + * + * This means that calls to functions like protobuf_c_message_unpack() which + * return a `ProtobufCMessage` must be paired with a call to a free function, + * like protobuf_c_message_free_unpacked(). + */ +struct ProtobufCMessage { + /** The descriptor for this message type. */ + const ProtobufCMessageDescriptor *descriptor; + /** The number of elements in `unknown_fields`. */ + unsigned n_unknown_fields; + /** The fields that weren't recognized by the parser. */ + ProtobufCMessageUnknownField *unknown_fields; +}; + +/** + * Describes a message. + */ +struct ProtobufCMessageDescriptor { + /** Magic value checked to ensure that the API is used correctly. */ + uint32_t magic; + + /** The qualified name (e.g., "namespace.Type"). */ + const char *name; + /** The unqualified name as given in the .proto file (e.g., "Type"). */ + const char *short_name; + /** Identifier used in generated C code. */ + const char *c_name; + /** The dot-separated namespace. */ + const char *package_name; + + /** + * Size in bytes of the C structure representing an instance of this + * type of message. + */ + size_t sizeof_message; + + /** Number of elements in `fields`. */ + unsigned n_fields; + /** Field descriptors, sorted by tag number. */ + const ProtobufCFieldDescriptor *fields; + /** Used for looking up fields by name. */ + const unsigned *fields_sorted_by_name; + + /** Number of elements in `field_ranges`. */ + unsigned n_field_ranges; + /** Used for looking up fields by id. */ + const ProtobufCIntRange *field_ranges; + + /** Message initialisation function. */ + ProtobufCMessageInit message_init; + + /** Reserved for future use. */ + void *reserved1; + /** Reserved for future use. */ + void *reserved2; + /** Reserved for future use. */ + void *reserved3; +}; + +/** + * An unknown message field. + */ +struct ProtobufCMessageUnknownField { + /** The tag number. */ + uint32_t tag; + /** The wire type of the field. */ + ProtobufCWireType wire_type; + /** Number of bytes in `data`. */ + size_t len; + /** Field data. */ + uint8_t *data; +}; + +/** + * Method descriptor. + */ +struct ProtobufCMethodDescriptor { + /** Method name. */ + const char *name; + /** Input message descriptor. */ + const ProtobufCMessageDescriptor *input; + /** Output message descriptor. */ + const ProtobufCMessageDescriptor *output; +}; + +/** + * Service. + */ +struct ProtobufCService { + /** Service descriptor. */ + const ProtobufCServiceDescriptor *descriptor; + /** Function to invoke the service. */ + void (*invoke)(ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); + /** Function to destroy the service. */ + void (*destroy)(ProtobufCService *service); +}; + +/** + * Service descriptor. + */ +struct ProtobufCServiceDescriptor { + /** Magic value checked to ensure that the API is used correctly. */ + uint32_t magic; + + /** Service name. */ + const char *name; + /** Short version of service name. */ + const char *short_name; + /** C identifier for the service name. */ + const char *c_name; + /** Package name. */ + const char *package; + /** Number of elements in `methods`. */ + unsigned n_methods; + /** Method descriptors, in the order defined in the .proto file. */ + const ProtobufCMethodDescriptor *methods; + /** Sort index of methods. */ + const unsigned *method_indices_by_name; +}; + +/** + * Get the version of the protobuf-c library. Note that this is the version of + * the library linked against, not the version of the headers compiled against. + * + * \return A string containing the version number of protobuf-c. + */ +PROTOBUF_C__API +const char * +protobuf_c_version(void); + +/** + * Get the version of the protobuf-c library. Note that this is the version of + * the library linked against, not the version of the headers compiled against. + * + * \return A 32 bit unsigned integer containing the version number of + * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH. + */ +PROTOBUF_C__API +uint32_t +protobuf_c_version_number(void); + +/** + * The version of the protobuf-c headers, represented as a string using the same + * format as protobuf_c_version(). + */ +#define PROTOBUF_C_VERSION "1.3.0" + +/** + * The version of the protobuf-c headers, represented as an integer using the + * same format as protobuf_c_version_number(). + */ +#define PROTOBUF_C_VERSION_NUMBER 1003000 + +/** + * The minimum protoc-c version which works with the current version of the + * protobuf-c headers. + */ +#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000 + +/** + * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name. + * + * \param desc + * The `ProtobufCEnumDescriptor` object. + * \param name + * The `name` field from the corresponding `ProtobufCEnumValue` object to + * match. + * \return + * A `ProtobufCEnumValue` object. + * \retval NULL + * If not found or if the optimize_for = CODE_SIZE option was set. + */ +PROTOBUF_C__API +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value_by_name( + const ProtobufCEnumDescriptor *desc, + const char *name); + +/** + * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric + * value. + * + * \param desc + * The `ProtobufCEnumDescriptor` object. + * \param value + * The `value` field from the corresponding `ProtobufCEnumValue` object to + * match. + * + * \return + * A `ProtobufCEnumValue` object. + * \retval NULL + * If not found. + */ +PROTOBUF_C__API +const ProtobufCEnumValue * +protobuf_c_enum_descriptor_get_value( + const ProtobufCEnumDescriptor *desc, + int value); + +/** + * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by + * the name of the field. + * + * \param desc + * The `ProtobufCMessageDescriptor` object. + * \param name + * The name of the field. + * \return + * A `ProtobufCFieldDescriptor` object. + * \retval NULL + * If not found or if the optimize_for = CODE_SIZE option was set. + */ +PROTOBUF_C__API +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field_by_name( + const ProtobufCMessageDescriptor *desc, + const char *name); + +/** + * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by + * the tag value of the field. + * + * \param desc + * The `ProtobufCMessageDescriptor` object. + * \param value + * The tag value of the field. + * \return + * A `ProtobufCFieldDescriptor` object. + * \retval NULL + * If not found. + */ +PROTOBUF_C__API +const ProtobufCFieldDescriptor * +protobuf_c_message_descriptor_get_field( + const ProtobufCMessageDescriptor *desc, + unsigned value); + +/** + * Determine the number of bytes required to store the serialised message. + * + * \param message + * The message object to serialise. + * \return + * Number of bytes. + */ +PROTOBUF_C__API +size_t +protobuf_c_message_get_packed_size(const ProtobufCMessage *message); + +/** + * Serialise a message from its in-memory representation. + * + * This function stores the serialised bytes of the message in a pre-allocated + * buffer. + * + * \param message + * The message object to serialise. + * \param[out] out + * Buffer to store the bytes of the serialised message. This buffer must + * have enough space to store the packed message. Use + * protobuf_c_message_get_packed_size() to determine the number of bytes + * required. + * \return + * Number of bytes stored in `out`. + */ +PROTOBUF_C__API +size_t +protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out); + +/** + * Serialise a message from its in-memory representation to a virtual buffer. + * + * This function calls the `append` method of a `ProtobufCBuffer` object to + * consume the bytes generated by the serialiser. + * + * \param message + * The message object to serialise. + * \param buffer + * The virtual buffer object. + * \return + * Number of bytes passed to the virtual buffer. + */ +PROTOBUF_C__API +size_t +protobuf_c_message_pack_to_buffer( + const ProtobufCMessage *message, + ProtobufCBuffer *buffer); + +/** + * Unpack a serialised message into an in-memory representation. + * + * \param descriptor + * The message descriptor. + * \param allocator + * `ProtobufCAllocator` to use for memory allocation. May be NULL to + * specify the default allocator. + * \param len + * Length in bytes of the serialised message. + * \param data + * Pointer to the serialised message. + * \return + * An unpacked message object. + * \retval NULL + * If an error occurred during unpacking. + */ +PROTOBUF_C__API +ProtobufCMessage * +protobuf_c_message_unpack( + const ProtobufCMessageDescriptor *descriptor, + ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); + +/** + * Free an unpacked message object. + * + * This function should be used to deallocate the memory used by a call to + * protobuf_c_message_unpack(). + * + * \param message + * The message object to free. May be NULL. + * \param allocator + * `ProtobufCAllocator` to use for memory deallocation. May be NULL to + * specify the default allocator. + */ +PROTOBUF_C__API +void +protobuf_c_message_free_unpacked( + ProtobufCMessage *message, + ProtobufCAllocator *allocator); + +/** + * Check the validity of a message object. + * + * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present. + * Recursively checks nested messages. + * + * \retval TRUE + * Message is valid. + * \retval FALSE + * Message is invalid. + */ +PROTOBUF_C__API +protobuf_c_boolean +protobuf_c_message_check(const ProtobufCMessage *); + +/** Message initialiser. */ +#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL } + +/** + * Initialise a message object from a message descriptor. + * + * \param descriptor + * Message descriptor. + * \param message + * Allocated block of memory of size `descriptor->sizeof_message`. + */ +PROTOBUF_C__API +void +protobuf_c_message_init( + const ProtobufCMessageDescriptor *descriptor, + void *message); + +/** + * Free a service. + * + * \param service + * The service object to free. + */ +PROTOBUF_C__API +void +protobuf_c_service_destroy(ProtobufCService *service); + +/** + * Look up a `ProtobufCMethodDescriptor` by name. + * + * \param desc + * Service descriptor. + * \param name + * Name of the method. + * + * \return + * A `ProtobufCMethodDescriptor` object. + * \retval NULL + * If not found or if the optimize_for = CODE_SIZE option was set. + */ +PROTOBUF_C__API +const ProtobufCMethodDescriptor * +protobuf_c_service_descriptor_get_method_by_name( + const ProtobufCServiceDescriptor *desc, + const char *name); + +/** + * Initialise a `ProtobufCBufferSimple` object. + */ +#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \ +{ \ + { protobuf_c_buffer_simple_append }, \ + sizeof(array_of_bytes), \ + 0, \ + (array_of_bytes), \ + 0, \ + NULL \ +} + +/** + * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory. + */ +#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \ +do { \ + if ((simp_buf)->must_free_data) { \ + if ((simp_buf)->allocator != NULL) \ + (simp_buf)->allocator->free( \ + (simp_buf)->allocator, \ + (simp_buf)->data); \ + else \ + free((simp_buf)->data); \ + } \ +} while (0) + +/** + * The `append` method for `ProtobufCBufferSimple`. + * + * \param buffer + * The buffer object to append to. Must actually be a + * `ProtobufCBufferSimple` object. + * \param len + * Number of bytes in `data`. + * \param data + * Data to append. + */ +PROTOBUF_C__API +void +protobuf_c_buffer_simple_append( + ProtobufCBuffer *buffer, + size_t len, + const unsigned char *data); + +PROTOBUF_C__API +void +protobuf_c_service_generated_init( + ProtobufCService *service, + const ProtobufCServiceDescriptor *descriptor, + ProtobufCServiceDestroy destroy); + +PROTOBUF_C__API +void +protobuf_c_service_invoke_internal( + ProtobufCService *service, + unsigned method_index, + const ProtobufCMessage *input, + ProtobufCClosure closure, + void *closure_data); + +/**@}*/ + +PROTOBUF_C__END_DECLS + +#endif /* PROTOBUF_C_H */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/targetver.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/targetver.h new file mode 100644 index 000000000..87c0086de --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v6/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs index 9c2c957ab..0882d43e0 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs @@ -227,8 +227,9 @@ namespace Tango.MachineStudio.RML.ViewModels //input.DeltaChroma = DeltaChroma; //input.DeltaL = DeltaL; input.ForwardData = ByteString.CopyFrom(CCT.Data); - input.GbdData = ByteString.CopyFrom(GBD.Data); - input.LubData = ByteString.CopyFrom(LUB.Data); + + if (GBD != null) input.GbdData = ByteString.CopyFrom(GBD.Data); + if (LUB != null) input.LubData = ByteString.CopyFrom(LUB.Data); input.InputCoordinates = new InputCoordinates(); input.InputCoordinates.Red = (int)SourceColor.Red; @@ -372,8 +373,8 @@ namespace Tango.MachineStudio.RML.ViewModels ConversionInput input = new ConversionInput(); input.ColorSpace = PMR.ColorLab.ColorSpace.Volume; input.ForwardData = ByteString.CopyFrom(CCT.Data); - input.GbdData = ByteString.CopyFrom(GBD.Data); - input.LubData = ByteString.CopyFrom(LUB.Data); + if (GBD != null) input.GbdData = ByteString.CopyFrom(GBD.Data); + if (LUB != null) input.LubData = ByteString.CopyFrom(LUB.Data); input.GenerateHive = false; input.InputCoordinates = new InputCoordinates(); diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs index bb6a3c467..6da1cf64b 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs @@ -444,23 +444,7 @@ namespace Tango.MachineStudio.RML.ViewModels .WithSpools() .BuildAsync(); - if (ActiveRML.Cct != null) - { - _selectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid); - RaisePropertyChanged(nameof(SelectedCCT)); - } - - if (ActiveRML.Gbd != null) - { - _selectedGBD = GBDS.SingleOrDefault(x => x.Guid == ActiveRML.Gbd.Guid); - RaisePropertyChanged(nameof(SelectedGBD)); - } - - if (ActiveRML.Lub != null) - { - _selectedLUB = LUBS.SingleOrDefault(x => x.Guid == ActiveRML.Lub.Guid); - RaisePropertyChanged(nameof(SelectedLUB)); - } + InvalidateRelayCommands(); if (ActiveRML.ProcessParametersTablesGroups.ToList().Count == 0) { @@ -526,6 +510,27 @@ namespace Tango.MachineStudio.RML.ViewModels LiquidTypesRmls = LiquidTypesRmls, }; + if (ActiveRML.Cct != null) + { + _selectedCCT = CCTS.SingleOrDefault(x => x.Guid == ActiveRML.Cct.Guid); + await OnSelectedCCTChanged(); + RaisePropertyChanged(nameof(SelectedCCT)); + } + + if (ActiveRML.Gbd != null) + { + _selectedGBD = GBDS.SingleOrDefault(x => x.Guid == ActiveRML.Gbd.Guid); + await OnSelectedGBDChanged(); + RaisePropertyChanged(nameof(SelectedGBD)); + } + + if (ActiveRML.Lub != null) + { + _selectedLUB = LUBS.SingleOrDefault(x => x.Guid == ActiveRML.Lub.Guid); + await OnSelectedLUBChanged(); + RaisePropertyChanged(nameof(SelectedLUB)); + } + ColorCalibrationVM = new ColorCalibrationViewVM(_notification) { RML = ActiveRML, @@ -554,7 +559,7 @@ namespace Tango.MachineStudio.RML.ViewModels private async Task OnSelectedCCTChanged() { - if (SelectedCCT != null && !SelectedCCT.IsNew) + if (ColorConversionViewVM != null && SelectedCCT != null && !SelectedCCT.IsNew) { using (_notification.PushTaskItem("Loading CCT data...")) { @@ -575,7 +580,7 @@ namespace Tango.MachineStudio.RML.ViewModels private async Task OnSelectedGBDChanged() { - if (SelectedGBD != null && !SelectedGBD.IsNew) + if (ColorConversionViewVM != null && SelectedGBD != null && !SelectedGBD.IsNew) { using (_notification.PushTaskItem("Loading GBD data...")) { @@ -596,7 +601,7 @@ namespace Tango.MachineStudio.RML.ViewModels private async Task OnSelectedLUBChanged() { - if (SelectedLUB != null && !SelectedLUB.IsNew) + if (ColorConversionViewVM != null && SelectedLUB != null && !SelectedLUB.IsNew) { using (_notification.PushTaskItem("Loading LUB data...")) { diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml index e2ef8b229..7e3b4fa4a 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml @@ -263,7 +263,7 @@ - + Enable Gradient Generation Use Light Inks diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index ac52d55c5..eca12dfef 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -544,6 +544,13 @@ Tango.MachineStudio.Common + + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059} + Tango.ColorLib_v6 + false + Content + PreserveNewest + {0F87D32E-B65F-4AE8-862C-29F4CCC38240} Tango.ColorLib_v5 diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj index bb37dbea2..288c8a328 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj @@ -630,6 +630,13 @@ Tango.PPC.Shared + + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059} + Tango.ColorLib_v6 + false + Content + PreserveNewest + {0F87D32E-B65F-4AE8-862C-29F4CCC38240} Tango.ColorLib_v5 diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 2278bb67b..ef4e3dc1d 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -481,6 +481,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.PDF", "Tango.PDF\Tang EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.BulkEmailModifier.CLI", "Utilities\Tango.BulkEmailModifier.CLI\Tango.BulkEmailModifier.CLI.csproj", "{DA4FCA0B-E0EA-431F-B0CC-AA9B0A4C73C2}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tango.ColorLib_v6", "ColorLib\Tango.ColorLib_v6\Tango.ColorLib_v6.vcxproj", "{D74E49AA-4C6B-4427-BEFF-D7CE2690D059}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -4592,6 +4594,20 @@ Global {DA4FCA0B-E0EA-431F-B0CC-AA9B0A4C73C2}.Release|x64.Build.0 = Release|Any CPU {DA4FCA0B-E0EA-431F-B0CC-AA9B0A4C73C2}.Release|x86.ActiveCfg = Release|Any CPU {DA4FCA0B-E0EA-431F-B0CC-AA9B0A4C73C2}.Release|x86.Build.0 = Release|Any CPU + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|ARM.ActiveCfg = Debug|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|ARM64.ActiveCfg = Debug|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|x64.ActiveCfg = Debug|x64 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|x64.Build.0 = Debug|x64 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|x86.ActiveCfg = Debug|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Debug|x86.Build.0 = Debug|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|Any CPU.ActiveCfg = Release|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|ARM.ActiveCfg = Release|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|ARM64.ActiveCfg = Release|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|x64.ActiveCfg = Release|x64 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|x64.Build.0 = Release|x64 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|x86.ActiveCfg = Release|Win32 + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4763,14 +4779,15 @@ Global {DBBD90F4-4135-475D-A8F8-6795D3A8F697} = {0048447D-1D94-4E60-9DAD-7349C777CB4E} {0F87D32E-B65F-4AE8-862C-29F4CCC38240} = {7181F9DE-0760-46B7-AD8F-BDBCAEDEF1B7} {DA4FCA0B-E0EA-431F-B0CC-AA9B0A4C73C2} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} + {D74E49AA-4C6B-4427-BEFF-D7CE2690D059} = {7181F9DE-0760-46B7-AD8F-BDBCAEDEF1B7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} - BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear - BuildVersion_UpdateAssemblyVersion = True - BuildVersion_UpdateFileVersion = False - BuildVersion_StartDate = 2000/1/1 - BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs BuildVersion_UseGlobalSettings = False + BuildVersion_AssemblyInfoFilename = Properties\AssemblyInfo.cs + BuildVersion_StartDate = 2000/1/1 + BuildVersion_UpdateFileVersion = False + BuildVersion_UpdateAssemblyVersion = True + BuildVersion_BuildVersioningStyle = None.None.Increment.DeltaBaseYearDayOfYear + SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} EndGlobalSection EndGlobal -- cgit v1.3.1 From a476559758ceb3700d9bf80911a3b1e87ac5cbf8 Mon Sep 17 00:00:00 2001 From: Roy Date: Mon, 3 Oct 2022 15:27:16 +0300 Subject: Use Lubricant Transform --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../PMR/Messages/ColorLab/ConversionInput.proto | 1 + .../ColorLab/GradientConversionInput.proto | 1 + .../PMR/Messages/ColorLab/OutOfGamutInput.proto | 1 + .../ColorLab/RecommendedProcessTableInput.proto | 1 + .../ViewModels/ColorConversionViewVM.cs | 2 + .../Tango.MachineStudio.RML/Views/RmlView.xaml | 1 + Software/Visual_Studio/Tango.BL/DTO/RmlDTOBase.cs | 8 + .../Visual_Studio/Tango.BL/Entities/RmlBase.cs | 38 +++++ .../Tango.ColorConversion/DefaultColorConverter.cs | 8 + Software/Visual_Studio/Tango.DAL.Remote/DB/RML.cs | 1 + .../Tango.DAL.Remote/DB/RemoteADO.edmx | 3 + .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 178 ++++++++++----------- .../Tango.PMR/ColorLab/ConversionInput.cs | 35 +++- .../Tango.PMR/ColorLab/GradientConversionInput.cs | 37 ++++- .../Tango.PMR/ColorLab/OutOfGamutInput.cs | 37 ++++- .../ColorLab/RecommendedProcessTableInput.cs | 37 ++++- .../SQLExaminer/Configurations/OverrideData.xml | Bin 93812 -> 93918 bytes 21 files changed, 285 insertions(+), 104 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Modules') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index da3b017a9..01bb09c73 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 7ce53cd7f..eec900a58 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index de4c86e73..a2d27bdd5 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index aa5856542..f4d1f3f36 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/PMR/Messages/ColorLab/ConversionInput.proto b/Software/PMR/Messages/ColorLab/ConversionInput.proto index e0515f16f..069abd7df 100644 --- a/Software/PMR/Messages/ColorLab/ConversionInput.proto +++ b/Software/PMR/Messages/ColorLab/ConversionInput.proto @@ -25,4 +25,5 @@ message ConversionInput double VMax = 14; bytes GbdData = 15; bytes LubData = 16; + bool UseLubricantTransform = 17; } \ No newline at end of file diff --git a/Software/PMR/Messages/ColorLab/GradientConversionInput.proto b/Software/PMR/Messages/ColorLab/GradientConversionInput.proto index b8e1c162f..5e544fefb 100644 --- a/Software/PMR/Messages/ColorLab/GradientConversionInput.proto +++ b/Software/PMR/Messages/ColorLab/GradientConversionInput.proto @@ -19,4 +19,5 @@ message GradientConversionInput repeated ProcessRange ProcessRanges = 8; bytes GbdData = 9; bytes LubData = 10; + bool UseLubricantTransform = 11; } \ No newline at end of file diff --git a/Software/PMR/Messages/ColorLab/OutOfGamutInput.proto b/Software/PMR/Messages/ColorLab/OutOfGamutInput.proto index dbb442dad..1b361a180 100644 --- a/Software/PMR/Messages/ColorLab/OutOfGamutInput.proto +++ b/Software/PMR/Messages/ColorLab/OutOfGamutInput.proto @@ -18,4 +18,5 @@ message OutOfGamutInput repeated ProcessRange ProcessRanges = 7; bytes GbdData = 8; bytes LubData = 9; + bool UseLubricantTransform = 10; } \ No newline at end of file diff --git a/Software/PMR/Messages/ColorLab/RecommendedProcessTableInput.proto b/Software/PMR/Messages/ColorLab/RecommendedProcessTableInput.proto index f4a03644d..62ddc1f07 100644 --- a/Software/PMR/Messages/ColorLab/RecommendedProcessTableInput.proto +++ b/Software/PMR/Messages/ColorLab/RecommendedProcessTableInput.proto @@ -19,4 +19,5 @@ message RecommendedProcessTableInput bool UseLightInks = 8; bytes GbdData = 9; bytes LubData = 10; + bool UseLubricantTransform = 11; } \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs index 0882d43e0..ca3c3e322 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/ColorConversionViewVM.cs @@ -245,6 +245,7 @@ namespace Tango.MachineStudio.RML.ViewModels input.ThreadB = RML.WhitePointB; input.UseLightInks = RML.UseLightInks; + input.UseLubricantTransform = RML.UseLubricantTransform; input.VMax = RML.VMax; //Validate calibration data @@ -383,6 +384,7 @@ namespace Tango.MachineStudio.RML.ViewModels input.ThreadB = RML.WhitePointB; input.UseLightInks = RML.UseLightInks; + input.UseLubricantTransform = RML.UseLubricantTransform; input.VMax = RML.VMax; foreach (var vm in LiquidsCalibrationData.Where(x => x.LiquidType.HasPigment)) diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml index 7e3b4fa4a..08af47ef4 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml @@ -267,6 +267,7 @@ Enable Gradient Generation Use Light Inks + Use Lubricant Transform diff --git a/Software/Visual_Studio/Tango.BL/DTO/RmlDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/RmlDTOBase.cs index be6c9486f..e3b9f676c 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/RmlDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/RmlDTOBase.cs @@ -269,6 +269,14 @@ namespace Tango.BL.DTO get; set; } + /// + /// use lubricant transform + /// + public Boolean UseLubricantTransform + { + get; set; + } + /// /// head type /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/RmlBase.cs b/Software/Visual_Studio/Tango.BL/Entities/RmlBase.cs index 5aac56248..17b29d691 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/RmlBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/RmlBase.cs @@ -71,6 +71,8 @@ namespace Tango.BL.Entities public event EventHandler UseLightInksChanged; + public event EventHandler UseLubricantTransformChanged; + public event EventHandler HeadTypeChanged; public event EventHandler QualificationLevelChanged; @@ -973,6 +975,33 @@ namespace Tango.BL.Entities } } + protected Boolean _uselubricanttransform; + + /// + /// Gets or sets the rmlbase use lubricant transform. + /// + + [Column("USE_LUBRICANT_TRANSFORM")] + + public Boolean UseLubricantTransform + { + get + { + return _uselubricanttransform; + } + + set + { + if (_uselubricanttransform != value) + { + _uselubricanttransform = value; + + OnUseLubricantTransformChanged(value); + + } + } + } + protected Int32 _headtype; /// @@ -2261,6 +2290,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(UseLightInks)); } + /// + /// Called when the UseLubricantTransform has changed. + /// + protected virtual void OnUseLubricantTransformChanged(Boolean uselubricanttransform) + { + UseLubricantTransformChanged?.Invoke(this, uselubricanttransform); + RaisePropertyChanged(nameof(UseLubricantTransform)); + } + /// /// Called when the HeadType has changed. /// diff --git a/Software/Visual_Studio/Tango.ColorConversion/DefaultColorConverter.cs b/Software/Visual_Studio/Tango.ColorConversion/DefaultColorConverter.cs index cdb00a3ee..20e17bcc6 100644 --- a/Software/Visual_Studio/Tango.ColorConversion/DefaultColorConverter.cs +++ b/Software/Visual_Studio/Tango.ColorConversion/DefaultColorConverter.cs @@ -149,6 +149,8 @@ namespace Tango.ColorConversion conversionInput.UseLightInks = rml.UseLightInks && lightInksInstalled && useLightInks && settings.UseLightInks; + conversionInput.UseLubricantTransform = rml.UseLubricantTransform; + conversionInput.VMax = rml.VMax; conversionInput.ForwardData = ByteString.CopyFrom(rml.Cct.Data); @@ -337,6 +339,8 @@ namespace Tango.ColorConversion input.ThreadA = rml.WhitePointA; input.ThreadB = rml.WhitePointB; + input.UseLubricantTransform = rml.UseLubricantTransform; + input.InputCoordinates = new InputCoordinates(); if (stop.BrushColorSpace == ColorSpaces.RGB) @@ -553,6 +557,8 @@ namespace Tango.ColorConversion var settings = SettingsManager.Default.GetOrCreate(); input.UseLightInks = settings.UseLightInks && rml.UseLightInks && machine.LightInksInstalled && useLightInks; + input.UseLubricantTransform = rml.UseLubricantTransform; + //TODO: Do we need input.Vmax ?? (Mirta) foreach (var prTable in rml.GetActiveProcessGroup().ProcessParametersTables) @@ -802,6 +808,8 @@ namespace Tango.ColorConversion conversionInput.LubData = ByteString.CopyFrom(rml.Lub.Data); } + conversionInput.UseLubricantTransform = rml.UseLubricantTransform; + conversionInput.ThreadL = rml.WhitePointL; conversionInput.ThreadA = rml.WhitePointA; conversionInput.ThreadB = rml.WhitePointB; diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RML.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/RML.cs index 5488e8c54..b1f71c687 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RML.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RML.cs @@ -61,6 +61,7 @@ namespace Tango.DAL.Remote.DB public int COLOR_CONVERSION_VERSION { get; set; } public bool USE_COLOR_LIB_GRADIENTS { get; set; } public bool USE_LIGHT_INKS { get; set; } + public bool USE_LUBRICANT_TRANSFORM { get; set; } public int HEAD_TYPE { get; set; } public int QUALIFICATION_LEVEL { get; set; } public Nullable QUALIFICATION_DATE { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx index d52f40cab..dc068684b 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx @@ -1309,6 +1309,7 @@ + @@ -6823,6 +6824,7 @@ + @@ -10214,6 +10216,7 @@ + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram index f48276400..5beb4e96f 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram @@ -5,102 +5,102 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + diff --git a/Software/Visual_Studio/Tango.PMR/ColorLab/ConversionInput.cs b/Software/Visual_Studio/Tango.PMR/ColorLab/ConversionInput.cs index 592297ca0..a1f1538d3 100644 --- a/Software/Visual_Studio/Tango.PMR/ColorLab/ConversionInput.cs +++ b/Software/Visual_Studio/Tango.PMR/ColorLab/ConversionInput.cs @@ -24,7 +24,7 @@ namespace Tango.PMR.ColorLab { string.Concat( "ChVDb252ZXJzaW9uSW5wdXQucHJvdG8SElRhbmdvLlBNUi5Db2xvckxhYhoW", "SW5wdXRDb29yZGluYXRlcy5wcm90bxoQQ29sb3JTcGFjZS5wcm90bxoSUHJv", - "Y2Vzc1JhbmdlLnByb3RvIrMDCg9Db252ZXJzaW9uSW5wdXQSDwoHVGhyZWFk", + "Y2Vzc1JhbmdlLnByb3RvItIDCg9Db252ZXJzaW9uSW5wdXQSDwoHVGhyZWFk", "TBgBIAEoARIPCgdUaHJlYWRBGAIgASgBEg8KB1RocmVhZEIYAyABKAESMgoK", "Q29sb3JTcGFjZRgEIAEoDjIeLlRhbmdvLlBNUi5Db2xvckxhYi5Db2xvclNw", "YWNlEj4KEElucHV0Q29vcmRpbmF0ZXMYBSABKAsyJC5UYW5nby5QTVIuQ29s", @@ -34,11 +34,12 @@ namespace Tango.PMR.ColorLab { "UmFuZ2VzGAsgAygLMiAuVGFuZ28uUE1SLkNvbG9yTGFiLlByb2Nlc3NSYW5n", "ZRIUCgxHZW5lcmF0ZUhpdmUYDCABKAgSFAoMVXNlTGlnaHRJbmtzGA0gASgI", "EgwKBFZNYXgYDiABKAESDwoHR2JkRGF0YRgPIAEoDBIPCgdMdWJEYXRhGBAg", - "ASgMQh4KHGNvbS50d2luZS50YW5nby5wbXIuY29sb3JsYWJiBnByb3RvMw==")); + "ASgMEh0KFVVzZUx1YnJpY2FudFRyYW5zZm9ybRgRIAEoCEIeChxjb20udHdp", + "bmUudGFuZ28ucG1yLmNvbG9ybGFiYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Tango.PMR.ColorLab.InputCoordinatesReflection.Descriptor, global::Tango.PMR.ColorLab.ColorSpaceReflection.Descriptor, global::Tango.PMR.ColorLab.ProcessRangeReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.ConversionInput), global::Tango.PMR.ColorLab.ConversionInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ColorSpace", "InputCoordinates", "ForwardData", "InverseData", "SegmentLength", "DeltaChroma", "DeltaL", "ProcessRanges", "GenerateHive", "UseLightInks", "VMax", "GbdData", "LubData" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.ConversionInput), global::Tango.PMR.ColorLab.ConversionInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ColorSpace", "InputCoordinates", "ForwardData", "InverseData", "SegmentLength", "DeltaChroma", "DeltaL", "ProcessRanges", "GenerateHive", "UseLightInks", "VMax", "GbdData", "LubData", "UseLubricantTransform" }, null, null, null) })); } #endregion @@ -85,6 +86,7 @@ namespace Tango.PMR.ColorLab { vMax_ = other.vMax_; gbdData_ = other.gbdData_; lubData_ = other.lubData_; + useLubricantTransform_ = other.useLubricantTransform_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -267,6 +269,17 @@ namespace Tango.PMR.ColorLab { } } + /// Field number for the "UseLubricantTransform" field. + public const int UseLubricantTransformFieldNumber = 17; + private bool useLubricantTransform_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool UseLubricantTransform { + get { return useLubricantTransform_; } + set { + useLubricantTransform_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as ConversionInput); @@ -296,6 +309,7 @@ namespace Tango.PMR.ColorLab { if (VMax != other.VMax) return false; if (GbdData != other.GbdData) return false; if (LubData != other.LubData) return false; + if (UseLubricantTransform != other.UseLubricantTransform) return false; return true; } @@ -318,6 +332,7 @@ namespace Tango.PMR.ColorLab { if (VMax != 0D) hash ^= VMax.GetHashCode(); if (GbdData.Length != 0) hash ^= GbdData.GetHashCode(); if (LubData.Length != 0) hash ^= LubData.GetHashCode(); + if (UseLubricantTransform != false) hash ^= UseLubricantTransform.GetHashCode(); return hash; } @@ -389,6 +404,10 @@ namespace Tango.PMR.ColorLab { output.WriteRawTag(130, 1); output.WriteBytes(LubData); } + if (UseLubricantTransform != false) { + output.WriteRawTag(136, 1); + output.WriteBool(UseLubricantTransform); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -440,6 +459,9 @@ namespace Tango.PMR.ColorLab { if (LubData.Length != 0) { size += 2 + pb::CodedOutputStream.ComputeBytesSize(LubData); } + if (UseLubricantTransform != false) { + size += 2 + 1; + } return size; } @@ -497,6 +519,9 @@ namespace Tango.PMR.ColorLab { if (other.LubData.Length != 0) { LubData = other.LubData; } + if (other.UseLubricantTransform != false) { + UseLubricantTransform = other.UseLubricantTransform; + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -574,6 +599,10 @@ namespace Tango.PMR.ColorLab { LubData = input.ReadBytes(); break; } + case 136: { + UseLubricantTransform = input.ReadBool(); + break; + } } } } diff --git a/Software/Visual_Studio/Tango.PMR/ColorLab/GradientConversionInput.cs b/Software/Visual_Studio/Tango.PMR/ColorLab/GradientConversionInput.cs index abb24ddb0..37e3642fa 100644 --- a/Software/Visual_Studio/Tango.PMR/ColorLab/GradientConversionInput.cs +++ b/Software/Visual_Studio/Tango.PMR/ColorLab/GradientConversionInput.cs @@ -24,19 +24,20 @@ namespace Tango.PMR.ColorLab { string.Concat( "Ch1HcmFkaWVudENvbnZlcnNpb25JbnB1dC5wcm90bxISVGFuZ28uUE1SLkNv", "bG9yTGFiGhJQcm9jZXNzUmFuZ2UucHJvdG8aEUlucHV0TGlxdWlkLnByb3Rv", - "GhdHcmFkaWVudElucHV0U3RvcC5wcm90byLAAgoXR3JhZGllbnRDb252ZXJz", + "GhdHcmFkaWVudElucHV0U3RvcC5wcm90byLfAgoXR3JhZGllbnRDb252ZXJz", "aW9uSW5wdXQSDwoHVGhyZWFkTBgBIAEoARIPCgdUaHJlYWRBGAIgASgBEg8K", "B1RocmVhZEIYAyABKAESEwoLRm9yd2FyZERhdGEYBCABKAwSFQoNU2VnbWVu", "dExlbmd0aBgFIAEoARI0CgVTdG9wcxgGIAMoCzIlLlRhbmdvLlBNUi5Db2xv", "ckxhYi5HcmFkaWVudElucHV0U3RvcBI1CgxJbnB1dExpcXVpZHMYByADKAsy", "Hy5UYW5nby5QTVIuQ29sb3JMYWIuSW5wdXRMaXF1aWQSNwoNUHJvY2Vzc1Jh", "bmdlcxgIIAMoCzIgLlRhbmdvLlBNUi5Db2xvckxhYi5Qcm9jZXNzUmFuZ2US", - "DwoHR2JkRGF0YRgJIAEoDBIPCgdMdWJEYXRhGAogASgMQh4KHGNvbS50d2lu", - "ZS50YW5nby5wbXIuY29sb3JsYWJiBnByb3RvMw==")); + "DwoHR2JkRGF0YRgJIAEoDBIPCgdMdWJEYXRhGAogASgMEh0KFVVzZUx1YnJp", + "Y2FudFRyYW5zZm9ybRgLIAEoCEIeChxjb20udHdpbmUudGFuZ28ucG1yLmNv", + "bG9ybGFiYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Tango.PMR.ColorLab.ProcessRangeReflection.Descriptor, global::Tango.PMR.ColorLab.InputLiquidReflection.Descriptor, global::Tango.PMR.ColorLab.GradientInputStopReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.GradientConversionInput), global::Tango.PMR.ColorLab.GradientConversionInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ForwardData", "SegmentLength", "Stops", "InputLiquids", "ProcessRanges", "GbdData", "LubData" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.GradientConversionInput), global::Tango.PMR.ColorLab.GradientConversionInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ForwardData", "SegmentLength", "Stops", "InputLiquids", "ProcessRanges", "GbdData", "LubData", "UseLubricantTransform" }, null, null, null) })); } #endregion @@ -77,6 +78,7 @@ namespace Tango.PMR.ColorLab { processRanges_ = other.processRanges_.Clone(); gbdData_ = other.gbdData_; lubData_ = other.lubData_; + useLubricantTransform_ = other.useLubricantTransform_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -191,6 +193,17 @@ namespace Tango.PMR.ColorLab { } } + /// Field number for the "UseLubricantTransform" field. + public const int UseLubricantTransformFieldNumber = 11; + private bool useLubricantTransform_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool UseLubricantTransform { + get { return useLubricantTransform_; } + set { + useLubricantTransform_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as GradientConversionInput); @@ -214,6 +227,7 @@ namespace Tango.PMR.ColorLab { if(!processRanges_.Equals(other.processRanges_)) return false; if (GbdData != other.GbdData) return false; if (LubData != other.LubData) return false; + if (UseLubricantTransform != other.UseLubricantTransform) return false; return true; } @@ -230,6 +244,7 @@ namespace Tango.PMR.ColorLab { hash ^= processRanges_.GetHashCode(); if (GbdData.Length != 0) hash ^= GbdData.GetHashCode(); if (LubData.Length != 0) hash ^= LubData.GetHashCode(); + if (UseLubricantTransform != false) hash ^= UseLubricantTransform.GetHashCode(); return hash; } @@ -271,6 +286,10 @@ namespace Tango.PMR.ColorLab { output.WriteRawTag(82); output.WriteBytes(LubData); } + if (UseLubricantTransform != false) { + output.WriteRawTag(88); + output.WriteBool(UseLubricantTransform); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -300,6 +319,9 @@ namespace Tango.PMR.ColorLab { if (LubData.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(LubData); } + if (UseLubricantTransform != false) { + size += 1 + 1; + } return size; } @@ -332,6 +354,9 @@ namespace Tango.PMR.ColorLab { if (other.LubData.Length != 0) { LubData = other.LubData; } + if (other.UseLubricantTransform != false) { + UseLubricantTransform = other.UseLubricantTransform; + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -382,6 +407,10 @@ namespace Tango.PMR.ColorLab { LubData = input.ReadBytes(); break; } + case 88: { + UseLubricantTransform = input.ReadBool(); + break; + } } } } diff --git a/Software/Visual_Studio/Tango.PMR/ColorLab/OutOfGamutInput.cs b/Software/Visual_Studio/Tango.PMR/ColorLab/OutOfGamutInput.cs index e56cf37fe..ebde255c5 100644 --- a/Software/Visual_Studio/Tango.PMR/ColorLab/OutOfGamutInput.cs +++ b/Software/Visual_Studio/Tango.PMR/ColorLab/OutOfGamutInput.cs @@ -24,18 +24,19 @@ namespace Tango.PMR.ColorLab { string.Concat( "ChVPdXRPZkdhbXV0SW5wdXQucHJvdG8SElRhbmdvLlBNUi5Db2xvckxhYhoW", "SW5wdXRDb29yZGluYXRlcy5wcm90bxoQQ29sb3JTcGFjZS5wcm90bxoSUHJv", - "Y2Vzc1JhbmdlLnByb3RvIqgCCg9PdXRPZkdhbXV0SW5wdXQSDwoHVGhyZWFk", + "Y2Vzc1JhbmdlLnByb3RvIscCCg9PdXRPZkdhbXV0SW5wdXQSDwoHVGhyZWFk", "TBgBIAEoARIPCgdUaHJlYWRBGAIgASgBEg8KB1RocmVhZEIYAyABKAESMgoK", "Q29sb3JTcGFjZRgEIAEoDjIeLlRhbmdvLlBNUi5Db2xvckxhYi5Db2xvclNw", "YWNlEj4KEElucHV0Q29vcmRpbmF0ZXMYBSABKAsyJC5UYW5nby5QTVIuQ29s", "b3JMYWIuSW5wdXRDb29yZGluYXRlcxITCgtGb3J3YXJkRGF0YRgGIAEoDBI3", "Cg1Qcm9jZXNzUmFuZ2VzGAcgAygLMiAuVGFuZ28uUE1SLkNvbG9yTGFiLlBy", - "b2Nlc3NSYW5nZRIPCgdHYmREYXRhGAggASgMEg8KB0x1YkRhdGEYCSABKAxC", - "HgocY29tLnR3aW5lLnRhbmdvLnBtci5jb2xvcmxhYmIGcHJvdG8z")); + "b2Nlc3NSYW5nZRIPCgdHYmREYXRhGAggASgMEg8KB0x1YkRhdGEYCSABKAwS", + "HQoVVXNlTHVicmljYW50VHJhbnNmb3JtGAogASgIQh4KHGNvbS50d2luZS50", + "YW5nby5wbXIuY29sb3JsYWJiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Tango.PMR.ColorLab.InputCoordinatesReflection.Descriptor, global::Tango.PMR.ColorLab.ColorSpaceReflection.Descriptor, global::Tango.PMR.ColorLab.ProcessRangeReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.OutOfGamutInput), global::Tango.PMR.ColorLab.OutOfGamutInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ColorSpace", "InputCoordinates", "ForwardData", "ProcessRanges", "GbdData", "LubData" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.OutOfGamutInput), global::Tango.PMR.ColorLab.OutOfGamutInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ColorSpace", "InputCoordinates", "ForwardData", "ProcessRanges", "GbdData", "LubData", "UseLubricantTransform" }, null, null, null) })); } #endregion @@ -75,6 +76,7 @@ namespace Tango.PMR.ColorLab { processRanges_ = other.processRanges_.Clone(); gbdData_ = other.gbdData_; lubData_ = other.lubData_; + useLubricantTransform_ = other.useLubricantTransform_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -180,6 +182,17 @@ namespace Tango.PMR.ColorLab { } } + /// Field number for the "UseLubricantTransform" field. + public const int UseLubricantTransformFieldNumber = 10; + private bool useLubricantTransform_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool UseLubricantTransform { + get { return useLubricantTransform_; } + set { + useLubricantTransform_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as OutOfGamutInput); @@ -202,6 +215,7 @@ namespace Tango.PMR.ColorLab { if(!processRanges_.Equals(other.processRanges_)) return false; if (GbdData != other.GbdData) return false; if (LubData != other.LubData) return false; + if (UseLubricantTransform != other.UseLubricantTransform) return false; return true; } @@ -217,6 +231,7 @@ namespace Tango.PMR.ColorLab { hash ^= processRanges_.GetHashCode(); if (GbdData.Length != 0) hash ^= GbdData.GetHashCode(); if (LubData.Length != 0) hash ^= LubData.GetHashCode(); + if (UseLubricantTransform != false) hash ^= UseLubricantTransform.GetHashCode(); return hash; } @@ -260,6 +275,10 @@ namespace Tango.PMR.ColorLab { output.WriteRawTag(74); output.WriteBytes(LubData); } + if (UseLubricantTransform != false) { + output.WriteRawTag(80); + output.WriteBool(UseLubricantTransform); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -290,6 +309,9 @@ namespace Tango.PMR.ColorLab { if (LubData.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(LubData); } + if (UseLubricantTransform != false) { + size += 1 + 1; + } return size; } @@ -326,6 +348,9 @@ namespace Tango.PMR.ColorLab { if (other.LubData.Length != 0) { LubData = other.LubData; } + if (other.UseLubricantTransform != false) { + UseLubricantTransform = other.UseLubricantTransform; + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -375,6 +400,10 @@ namespace Tango.PMR.ColorLab { LubData = input.ReadBytes(); break; } + case 80: { + UseLubricantTransform = input.ReadBool(); + break; + } } } } diff --git a/Software/Visual_Studio/Tango.PMR/ColorLab/RecommendedProcessTableInput.cs b/Software/Visual_Studio/Tango.PMR/ColorLab/RecommendedProcessTableInput.cs index 8384769a6..4e5a52d8d 100644 --- a/Software/Visual_Studio/Tango.PMR/ColorLab/RecommendedProcessTableInput.cs +++ b/Software/Visual_Studio/Tango.PMR/ColorLab/RecommendedProcessTableInput.cs @@ -24,19 +24,20 @@ namespace Tango.PMR.ColorLab { string.Concat( "CiJSZWNvbW1lbmRlZFByb2Nlc3NUYWJsZUlucHV0LnByb3RvEhJUYW5nby5Q", "TVIuQ29sb3JMYWIaElByb2Nlc3NSYW5nZS5wcm90bxoRSW5wdXRMaXF1aWQu", - "cHJvdG8aF0dyYWRpZW50SW5wdXRTdG9wLnByb3RvIsQCChxSZWNvbW1lbmRl", + "cHJvdG8aF0dyYWRpZW50SW5wdXRTdG9wLnByb3RvIuMCChxSZWNvbW1lbmRl", "ZFByb2Nlc3NUYWJsZUlucHV0Eg8KB1RocmVhZEwYASABKAESDwoHVGhyZWFk", "QRgCIAEoARIPCgdUaHJlYWRCGAMgASgBEhMKC0ZvcndhcmREYXRhGAQgASgM", "EjQKBVN0b3BzGAUgAygLMiUuVGFuZ28uUE1SLkNvbG9yTGFiLkdyYWRpZW50", "SW5wdXRTdG9wEjUKDElucHV0TGlxdWlkcxgGIAMoCzIfLlRhbmdvLlBNUi5D", "b2xvckxhYi5JbnB1dExpcXVpZBI3Cg1Qcm9jZXNzUmFuZ2VzGAcgAygLMiAu", "VGFuZ28uUE1SLkNvbG9yTGFiLlByb2Nlc3NSYW5nZRIUCgxVc2VMaWdodElu", - "a3MYCCABKAgSDwoHR2JkRGF0YRgJIAEoDBIPCgdMdWJEYXRhGAogASgMQh4K", - "HGNvbS50d2luZS50YW5nby5wbXIuY29sb3JsYWJiBnByb3RvMw==")); + "a3MYCCABKAgSDwoHR2JkRGF0YRgJIAEoDBIPCgdMdWJEYXRhGAogASgMEh0K", + "FVVzZUx1YnJpY2FudFRyYW5zZm9ybRgLIAEoCEIeChxjb20udHdpbmUudGFu", + "Z28ucG1yLmNvbG9ybGFiYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Tango.PMR.ColorLab.ProcessRangeReflection.Descriptor, global::Tango.PMR.ColorLab.InputLiquidReflection.Descriptor, global::Tango.PMR.ColorLab.GradientInputStopReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.RecommendedProcessTableInput), global::Tango.PMR.ColorLab.RecommendedProcessTableInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ForwardData", "Stops", "InputLiquids", "ProcessRanges", "UseLightInks", "GbdData", "LubData" }, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.ColorLab.RecommendedProcessTableInput), global::Tango.PMR.ColorLab.RecommendedProcessTableInput.Parser, new[]{ "ThreadL", "ThreadA", "ThreadB", "ForwardData", "Stops", "InputLiquids", "ProcessRanges", "UseLightInks", "GbdData", "LubData", "UseLubricantTransform" }, null, null, null) })); } #endregion @@ -77,6 +78,7 @@ namespace Tango.PMR.ColorLab { useLightInks_ = other.useLightInks_; gbdData_ = other.gbdData_; lubData_ = other.lubData_; + useLubricantTransform_ = other.useLubricantTransform_; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -191,6 +193,17 @@ namespace Tango.PMR.ColorLab { } } + /// Field number for the "UseLubricantTransform" field. + public const int UseLubricantTransformFieldNumber = 11; + private bool useLubricantTransform_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool UseLubricantTransform { + get { return useLubricantTransform_; } + set { + useLubricantTransform_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as RecommendedProcessTableInput); @@ -214,6 +227,7 @@ namespace Tango.PMR.ColorLab { if (UseLightInks != other.UseLightInks) return false; if (GbdData != other.GbdData) return false; if (LubData != other.LubData) return false; + if (UseLubricantTransform != other.UseLubricantTransform) return false; return true; } @@ -230,6 +244,7 @@ namespace Tango.PMR.ColorLab { if (UseLightInks != false) hash ^= UseLightInks.GetHashCode(); if (GbdData.Length != 0) hash ^= GbdData.GetHashCode(); if (LubData.Length != 0) hash ^= LubData.GetHashCode(); + if (UseLubricantTransform != false) hash ^= UseLubricantTransform.GetHashCode(); return hash; } @@ -271,6 +286,10 @@ namespace Tango.PMR.ColorLab { output.WriteRawTag(82); output.WriteBytes(LubData); } + if (UseLubricantTransform != false) { + output.WriteRawTag(88); + output.WriteBool(UseLubricantTransform); + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -300,6 +319,9 @@ namespace Tango.PMR.ColorLab { if (LubData.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeBytesSize(LubData); } + if (UseLubricantTransform != false) { + size += 1 + 1; + } return size; } @@ -332,6 +354,9 @@ namespace Tango.PMR.ColorLab { if (other.LubData.Length != 0) { LubData = other.LubData; } + if (other.UseLubricantTransform != false) { + UseLubricantTransform = other.UseLubricantTransform; + } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -382,6 +407,10 @@ namespace Tango.PMR.ColorLab { LubData = input.ReadBytes(); break; } + case 88: { + UseLubricantTransform = input.ReadBool(); + break; + } } } } diff --git a/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml b/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml index d89a2de1f..9e3db5c20 100644 Binary files a/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml and b/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml differ -- cgit v1.3.1