From bf66536228666d733475f4ccdb248e5cec74c0aa Mon Sep 17 00:00:00 2001 From: Victoria Plitt Date: Tue, 5 Nov 2019 11:38:50 +0200 Subject: Done Related Work Items: #1277 --- .../Images/Statuses/Ready_Anim.gif | Bin 0 -> 4671 bytes .../Images/Statuses/dyeing.png | Bin 0 -> 1281 bytes .../Images/Statuses/dyeing_Anim.gif | Bin 0 -> 27299 bytes .../Images/Statuses/error_Anim.gif | Bin 0 -> 6654 bytes .../Images/Statuses/getting_ready_Anim.gif | Bin 0 -> 20744 bytes .../Images/Statuses/machine-off.png | Bin 0 -> 861 bytes .../Images/Statuses/machine_off_Anim.gif | Bin 0 -> 48595 bytes .../Images/Statuses/ready-to-dye.png | Bin 0 -> 891 bytes .../Images/Statuses/service_Anim.gif | Bin 0 -> 6408 bytes .../Images/Statuses/shutdown_icon_Anim.gif | Bin 0 -> 16723 bytes .../Images/Statuses/standby.png | Bin 0 -> 1034 bytes .../Images/Statuses/standby_Anim.gif | Bin 0 -> 31289 bytes .../Tango.MachineStudio.UI.csproj | 18 ++++++- .../Tango.MachineStudio.UI/Views/MainView.xaml | 60 +++++++++++++++++++++ 14 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif new file mode 100644 index 000000000..11cef3b10 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png new file mode 100644 index 000000000..fbace4fa5 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif new file mode 100644 index 000000000..058d9a34d Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif new file mode 100644 index 000000000..9bf0d84f3 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif new file mode 100644 index 000000000..79256816a Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png new file mode 100644 index 000000000..6dc569e35 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif new file mode 100644 index 000000000..9ca81da39 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png new file mode 100644 index 000000000..7edf624be Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif new file mode 100644 index 000000000..f5962c36c Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif new file mode 100644 index 000000000..d936476b6 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png new file mode 100644 index 000000000..6b46c22c0 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif new file mode 100644 index 000000000..89491179d Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif differ 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 b542821d7..3379ef4ae 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 @@ -359,6 +359,18 @@ TCC\template.bmp Always + + + + + + + + + + + + SettingsSingleFileGenerator @@ -384,6 +396,10 @@ {bb2abb74-ba58-4812-83aa-ec8171f42df4} Tango.AutoComplete + + {d129789c-3096-4d0b-8dd7-fe24a4df4b21} + Tango.AnimatedGif + {f441feee-322a-4943-b566-110e12fd3b72} Tango.BL @@ -641,7 +657,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 5513b65ac..d427be9e5 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -11,6 +11,8 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:common="clr-namespace:Tango.MachineStudio.Common;assembly=Tango.MachineStudio.Common" xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL" + xmlns:operations="clr-namespace:Tango.Integration.Operation;assembly=Tango.Integration" + xmlns:gif="clr-namespace:Tango.AnimatedGif;assembly=Tango.AnimatedGif" xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" @@ -26,6 +28,7 @@ + @@ -274,6 +277,63 @@ + + + + + + + + + + + + + + + + + + + + -- cgit v1.3.1 From 0b8ce9dd355873283ffbb644fbad5c46084f895e Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Wed, 6 Nov 2019 15:49:22 +0200 Subject: Fixed a bug with job colorspace is null when entering job summery on catalog. Added ContinuousRequestTimeout to MachineOperator and machine studio external bridge connection. Fixed dispensing nl\sec calculation. Fixed job brush stops liquid volumes setting by correct process parameters. --- .../MachineStudioSettings.cs | 6 + .../ViewModels/MainViewVM.cs | 1 + .../Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs | 20 ++- .../Tango.BL/Dispensing/DispensingCalcBase.cs | 2 +- .../Operation/IMachineOperator.cs | 5 + .../Tango.Integration/Operation/MachineOperator.cs | 142 +++++++++++---------- 6 files changed, 96 insertions(+), 80 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs index c307a8e33..1831d5aa3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs @@ -134,6 +134,11 @@ namespace Tango.MachineStudio.Common /// public TimeSpan ExternalBridgeRequestTimeout { get; set; } + /// + /// Gets or sets the external bridge continuous request timeout. + /// + public TimeSpan ExternalBridgeContinuousRequestTimeout { get; set; } + /// /// Gets the machine service address. /// @@ -173,6 +178,7 @@ namespace Tango.MachineStudio.Common Theme = MachineStudioTheme.Light; JobUnitsMethod = JobUnitsMethods.Operator; ExternalBridgeRequestTimeout = TimeSpan.FromSeconds(5); + ExternalBridgeContinuousRequestTimeout = TimeSpan.FromSeconds(5); } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs index 90fe25c8f..c7fd7a525 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs @@ -460,6 +460,7 @@ namespace Tango.MachineStudio.UI.ViewModels { x.SelectedMachine.As().EnableApplicationLogs = x.EnableApplicationLogs; x.SelectedMachine.RequestTimeout = _settings.ExternalBridgeRequestTimeout; + x.SelectedMachine.ContinuousRequestTimeout = _settings.ExternalBridgeContinuousRequestTimeout; } if (x.SelectedMachine.RequiresAuthentication) diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs index bff6beff5..365075d4a 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs @@ -130,16 +130,6 @@ namespace Tango.PPC.Jobs.ViewModels _context = obj.Context; Job = obj.Job; - if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog) - { - if (_context.ColorCatalogs.SingleOrDefault(x => x.Guid == Job.ColorCatalogGuid) == null) - { - await NotificationProvider.ShowError("The selected color catalog for this job could not be found.\nCannot load job."); - await NavigationManager.NavigateBack(); - return; - } - } - IsPreparingJob = true; Job = await new JobBuilder(_context).Set(Job.Guid) @@ -150,7 +140,15 @@ namespace Tango.PPC.Jobs.ViewModels .WithBrushStops() .BuildAsync(); - await Task.Delay(2000); + if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog) + { + if (_context.ColorCatalogs.SingleOrDefault(x => x.Guid == Job.ColorCatalogGuid) == null) + { + await NotificationProvider.ShowError("The selected color catalog for this job could not be found.\nCannot load job."); + await NavigationManager.NavigateBack(); + return; + } + } await Task.Factory.StartNew(() => { diff --git a/Software/Visual_Studio/Tango.BL/Dispensing/DispensingCalcBase.cs b/Software/Visual_Studio/Tango.BL/Dispensing/DispensingCalcBase.cs index cceabb571..e0f16d4d4 100644 --- a/Software/Visual_Studio/Tango.BL/Dispensing/DispensingCalcBase.cs +++ b/Software/Visual_Studio/Tango.BL/Dispensing/DispensingCalcBase.cs @@ -53,7 +53,7 @@ namespace Tango.BL.Dispensing /// public virtual double CalculatePulsePerSecond(LiquidVolume liquidVolume) { - return CalculateNanoliterPerSecond(liquidVolume) / liquidVolume.NanoliterPerStep * 8d; + return CalculateNanoliterPerSecond(liquidVolume) / liquidVolume.NanoliterPerStep / (double)liquidVolume.DispenserStepDivision; } /// diff --git a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs index 733f7a981..0168320c0 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs @@ -98,6 +98,11 @@ namespace Tango.Integration.Operation /// bool CanPrint { get; } + /// + /// Gets or sets the general continuous request timeout. + /// + TimeSpan ContinuousRequestTimeout { get; set; } + /// /// Occurs when the machine has changed. /// diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index ac9ee93ec..66f8d551c 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -102,6 +102,7 @@ namespace Tango.Integration.Operation EmergencyNotificationProvider = new UsbEmergencyNotificationProvider("COM1"); EnableJobLiquidQuantityValidation = true; FailsWithAdapter = true; + ContinuousRequestTimeout = TimeSpan.FromSeconds(2); } /// @@ -461,6 +462,11 @@ namespace Tango.Integration.Operation /// public IEmergencyNotificationProvider EmergencyNotificationProvider { get; set; } + /// + /// Gets or sets the general continuous request timeout. + /// + public TimeSpan ContinuousRequestTimeout { get; set; } + #endregion #region Virtual Methods @@ -1113,7 +1119,7 @@ namespace Tango.Integration.Operation Thread.Sleep(500); //Just wait maybe Shlomo is getting this message to fast after restart ? bool completed = false; - SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + SendContinuousRequest(request, null, ContinuousRequestTimeout).Subscribe((response) => { if (!completed) { @@ -1339,7 +1345,7 @@ namespace Tango.Integration.Operation var previous_segments_length = job.Segments.Where(x => x.SegmentIndex < segment.SegmentIndex).Sum(x => x.Length); - SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + SendContinuousRequest(request, null, ContinuousRequestTimeout).Subscribe((response) => { response.Message.Status.Progress += previous_segments_length; @@ -1518,100 +1524,100 @@ namespace Tango.Integration.Operation //Perform color correction foreach (var stop in jobSegments.SelectMany(x => x.BrushStops)) { - if (stop.LiquidVolumes == null) + //if (stop.LiquidVolumes == null || stop.BrushColorSpace == ColorSpaces.Volume) + //{ + if (stop.BrushColorSpace == ColorSpaces.RGB || stop.BrushColorSpace == ColorSpaces.LAB) { - if (stop.BrushColorSpace == ColorSpaces.RGB || stop.BrushColorSpace == ColorSpaces.LAB) + var output = converter.Convert(stop, false); + + //TODO: Restore this when Mirta conversion is working as expected. + //if (suggestions.OutOfGamut) + //{ + // throw new InvalidOperationException("Cannot print a brush stop which is out of gamut."); + //} + + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + + foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids) { - var output = converter.Convert(stop, false); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == outputLiquid.LiquidType.ToInt32()); - //TODO: Restore this when Mirta conversion is working as expected. - //if (suggestions.OutOfGamut) - //{ - // throw new InvalidOperationException("Cannot print a brush stop which is out of gamut."); - //} + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'."); + } + liquidVolume.Volume = outputLiquid.Volume; + } + } + else if (stop.BrushColorSpace == ColorSpaces.Catalog) + { + if (stop.ColorCatalogsItem != null) + { stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids) + if (stop.ColorCatalogsItem.Cyan > 0) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == outputLiquid.LiquidType.ToInt32()); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Cyan.ToInt32()); if (liquidVolume == null) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'."); + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Cyan + "'."); } - liquidVolume.Volume = outputLiquid.Volume; + liquidVolume.Volume = stop.ColorCatalogsItem.Cyan; } - } - else if (stop.BrushColorSpace == ColorSpaces.Catalog) - { - if (stop.ColorCatalogsItem != null) + + if (stop.ColorCatalogsItem.Magenta > 0) { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Magenta.ToInt32()); - if (stop.ColorCatalogsItem.Cyan > 0) + if (liquidVolume == null) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Cyan.ToInt32()); - - if (liquidVolume == null) - { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Cyan + "'."); - } - - liquidVolume.Volume = stop.ColorCatalogsItem.Cyan; + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Magenta + "'."); } - if (stop.ColorCatalogsItem.Magenta > 0) - { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Magenta.ToInt32()); - - if (liquidVolume == null) - { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Magenta + "'."); - } + liquidVolume.Volume = stop.ColorCatalogsItem.Magenta; + } - liquidVolume.Volume = stop.ColorCatalogsItem.Magenta; - } + if (stop.ColorCatalogsItem.Yellow > 0) + { + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Yellow.ToInt32()); - if (stop.ColorCatalogsItem.Yellow > 0) + if (liquidVolume == null) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Yellow.ToInt32()); - - if (liquidVolume == null) - { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Yellow + "'."); - } - - liquidVolume.Volume = stop.ColorCatalogsItem.Yellow; + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Yellow + "'."); } - if (stop.ColorCatalogsItem.Black > 0) - { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Black.ToInt32()); + liquidVolume.Volume = stop.ColorCatalogsItem.Yellow; + } - if (liquidVolume == null) - { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Black + "'."); - } + if (stop.ColorCatalogsItem.Black > 0) + { + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == LiquidTypes.Black.ToInt32()); - liquidVolume.Volume = stop.ColorCatalogsItem.Black; + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Black + "'."); } + + liquidVolume.Volume = stop.ColorCatalogsItem.Black; } - else - { - throw new InvalidOperationException($"No catalog item specified for segment color."); - } - } - else if (stop.BrushColorSpace == ColorSpaces.Volume) - { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); } else { - throw new InvalidOperationException($"Unsupported color space {stop.BrushColorSpace}."); + throw new InvalidOperationException($"No catalog item specified for segment color."); } } + else if (stop.BrushColorSpace == ColorSpaces.Volume) + { + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + } + else + { + throw new InvalidOperationException($"Unsupported color space {stop.BrushColorSpace}."); + } + //} if (job.EnableLubrication) { @@ -1909,7 +1915,7 @@ namespace Tango.Integration.Operation bool responseLogged = false; bool completed = false; //Use this in case Shlomo is sending progress after completion. - SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + SendContinuousRequest(request, null, ContinuousRequestTimeout).Subscribe((response) => { if (!completed) { @@ -2182,7 +2188,7 @@ namespace Tango.Integration.Operation LogRequestSent(request); bool responseLogged = false; - SendContinuousRequest(request, null, TimeSpan.FromSeconds(2)).Subscribe((response) => + SendContinuousRequest(request, null, ContinuousRequestTimeout).Subscribe((response) => { handler.RaiseStatusReceived(response.Message.Status); @@ -2403,7 +2409,7 @@ namespace Tango.Integration.Operation public IObservable StartMotorHoming(MotorHomingRequest request) { LogRequestSent(request); - return SendContinuousRequest(request, null, TimeSpan.FromSeconds(5)).Select(x => x.Message); + return SendContinuousRequest(request, null, ContinuousRequestTimeout).Select(x => x.Message); } /// @@ -2447,7 +2453,7 @@ namespace Tango.Integration.Operation public IObservable StartDispenserHoming(DispenserHomingRequest request) { LogRequestSent(request); - return SendContinuousRequest(request, null, TimeSpan.FromSeconds(5)).Select(x => x.Message); + return SendContinuousRequest(request, null, ContinuousRequestTimeout).Select(x => x.Message); } /// -- cgit v1.3.1 From c698425b1ab832fe351aff257815709c01950fc3 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Wed, 6 Nov 2019 18:06:45 +0200 Subject: Implemented liquid quantity validation on PPC and MS. Improved PPC full control view. --- 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 .../ViewModels/MainViewVM.cs | 48 +++++---- .../Tango.MachineStudio.UI.csproj | 2 +- .../Dialogs/InsufficientLiquidQuantityView.xaml | 78 +++++++++++++++ .../Dialogs/InsufficientLiquidQuantityView.xaml.cs | 54 +++++++++++ .../Dialogs/InsufficientLiquidQuantityViewVM.cs | 20 ++++ .../Tango.PPC.Jobs/Images/cartridge_validation.png | Bin 0 -> 44260 bytes .../Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj | 13 ++- .../Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs | 22 ++++- .../Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs | 6 +- .../Controls/MachineStatusControl.xaml | 46 +++++++++ .../Controls/MachineStatusControl.xaml.cs | 28 ++++++ .../Dialogs/InsufficientLiquidQuantityView.xaml | 78 --------------- .../Dialogs/InsufficientLiquidQuantityView.xaml.cs | 54 ----------- .../Dialogs/InsufficientLiquidQuantityViewVM.cs | 20 ---- .../Tango.PPC.UI/Images/cartridge_validation.png | Bin 44260 -> 0 bytes .../Printing/DefaultPrintingManager.cs | 18 ++-- .../PPC/Tango.PPC.UI/Tango.PPC.UI.csproj | 18 ++-- .../PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml | 11 ++- .../PPC/Tango.PPC.UI/Views/LayoutView.xaml | 35 +------ .../Tango.Integration/Operation/MachineOperator.cs | 108 ++++++++++++++++++++- 24 files changed, 421 insertions(+), 238 deletions(-) create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml.cs create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityViewVM.cs create mode 100644 Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/cartridge_validation.png create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml.cs delete mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml delete mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml.cs delete mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityViewVM.cs delete mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Images/cartridge_validation.png (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index 941c49094..bf543e37a 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 a600515de..700cc50d6 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 afccdfc0b..59730a18c 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 76704422a..9bdb66d41 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ 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 3a1f3fb11..c9483b9a2 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 @@ -1481,15 +1481,39 @@ namespace Tango.MachineStudio.Developer.ViewModels JobHandler.Failed += (x, ex) => { - LogManager.Log(ex, String.Format("Job {0} has failed.", RunningJob.Name)); - _eventLogger.Log(ex, String.Format("Job {0} has failed.", RunningJob.Name)); - SetJobFailed(); + if (ex is InsufficientLiquidQuantityException) + { + InvokeUI(() => + { + _notification.ShowModalDialog(new InsufficientLiquidQuantityViewVM(ex as InsufficientLiquidQuantityException), (_) => + { - InvokeUI(() => + MachineOperator.EnableJobLiquidQuantityValidation = false; + StartJob(); + + }, () => + { + SetJobFailed(); + + InvokeUI(() => + { + StopRecordingIfInProgress(); + }); + }); + }); + } + else { - _notification.ShowError("Job failed. " + ex.FlattenMessage()); - StopRecordingIfInProgress(); - }); + LogManager.Log(ex, String.Format("Job {0} has failed.", RunningJob.Name)); + _eventLogger.Log(ex, String.Format("Job {0} has failed.", RunningJob.Name)); + SetJobFailed(); + + InvokeUI(() => + { + _notification.ShowError("Job failed. " + ex.FlattenMessage()); + StopRecordingIfInProgress(); + }); + } }; JobHandler.Finalizing += (_, __) => @@ -1521,16 +1545,6 @@ namespace Tango.MachineStudio.Developer.ViewModels //Finally Canceled.. }; } - catch (InsufficientLiquidQuantityException ex) - { - _notification.ShowModalDialog(new InsufficientLiquidQuantityViewVM(ex), (x) => - { - - MachineOperator.EnableJobLiquidQuantityValidation = false; - StartJob(); - - }, () => { }); - } catch (Exception ex) { LogManager.Log(ex); 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 3379ef4ae..914f7ac2d 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 @@ -657,7 +657,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml new file mode 100644 index 000000000..90492ce9f --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml @@ -0,0 +1,78 @@ + + + + + CLOSE + + + + Insufficient Ink Level + + There seems to be an insufficient ink levels in one or more of the following dispensers. + The job cannot be completed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml.cs new file mode 100644 index 000000000..eabff89b4 --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityView.xaml.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.Integration.Operation; +using static Tango.Integration.Operation.InsufficientLiquidQuantityException; + +namespace Tango.PPC.Jobs.Dialogs +{ + /// + /// Interaction logic for InsufficientLiquidQuantityView.xaml + /// + public partial class InsufficientLiquidQuantityView : UserControl + { + public InsufficientLiquidQuantityView() + { + InitializeComponent(); + } + + private void IdsPackLoaded(object sender, RoutedEventArgs e) + { + Border border = sender as Border; + Grid parent = border.Parent as Grid; + IDSPackLevel packLevel = border.DataContext as IDSPackLevel; + + border.Height = ((double)packLevel.Current / (double)MachineOperator.MAX_DISPENSER_NANOLITER) * parent.ActualHeight; + } + + private void Limit_Loaded(object sender, RoutedEventArgs e) + { + Rectangle rect = sender as Rectangle; + Grid parent = rect.Parent as Grid; + IDSPackLevel packLevel = rect.DataContext as IDSPackLevel; + + var top = ((double)packLevel.Required / (double)MachineOperator.MAX_DISPENSER_NANOLITER) * parent.ActualHeight; + rect.Margin = new Thickness(0, 0, 0, top); + + if (packLevel.IsValid) + { + rect.Visibility = Visibility.Hidden; + } + } + } +} diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityViewVM.cs new file mode 100644 index 000000000..e8cd8df85 --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Dialogs/InsufficientLiquidQuantityViewVM.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.Operation; +using Tango.SharedUI; + +namespace Tango.PPC.Jobs.Dialogs +{ + public class InsufficientLiquidQuantityViewVM : DialogViewVM + { + public InsufficientLiquidQuantityException Exception { get; set; } + + public InsufficientLiquidQuantityViewVM(InsufficientLiquidQuantityException ex) + { + Exception = ex; + } + } +} diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/cartridge_validation.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/cartridge_validation.png new file mode 100644 index 000000000..373cb78c1 Binary files /dev/null and b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/cartridge_validation.png differ diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj index aedf09ce7..65d8ecba3 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj @@ -116,6 +116,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -211,6 +215,10 @@ CatalogSelectionView.xaml + + InsufficientLiquidQuantityView.xaml + + JobCreationView.xaml @@ -482,10 +490,13 @@ + + + - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs index 103a10b28..b98cde7dd 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs @@ -122,7 +122,10 @@ namespace Tango.PPC.Jobs.ViewModels NotificationProvider.CurrentAppBarItem.Close(); } - _stop_job_btn.Push(); + if (!_handler.Status.IsFailed) + { + _stop_job_btn.Push(); + } } #endregion @@ -141,10 +144,27 @@ namespace Tango.PPC.Jobs.ViewModels e.JobHandler.StatusChanged += JobHandler_StatusChanged; e.JobHandler.SpoolChangeRequired += JobHandler_SpoolChangeRequired; e.JobHandler.Stopped += JobHandler_Stopped; + e.JobHandler.Failed += JobHandler_Failed; _stop_job_btn.Push(); } + private void JobHandler_Failed(object sender, Exception ex) + { + if (ex is InsufficientLiquidQuantityException) + { + InvokeUI(async () => + { + await NotificationProvider.ShowDialog(new InsufficientLiquidQuantityViewVM(ex as InsufficientLiquidQuantityException)); + + if (IsVisible) + { + await NavigationManager.NavigateBack(); + } + }); + } + } + /// /// Handles the SpoolChangeRequired event of the JobHandler. /// diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index 3a3b820a5..ebdd18aeb 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -648,13 +648,9 @@ namespace Tango.PPC.Jobs.ViewModels try { LogManager.Log("Start job command pressed. Starting job and navigating to job progress view..."); - await PrintingManager.Print(Job, _db); + var handler = await PrintingManager.Print(Job, _db); await NavigationManager.NavigateTo(nameof(JobProgressView)); } - catch (InsufficientLiquidQuantityException) - { - //Ignore.. - } catch (Exception ex) { LogManager.Log(ex, "Could not start the current job."); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml new file mode 100644 index 000000000..d6114576d --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml @@ -0,0 +1,46 @@ + + + + + + + + + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml.cs new file mode 100644 index 000000000..61ecef0ad --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.PPC.UI.Controls +{ + /// + /// Interaction logic for MachineStatusControl.xaml + /// + public partial class MachineStatusControl : UserControl + { + public MachineStatusControl() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml deleted file mode 100644 index f3c471954..000000000 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - CLOSE - - - - Insufficient Ink Level - - There seems to be an insufficient ink levels in one or more of the following dispensers. - The job cannot be completed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml.cs deleted file mode 100644 index 9ec1eec0e..000000000 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityView.xaml.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using Tango.Integration.Operation; -using static Tango.Integration.Operation.InsufficientLiquidQuantityException; - -namespace Tango.PPC.UI.Dialogs -{ - /// - /// Interaction logic for InsufficientLiquidQuantityView.xaml - /// - public partial class InsufficientLiquidQuantityView : UserControl - { - public InsufficientLiquidQuantityView() - { - InitializeComponent(); - } - - private void IdsPackLoaded(object sender, RoutedEventArgs e) - { - Border border = sender as Border; - Grid parent = border.Parent as Grid; - IDSPackLevel packLevel = border.DataContext as IDSPackLevel; - - border.Height = ((double)packLevel.Current / (double)MachineOperator.MAX_DISPENSER_NANOLITER) * parent.ActualHeight; - } - - private void Limit_Loaded(object sender, RoutedEventArgs e) - { - Rectangle rect = sender as Rectangle; - Grid parent = rect.Parent as Grid; - IDSPackLevel packLevel = rect.DataContext as IDSPackLevel; - - var top = ((double)packLevel.Required / (double)MachineOperator.MAX_DISPENSER_NANOLITER) * parent.ActualHeight; - rect.Margin = new Thickness(0, 0, 0, top); - - if (packLevel.IsValid) - { - rect.Visibility = Visibility.Hidden; - } - } - } -} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityViewVM.cs deleted file mode 100644 index 8b15d2e00..000000000 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/InsufficientLiquidQuantityViewVM.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Integration.Operation; -using Tango.SharedUI; - -namespace Tango.PPC.UI.Dialogs -{ - public class InsufficientLiquidQuantityViewVM : DialogViewVM - { - public InsufficientLiquidQuantityException Exception { get; set; } - - public InsufficientLiquidQuantityViewVM(InsufficientLiquidQuantityException ex) - { - Exception = ex; - } - } -} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/cartridge_validation.png b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/cartridge_validation.png deleted file mode 100644 index 373cb78c1..000000000 Binary files a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/cartridge_validation.png and /dev/null differ diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs index 56ec2fa7e..21c68d3e6 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs @@ -56,16 +56,8 @@ namespace Tango.PPC.UI.Printing #if STUBPRINT handler = await _machineProvider.MachineOperator.PrintStub(job); #else - try - { - handler = await _machineProvider.MachineOperator.Print(job); - } - catch (InsufficientLiquidQuantityException ex) - { - LogManager.Log(ex); - await _notificationProvider.ShowDialog(new InsufficientLiquidQuantityViewVM(ex)); - throw ex; - } + + handler = await _machineProvider.MachineOperator.Print(job); #endif handler.Completed += async (x, e) => @@ -113,9 +105,13 @@ namespace Tango.PPC.UI.Printing }; handler.Failed += async (x, e) => { - try + if (e is InsufficientLiquidQuantityException) { + return; + } + try + { job.JobStatus = JobStatuses.Disrupted; if (!context.IsDisposed) 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 c5045abf3..a0ad5b44d 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 @@ -120,15 +120,14 @@ WiFiAuthenticationView.xaml + + MachineStatusControl.xaml + CartridgeValidationView.xaml - - InsufficientLiquidQuantityView.xaml - - ScreenLockView.xaml @@ -202,13 +201,13 @@ Designer MSBuild:Compile - - MSBuild:Compile + Designer + MSBuild:Compile - - Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -327,7 +326,6 @@ - Tango.ColorLib_v1.dll @@ -577,7 +575,7 @@ if $(ConfigurationName) == Release del *.xml - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml index d83128007..4de00120f 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml @@ -7,14 +7,19 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:Tango.PPC.UI.ViewModels" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:localControls="clr-namespace:Tango.PPC.UI.Controls" xmlns:local="clr-namespace:Tango.PPC.UI.Views" mc:Ignorable="d" d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:ExternalBridgeViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.ExternalBridgeViewVM}" Background="{StaticResource TangoPrimaryBackgroundBrush}"> - - - + + + + + + + - - + diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index 3d3590746..6963b90d4 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -1485,6 +1485,90 @@ namespace Tango.Integration.Operation } } + private void ValidateJobLiquidQuantity(JobTicket ticket, ProcessParametersTable processParameters, Configuration configuration) + { + LogManager.Log("Validating job liquid quantity..."); + + Dictionary liquidQuantities = new Dictionary(); + + foreach (var pack in configuration.NoneEmptyIdsPacks.OrderBy(x => x.PackIndex)) + { + liquidQuantities.Add(pack.PackIndex, 0); + } + + for (int i = 0; i < Math.Max(ticket.NumberOfUnits, 1); i++) + { + for (int segmentIndex = 0; segmentIndex < ticket.Segments.Count; segmentIndex++) + { + var segment = ticket.Segments[segmentIndex]; + var segment_length_cm = segment.Length * 100d; + + var stop_count = segment.BrushStops.Count - (segment.BrushStops.Count == 1 ? 0 : 1); + var stop_length_centimeters = segment_length_cm / stop_count; + + for (int stopIndex = 0; stopIndex < stop_count; stopIndex++) + { + var stop = segment.BrushStops[stopIndex]; + + foreach (var dispenser in stop.Dispensers) + { + liquidQuantities[dispenser.Index] += dispenser.NanoliterPerCentimeter * stop_length_centimeters; + } + } + } + } + + if (MachineStatus != null) + { + var exception = new InsufficientLiquidQuantityException($"Insufficient liquids level."); + + bool shouldThrow = false; + + foreach (var liquidQuantity in liquidQuantities) + { + int index = liquidQuantity.Key; + var packLevel = MachineStatus.IDSPacksLevels.SingleOrDefault(x => x.Index == index); + var idsPack = configuration.NoneEmptyIdsPacks.SingleOrDefault(x => x.PackIndex == index); + + if (packLevel != null) + { + var idsLevel = new InsufficientLiquidQuantityException.IDSPackLevel() + { + IdsPack = idsPack, + Current = packLevel.DispenserLevel, + Required = (int)liquidQuantities[index] + }; + + if (liquidQuantities[index] > packLevel.DispenserLevel) + { + shouldThrow = true; + } + + exception.IdsPackLevels.Add(idsLevel); + } + else + { + LogManager.Log($"Could not validate required liquid quantity for job. Missing IDS Pack level at index {index}.", LogCategory.Warning); + } + } + + + if (shouldThrow) + { + throw LogManager.Log(exception, JsonConvert.SerializeObject(exception.IdsPackLevels.Select(x => new + { + Liquid = x.IdsPack.LiquidType.Name, + x.Required, + x.Current + }).ToList())); + } + } + else + { + LogManager.Log("Could not validate required liquid quantity for job. No machine status received", LogCategory.Warning); + } + } + #endregion #region Public Methods @@ -1658,10 +1742,10 @@ namespace Tango.Integration.Operation job.NumberOfUnits = 1; } - if (EnableJobLiquidQuantityValidation) - { - ValidateJobLiquidQuantity(job, processParameters, job.Machine.Configuration); - } + //if (EnableJobLiquidQuantityValidation) + //{ + // ValidateJobLiquidQuantity(job, processParameters, job.Machine.Configuration); + //} var originalJob = job; var clonedJob = job.Clone(); @@ -1807,6 +1891,22 @@ namespace Tango.Integration.Operation return; } + if (EnableJobLiquidQuantityValidation) + { + try + { + ValidateJobLiquidQuantity(ticket, processParameters, job.Machine.Configuration); + } + catch (Exception ex) + { + Status = MachineStatuses.ReadyToDye; + PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, clonedJob, ex)); + PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, clonedJob)); + handler.RaiseFailed(ex); + return; + } + } + var segs = new List(); if (JobUnitsMethod == JobUnitsMethods.Operator) -- cgit v1.3.1 From 981aa1aa04eebd3aba8380e686875024f2a5aaf6 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 10 Nov 2019 15:45:17 +0200 Subject: Added Color Conversion v3. Machine Studio v4.0.32 PPC v1.0.50 --- 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 .../Machine Studio Installer.aip | 15 +- .../PPC Installer-cache/cacheIndex.txt | Bin 52 -> 52 bytes .../Advanced Installer Projects/PPC Installer.aip | 14 +- .../ColorLib/Tango.ColorLib_v3/ColorConverter.cpp | 2583 ++++++++++++++ .../ColorLib/Tango.ColorLib_v3/ColorConverter.h | 138 + .../ColorLib/Tango.ColorLib_v3/Exports.cpp | 36 + .../ColorLib/Tango.ColorLib_v3/Exports.h | 6 + .../PMR/ColorLab/CalibrationData.pb-c.c | 105 + .../PMR/ColorLab/CalibrationData.pb-c.h | 76 + .../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 | 235 ++ .../PMR/ColorLab/ConversionInput.pb-c.h | 96 + .../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/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 + .../Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.c | 118 + .../Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.h | 76 + .../PMR/ColorLab/LiquidType.pb-c.c | 47 + .../PMR/ColorLab/LiquidType.pb-c.h | 48 + .../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 + .../ColorLib/Tango.ColorLib_v3/ReadMe.txt | 48 + .../Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj | 230 ++ .../Tango.ColorLib_v3.vcxproj.filters | 198 ++ .../Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.cpp | 183 + .../Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.h | 47 + .../ColorLib/Tango.ColorLib_v3/Utils/CalibData.cpp | 72 + .../ColorLib/Tango.ColorLib_v3/Utils/CalibData.h | 32 + .../Tango.ColorLib_v3/Utils/ColorConvert.cpp | 1166 +++++++ .../Tango.ColorLib_v3/Utils/ColorConvert.h | 131 + .../Tango.ColorLib_v3/Utils/ColorTransf.cpp | 521 +++ .../ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.h | 53 + .../ColorLib/Tango.ColorLib_v3/Utils/Curves.cpp | 154 + .../ColorLib/Tango.ColorLib_v3/Utils/Curves.h | 23 + .../ColorLib/Tango.ColorLib_v3/Utils/GBD.cpp | 347 ++ .../ColorLib/Tango.ColorLib_v3/Utils/GBD.h | 38 + .../ColorLib/Tango.ColorLib_v3/Utils/Interp.cpp | 127 + .../ColorLib/Tango.ColorLib_v3/Utils/Interp.h | 24 + .../Tango.ColorLib_v3/Utils/NDInterpUtils.cpp | 329 ++ .../Tango.ColorLib_v3/Utils/NDInterpUtils.h | 60 + .../Tango.ColorLib_v3/Utils/NumConversions.cpp | 64 + .../Tango.ColorLib_v3/Utils/NumConversions.h | 17 + .../Tango.ColorLib_v3/protobuf-c/protobuf-c.c | 3642 ++++++++++++++++++++ .../Tango.ColorLib_v3/protobuf-c/protobuf-c.h | 1106 ++++++ .../ColorLib/Tango.ColorLib_v3/targetver.h | 8 + .../Tango.MachineStudio.RML/Views/RmlView.xaml | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Tango.MachineStudio.UI.csproj | 6 +- .../PPC/Tango.PPC.UI/Tango.PPC.UI.csproj | 6 +- .../Visual_Studio/PPC/Tango.PPC.UI/app.manifest | 2 +- Software/Visual_Studio/Tango.sln | 49 +- 69 files changed, 14444 insertions(+), 24 deletions(-) create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationData.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationData.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationPoint.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationPoint.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ColorSpace.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ColorSpace.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionInput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionInput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionOutput.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionOutput.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputCoordinates.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputCoordinates.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputLiquid.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputLiquid.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputCoordinates.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputCoordinates.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputLiquid.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputLiquid.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ProcessRange.pb-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ProcessRange.pb-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ReadMe.txt create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj.filters create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Curves.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Curves.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/GBD.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/GBD.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Interp.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Interp.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NDInterpUtils.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NDInterpUtils.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.cpp create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/protobuf-c/protobuf-c.c create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/protobuf-c/protobuf-c.h create mode 100644 Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/targetver.h (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index bf543e37a..d5304a381 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 700cc50d6..c5bc583ac 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 59730a18c..849baff99 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 9bdb66d41..4c1df436f 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip index 5cd515e0f..b29828743 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip @@ -15,10 +15,10 @@ - + - + @@ -228,6 +228,7 @@ + @@ -237,6 +238,7 @@ + @@ -338,7 +340,7 @@ - + @@ -378,7 +380,7 @@ - + @@ -538,6 +540,8 @@ + + @@ -555,6 +559,7 @@ + @@ -756,7 +761,7 @@ - + diff --git a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt index 6d87e9201..a603ff06b 100644 Binary files a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt and b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt differ diff --git a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip index f1920c766..1f437eb43 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip @@ -106,6 +106,7 @@ + @@ -143,6 +144,7 @@ + @@ -178,15 +180,12 @@ - - - - + @@ -292,7 +291,8 @@ - + + @@ -385,9 +385,6 @@ - - - @@ -467,6 +464,7 @@ + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.cpp new file mode 100644 index 000000000..baf7ade84 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.cpp @@ -0,0 +1,2583 @@ +#include "ColorConverter.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 + +/*#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 + + +Tango::ColorLib::ColorConverter::ColorConverter() : m_A2BTransform(NULL), m_B2ATransform(NULL), +m_GBD(NULL), m_CalibCurves(NULL), m_Conv02(NULL), m_GamutRegionMaxLim(NULL), +m_maxNlPerCM(NULL), m_nA2BnSepIn(0), m_nA2BnSepOut(0), m_nB2AnSepIn(0), m_nB2AnSepOut(0), +m_nInks(0), m_nVolumes(0), m_AdaptWP(false), m_nGamutRegions(0), m_LinCurves(NULL), + m_nProcessRanges(0), m_ProcessRangesMaxP(NULL) + //m_ProcessRangesMinInkUptake(NULL),m_ProcessRangesMinP(NULL), + //m_ProcessRangesMaxInkUptake(NULL) +{ + m_whitepointLab.Set(-1, -1, -1); + m_whitepointXYZ_Strip.Set(-1, -1, -1); + m_whitepointXYZ_CT.Set(-1, -1, -1); + +} + +Tango::ColorLib::ColorConverter::~ColorConverter() +{ + if (m_A2BTransform != NULL) + { + delete m_A2BTransform; + m_A2BTransform = NULL; + } + if (m_B2ATransform != NULL) + { + delete m_B2ATransform; + m_B2ATransform = NULL; + } + if (m_GBD != NULL) + { + delete m_GBD; + m_GBD = NULL; + } + if (m_Conv02 != NULL) + { + delete m_Conv02; + m_Conv02 = NULL; + } + if (m_CalibCurves != NULL) + { + delete[] m_CalibCurves; + m_CalibCurves = NULL; + } + if (m_GamutRegionMaxLim != NULL) + { + delete[] m_GamutRegionMaxLim; + m_GamutRegionMaxLim = NULL; + } + if (m_LinCurves != NULL) + { + delete m_LinCurves; + m_LinCurves = NULL; + } + if (m_ProcessRangesMaxP != NULL) + { + delete[] m_ProcessRangesMaxP; + m_ProcessRangesMaxP = NULL; + } +/* if (m_ProcessRangesMinP != NULL) + { + delete[] m_ProcessRangesMinP; + m_ProcessRangesMinP = NULL; + }*/ + /*if (m_ProcessRangesMaxInkUptake != NULL) + { + delete[] m_ProcessRangesMaxInkUptake; + m_ProcessRangesMaxInkUptake = NULL; + } + if (m_ProcessRangesMinInkUptake != NULL) + { + delete[] m_ProcessRangesMinInkUptake; + m_ProcessRangesMinInkUptake = NULL; + }*/ +} + +void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(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]; + 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 + + m_B2ATransform->evalLab2InkP(Lab1P, InkOut, GamutRegion[i]); //InkOut is in units of 16 bits + InGamut = IsInGamut(Lab1P, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + //m_A2BTransform->evalInkP2Lab(InkOut, Lab1P, GamutRegion[i]); + + //Convert to CT WP + m_Conv02->ChangeWP(LabOnGamut, LabInFinal1, m_whitepointXYZ_CT, m_WP); //convert back to Absolute + LimitLab(LabInFinal1); //Absolute + + //Check if whitepoints match + if (m_AdaptWP) + { + //Convert to Strip whitepoint + m_Conv02->ChangeWP(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); + + double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + for (int j = 0; j < m_nB2AnSepOut; ++j) + { + InkOut[j] *= NormFactor; + if (InkOut[j] <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[j].Eval(InkOut[j] * 655.35, InkOut[j]); + InkOut[j] /= 655.35; + } + } + + VectorXd InkOutV = DoubleToVector(InkOut, m_nInks); + + ConvertToNLInks(InkOutV, InkOutV); + double maxNLInk = -10; + for (int j = 0; j < m_nInks; ++j) + maxNLInk = std::max(InkOutV(j), maxNLInk); + + for (int j = 0; j < (int)(conversionInput->n_processranges - 1); ++j) + { + if (maxNLInk > m_ProcessRangesMaxP[j]) + GamutRegion[i]++; + } + + NLInkPToVolume(InkOutV, Vol); + //make sure the rounded sum does not exceed the limit in the gamut region + for (int j = 0; j < m_nInks; ++j) + VolumeHive(i, j) = Vol(j); + } + for (int i = 0; i < 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; + } + 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) +{ + //Read thread white. Thread White is given in CIELab Space + m_whitepointLab.Set(conversionInput->threadl, conversionInput->threada, conversionInput->threadb); + //White point in XYZ Color Space + ColorConvert CConvert(D65, D65); + C_RGB_XYZ_Lab tmpW; + tmpW = CConvert.LabToXYZ(m_whitepointLab); + m_whitepointXYZ_Strip.Set(tmpW.Get_x(), tmpW.Get_y(), tmpW.Get_z()); + + + + //parse Color Tansformations, placed in forward data + int bytesread = 0; + NumConversions conv; + int tag_count = 0; + if (conversionInput->has_forwarddata) + { + //Read Header + CT_Header header = read_header(conversionInput, bytesread); + SetnGamutRegions((int)header.nGamutRegions); + if (m_nGamutRegions != conversionInput->n_processranges) + { + throw std::exception("Number of gamut regions in table does not match STRIP\0"); + return; + } + m_GamutRegionMaxLim = new double[m_nGamutRegions]; + for (int i = 0; i < m_nGamutRegions; ++i) + m_GamutRegionMaxLim[i] = header.GRegMaxLim[i]; + m_nProcessRanges = (int)(conversionInput->n_processranges); + +/* for (int i = 0; i < m_nGamutRegions; ++i) + { + if (abs(m_GamutRegionMaxLim[i] - conversionInput->processranges[i]->maxinkuptake)> eps) + throw std::exception(" Gamut Region Limit does not match MaxInkUptake in STRIP\0"); + } + */ + if (header.GRegMaxLim != NULL) + { + delete[]header.GRegMaxLim; + header.GRegMaxLim = NULL; + } + + + uint32_t tmp; + uint8_t *buff = conversionInput->forwarddata.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 = NULL; + int n = 0; + int i, j; + for (i = 0; i < tag_count; ++i) + { + TagSize[i] = new int[3]; + //TagSize[i] = DBG_NEW int[3]; + tmp = conv.ByteToInt(buff, bytesread); + n = sizeof((char*)&tmp); + delete[] tmpC; + tmpC = NULL; + tmpC = new char[n]; + //tmpC = DBG_NEW char[n]; + conv.getchar(tmp, n, tmpC); + //TagNames[i] = DBG_NEW char[n]; + TagNames[i] = new char[n]; + for (j = 0; j < n; ++j) + TagNames[i][j] = tmpC[j]; + bytesread += 4; + TagSize[i][0] = conv.ByteToInt(buff, bytesread); + bytesread += 4; + TagSize[i][1] = conv.ByteToInt(buff, bytesread); + bytesread += 4; + } + delete[] tmpC; + 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], "B2A ", 4) == 0) + TList[k] = B2A; + 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], "cprt", 4) == 0) + TList[k] = cprt; + else if (strncmp(TagNames[k], "lcrv", 4) == 0) + TList[k] = lcrv; + // else if (strncmp(TagNames[k], "GReg", 2) == 0) + // TList[k] = GReg; + else + throw std::exception("Unknown Tag in Color Tables"); + } + for (int k = 0; k < tag_count; ++k) + { + switch (TList[k]) + { + case A2B: + { + uint8_t *A2BLUT = &(conversionInput->forwarddata.data[TagSize[k][0]]); + int A2BLutsize = TagSize[k][1]; + m_A2BTransform = new ColorTransf(); + //m_A2BTransform = DBG_NEW ColorTransf(); + m_A2BTransform->InitData(A2BLUT, A2BLutsize); + break; + } + case B2A: + { + uint8_t *B2ALUT = &(conversionInput->forwarddata.data[TagSize[k][0]]); + int B2ALutsize = TagSize[k][1]; + m_B2ATransform = new ColorTransf(); + //m_B2ATransform = DBG_NEW ColorTransf(); + m_B2ATransform->InitData(B2ALUT, B2ALutsize); + break; + } + /* case GReg: + { + uint8_t *GRegLUT = &(conversionInput->forwarddata.data[TagSize[k][0]]); + int GRegLutsize = TagSize[k][1]; + m_GRegTransform = new ColorTransf(); + //m_B2ATransform = DBG_NEW ColorTransf(); + m_GRegTransform->InitData(GRegLUT, GRegLutsize); + break; + } */ + case gbd: + { + uint8_t *GBDList = &(conversionInput->forwarddata.data[TagSize[k][0]]); + m_GBD = new GBD(); + //m_GBD = DBG_NEW GBD(); + int GBDSize = TagSize[k][1]; + m_GBD->InitData(GBDList, GBDSize); + break; + } + case lcrv: + { + uint8_t *CurvesData = &(conversionInput->forwarddata.data[TagSize[k][0]]); + m_LinCurves = new Curves(); + int CurvesSize = TagSize[k][1]; + m_LinCurves->InitData(CurvesData, CurvesSize); + break; + } + case wtpt: + { + read_xyz_type(TagSize[k][0], TagSize[k][1], &m_whitepointXYZ_CT, conversionInput); + + break; + } + case cprt: + { + std::string textstr; + read_text_type(TagSize[k][0], TagSize[k][1], &textstr, conversionInput); + break; + } + case desc: + { + std::string textdescstr; + read_text_description_type(TagSize[k][0], TagSize[k][1], textdescstr, conversionInput); + 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.ColorSpace != NULL) + { + delete header.ColorSpace; + header.ColorSpace = NULL; + } + if (header.ConnectionSpace != NULL) + { + delete header.ConnectionSpace; + header.ConnectionSpace = NULL; + } + if (header.DeviceManufacturer != NULL) + { + delete header.DeviceManufacturer; + header.DeviceManufacturer = NULL; + } + } + + + //Verify all relevant tags had been read + if (m_A2BTransform == NULL) + { + throw std::exception("Missing Forward Transform in Color Tables"); + return; + } + if (m_B2ATransform == NULL) + { + throw std::exception("Missing Inverse Transform in Color Tables"); + return; + } + if (m_GBD == NULL) + { + throw std::exception("Missing 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; + } + return; // OK + } + + +void Tango::ColorLib::ColorConverter::readCalibrationTables(ConversionInput* conversionInput) +{ + SetNumberofInks((int)(conversionInput->inputcoordinates->n_inputliquids)); + //CalibData *CalibCurves = new CalibData[m_nInks]; + m_CalibCurves = new CalibData[m_nInks]; + //m_CalibCurves = DBG_NEW CalibData[m_nInks]; + for (int i = 0; i < m_nInks; ++i) + { + InputLiquid* InkType = conversionInput->inputcoordinates->inputliquids[i]; + + m_CalibCurves[i].SetCalibName((int)(InkType->calibrationdata->liquidtype)); + + m_CalibCurves[i].SetMaxNlPerCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter); + switch (InkType->calibrationdata->liquidtype) + { + 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::ConvertColorToLinearInks(ConversionInput* conversionInput, 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 (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, 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) = 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]; + //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 + int GamutRegion; + double *InkOutP = new double[m_nB2AnSepOut]; + //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; + //LabInFinal is in Relative Colorimetric, just like the Color Tables + m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is in units of 16 bits + + //Convert to Lab to get the actual in Gamut Lab + //double *LabInP = new double[3]; + //double *LabInP = DBG_NEW double[3]; + //m_A2BTransform->evalInkP2Lab(InkOutP, LabInP, GamutRegion); //Lab is in Relative Colorimetric + double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + //Convert InkOut to Linear via initial calibration Tables + //Initial calibration tables are the ones that were included in the color table + for (int i = 0; i < m_nB2AnSepOut; ++i) + { + InkOutP[i] *= NormFactor; + if (InkOutP[i] <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + } + } + InkOut = DoubleToVector(InkOutP, m_nInks); + + //Convert to CT thread, LabOnGamut is in Relative Colorimetric Space + CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_CT, m_WP); + //check if the thread to be used is the same as the one in the color tables + if (m_AdaptWP) + { + //Convert to Strip White Point + CConvertD65.ChangeWP(LabInFinal, LabInFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT); + } + LabOut = DoubleToVector(LabInFinal, 3); + CConvertD65.SetReferenceWhite(D65); + double *RGBOutP1 = new double[3]; + //double *RGBOutP1 = DBG_NEW double[3]; + CConvertD65.LabtoRGB(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; + } + 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. 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] = conversionInput->inputcoordinates->l; //Absolute Colorimetric + LabIn[1] = conversionInput->inputcoordinates->a; + LabIn[2] = conversionInput->inputcoordinates->b; + //the assumption is that the color space has illumination that matches the whitepoint of the Strip + ColorConvert CConvertD65(D65, D65); //Destination, source + double *LabInFinal1 = new double[3]; + //double *LabInFinal1 = DBG_NEW double[3]; + 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 + InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut); + LimitLab(LabOnGamut); + + //convert to Inks + int GamutRegion; + double *InkOutP = new double[m_nB2AnSepOut]; + //double *InkOutP = DBG_NEW double[m_nB2AnSepOut]; + m_B2ATransform->evalLab2InkP(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_ProcessRangesMaxP[0] range + double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0; + for (int i = 0; i < m_nB2AnSepOut; ++i) + { + InkOutP[i] *= NormFactor; + if (InkOutP[i] <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + } + } + InkOut = DoubleToVector(InkOutP, m_nInks); + double *LabOutFinal = new double[3]; + //double *LabOutFinal = DBG_NEW double[3]; + 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); + 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.LabtoRGB(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; + } + break; + } + + case(COLOR_SPACE__CMYK): + {//no conversion + //missing from structure light inks or special colors + // just convert Lab for rgb display + double *outData = new double[m_nA2BnSepIn]; + //double *outData = DBG_NEW double[m_nA2BnSepIn]; + size_t CountSep = 0; + outData[0] = (double)(conversionInput->inputcoordinates->cyan); + outData[1] = (double)(conversionInput->inputcoordinates->magenta); + outData[2] = (double)(conversionInput->inputcoordinates->yellow); + outData[3] = conversionInput->inputcoordinates->key; + CountSep=4; + + if (CountSep != m_nA2BnSepIn) + { + //mismatch between table and sent data + throw std::exception("Mismatch between table and sent data"); + return; + } + //Convert to RGB + int GamutRegion = 0; + double *InkOutP = new double[m_nA2BnSepIn]; + //double *InkOutP = DBG_NEW double[m_nA2BnSepIn]; + for (int i = 0; i < m_nA2BnSepIn; ++i) + InkOutP[i] = outData[i]; + double *LabOutP = new double[3]; + //double *LabOutP = DBG_NEW double[3]; + 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 + 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; + } + break; + } + 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; + } + break; + //missing calculation method and pantone table, either in terms of RGB or CMY or Lab + } + + default: + { + throw std::exception(" Unsupported Color Space"); + return; + } + } + //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_ProcessRangesMaxP[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) +{ + 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); /// 100 * Volume(i) / m_maxNlPerCM(i); //Volume is in % + if (InkMax < InkP(i)) + { + InkMax = InkP(i); + MaxInd = i; + } + InkSum += InkP(i); + } + NLInkP(MaxInd) = InkSum; + 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) = Result(ind); + } + } + 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_ProcessRangesMaxP[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); + } + return; +} + +void Tango::ColorLib::ColorConverter::SetMaxNLperCM(double maxNlPerCM, int i) +{ + m_maxNlPerCM(i) = maxNlPerCM; +} + +void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(ConversionInput* conversionInput, VectorXd &Volume, VectorXd &RGBOut, VectorXd &LabOut, int &GamutRegion) +{ + SetNumberOfVolumes((int)(conversionInput->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 = conversionInput->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 = conversionInput->inputcoordinates->inputliquids[i]->calibrationdata; + SetCalibData(calibrationData, i, &m_CalibCurves[i]); + SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); + m_CalibCurves[i].SetCalibName((int)(conversionInput->inputcoordinates->inputliquids[i]->calibrationdata->liquidtype)); + } + else + std::exception("unsupported volume"); + } + } + VectorXd NLInkP((int)(m_nVolumes)); + VectorXd InkOut((int)(m_nVolumes)); + //Convert to Nonlinear Inks + double SumVol_Ink = 0.0; + for (int i = 0; i < m_nVolumes; ++i) + { + Volume(i) = conversionInput->inputcoordinates->inputliquids[i]->volume; //volume is given in % + SumVol_Ink += Volume(i); + } + for (int i = 0; i < int(conversionInput->n_processranges - 1); ++i) + { + if (SumVol_Ink > m_ProcessRangesMaxP[i]) + GamutRegion++; + } + VolumeToNLInkP(Volume, NLInkP); + double *InkOutP = new double[m_nA2BnSepIn]; + VectorToDouble(NLInkP, InkOutP); + //for (int i = 0; i < m_nA2BnSepIn; ++i) + // InkOutP[i] = NLInkP(i); + double *LinInkP = new double[m_nA2BnSepIn]; + double NormFactor =100/ m_ProcessRangesMaxP[m_nProcessRanges - 1]; + + if (conversionInput->colorspace == COLOR_SPACE__Catalog) + { + for (int i = 0; i < m_nB2AnSepOut; ++i) + { + if (NLInkP(i) <= m_ProcessRangesMaxP[0]) + { + m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]); + InkOutP[i] /= 655.35; + NLInkP(i) = InkOutP[i]; + } + + } + for (int i = 0; i < (int)(m_nVolumes); ++i) + { + if(NLInkP(i) <= m_ProcessRangesMaxP[0]) + { + m_CalibCurves[i].m_InvLinearInterp->Eval(InkOutP[i], InkOutP[i]); + NLInkP(i) = InkOutP[i]; + } + } + NLInkPToVolume(NLInkP, Volume); + } + + //Convert to RGB + //GamutRegion = 0; + //Convert to Lab + + double *LabOutP = new double[m_nA2BnSepOut]; + //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_nB2AnSepOut; ++i) + InkOutP[i] *= NormFactor; + + 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 + 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 = (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 numofInks = CountNumberofInks(conversionInput); + if (numofInks < 0) + throw std::exception("Duplicate inks"); + int expected_liquids = numofInks; + original_input_liquids_count = conversionInput->inputcoordinates->n_inputliquids; + original_input_liquids = conversionInput->inputcoordinates->inputliquids; + + InputLiquid** filteredInputLiquids = (InputLiquid**)malloc(sizeof(InputLiquid*) * expected_liquids); + + for (size_t i = 0; i < conversionInput->inputcoordinates->n_inputliquids; i++) + { + InputLiquid* liquid = conversionInput->inputcoordinates->inputliquids[i]; + + switch (liquid->liquidtype) + { + case LIQUID_TYPE__Cyan: + filteredInputLiquids[0] = liquid; + break; + case LIQUID_TYPE__Magenta: + filteredInputLiquids[1] = liquid; + break; + case LIQUID_TYPE__Yellow: + filteredInputLiquids[2] = liquid; + break; + case LIQUID_TYPE__Black: + filteredInputLiquids[3] = liquid; + break; + } + } + + conversionInput->inputcoordinates->inputliquids = filteredInputLiquids; + conversionInput->inputcoordinates->n_inputliquids = expected_liquids; + //Filter and arrange colors + + //Initialize Output... + ConversionOutput *conversionOutput = (ConversionOutput*)malloc(sizeof(ConversionOutput)); + conversion_output__init(conversionOutput); + // ConversionOutput conversionOutput = CONVERSION_OUTPUT__INIT; + + + size_t n_elements = 0; + bool InGamut = false; + m_WP.Set(0.9505, 1.00, 1.0888); //D65 + //count number if inks + // int numofInks = CountNumberofInks(conversionInput); + readColorTransformations(conversionInput); + + //read calibration tables and store them in m_CalibCurves + + readCalibrationTables(conversionInput); + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + //m_Conv02 = DBG_NEW ColorConvert(IL, IL, Y_b, L_A, sur, CS); + SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn()); + SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut()); + SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn()); + SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut()); + + SetNumberOfInks(m_nB2AnSepOut); + // Compare Strip White point to Color Table White Point + CompareWhitePoints(); + + if (numofInks != m_nB2AnSepOut) + throw std::exception("Number of available inks does not match ink tables\0"); + + //Tables have been filled + + //Convert maxInkUptake to percentages + + //m_ProcessRangesMinP = new double[m_nProcessRanges]; + m_ProcessRangesMaxP = new double[m_nProcessRanges]; + //m_ProcessRangesMinInkUptake = new double[m_nProcessRanges]; + //m_ProcessRangesMaxInkUptake = new double[m_nProcessRanges]; + for (int i = 0; i < m_nProcessRanges; ++i) + { + // m_ProcessRangesMinP[i] = 100*(conversionInput->processranges[i]->mininkuptake)/ (conversionInput->processranges[0]->mininkuptake); + m_ProcessRangesMaxP[i] = 100 * (conversionInput->processranges[i]->maxinkuptake) / (conversionInput->processranges[0]->maxinkuptake); + //m_ProcessRangesMinInkUptake[i] = conversionInput->processranges[i]->mininkuptake; + //m_ProcessRangesMaxInkUptake[i] = conversionInput->processranges[i]->maxinkuptake; + } + + VectorXd InkOut(m_nB2AnSepOut); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nB2AnSepOut); + VectorXd Volume(m_nB2AnSepOut); + VectorXd VolumeOut(m_nB2AnSepOut); + //set maxNlPerCM + VectorXd NlperCM(m_nB2AnSepOut); + NlperCM.setZero(); + m_maxNlPerCM = NlperCM; + for (int i = 0; i < m_nB2AnSepOut; ++i) + SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i); + m_nVolumes = m_nB2AnSepOut; + int GamutRegion = 0; + //Convert input data to linear inks + if (conversionInput->colorspace == COLOR_SPACE__Volume || conversionInput->colorspace == COLOR_SPACE__Catalog) + { + ConvertVolumeToRGBDisplay(conversionInput, Volume, RGBOut, LabOut, GamutRegion); + InGamut = true; + } + else + { + ConvertColorToLinearInks(conversionInput, InkOut, RGBOut, LabOut, GamutRegion, InGamut); + //Inks are in Linear Space , convert to nonlinear by using Calibration Tables, + // Right now calibration is in the [0-100] range, values exceeding [0-100] are not transformed + ConvertToNLInks(InkOut, NLInkOut); + //Determine Gamut Region + double maxNLInk = -10; + for (int i = 0; i < m_nInks; ++i) + maxNLInk = std::max(NLInkOut[i], maxNLInk); + + for (int i = 0; i < int(conversionInput->n_processranges - 1); ++i) + { + if (maxNLInk > m_ProcessRangesMaxP[i]) + GamutRegion++; + } + //Convert to [nl/cm] + NLInkPToVolume(NLInkOut, Volume); + //OutputCoordinates outputCoords = OUTPUT_COORDINATES__INIT; + } + OutputCoordinates *outputCoords = (OutputCoordinates*)malloc(sizeof(OutputCoordinates)); + output_coordinates__init(outputCoords); + fillRGB(outputCoords, RGBOut); + fillLab(outputCoords, LabOut); + outputCoords->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); + +#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_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_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); +} + + +Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(ConversionInput* conversionInput, int &bytesread) +{ + //CT_Header *Header = new CT_Header; + //CT_Header *Header = DBG_NEW CT_Header; + CT_Header Header; + + // unsigned int tmp = (buffer[2 * i + 1] << 8) | buffer[2 * i]; + uint8_t *ColorTable = conversionInput->forwarddata.data; + //File Size + NumConversions Conv; + Header.TblSIze = Conv.ByteToInt(ColorTable, bytesread); + bytesread = 4; + uint8_t versionBCT[2]; + versionBCT[0] = (unsigned int)ColorTable[bytesread]; + bytesread += 1; + versionBCT[1] = (unsigned int)ColorTable[bytesread]; + + Header.Version[0] = versionBCT[0]; + Header.Version[1] = versionBCT[1] << 4; + Header.Version[2] = versionBCT[1] & 15; + bytesread += 1; + uint32_t tmp = Conv.ByteToInt(ColorTable, bytesread); + int n = sizeof((char*)&tmp); + //char *tmpC = DBG_NEW char[n]; + char *tmpC = new char[n]; + Conv.getchar(tmp, n, tmpC); + //Header.ColorSpace = DBG_NEW char[n]; + Header.ColorSpace = new char[n]; + memcpy_s(Header.ColorSpace, n + 1, tmpC, n); + + // strncpy_s(Header->ColorSpace, n+1, tmpC, n); + //Header->ColorSpace = tmpC; + bytesread += 4; + tmp = Conv.ByteToInt(ColorTable, bytesread); + Conv.getchar(tmp, n, tmpC); + //Header.ConnectionSpace = DBG_NEW char[n]; + Header.ConnectionSpace = new char[n]; + memcpy_s(Header.ConnectionSpace, n + 1, tmpC, n); + + bytesread += 4; + + bytesread += 12; + tmp = Conv.ByteToInt(ColorTable, bytesread); + Conv.getchar(tmp, n, tmpC); + //Header.DeviceManufacturer = DBG_NEW char[n]; + Header.DeviceManufacturer = new char[n]; + memcpy_s(Header.DeviceManufacturer, n + 1, tmpC, n); +// strncpy_s(Header->DeviceManufacturer, n + 1, tmpC, n); + //Header->DeviceManufacturer = tmpC; + if (tmpC != NULL) + { + delete[]tmpC; + tmpC = NULL; + } + + bytesread += 4; + //read illuminant + double xyz[3]; + for (int j = 0; j < 3; ++j) + { + tmp = Conv.ByteToInt(ColorTable, bytesread); + xyz[j] = (double)(tmp) / 65536; + bytesread += 4; + } + Header.Illuminant.Set(xyz[0], xyz[1], xyz[2]); + //Read Number of Gamut Regions and Max Limits per Region + Header.nGamutRegions = ColorTable[bytesread]; + bytesread++; + Header.GRegMaxLim = new double[Header.nGamutRegions]; + for (int i = 0; i < Header.nGamutRegions; ++i) + { + tmp = Conv.ByteToShort(ColorTable, bytesread); + bytesread +=2; + Header.GRegMaxLim[i] = (double)tmp; + } + + if (bytesread < 128) + { + bytesread = 128; + return(Header); + } + else + { + throw std::exception("could not read Color table Header"); + } +} + +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::read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *XYZ, ConversionInput* conversionInput) +{ + // 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 = &(conversionInput->forwarddata.data[offset]); + NumConversions Conv; + int bytesread = 0; + int tmpxyz = Conv.ByteToInt(buff, bytesread); + + int n = sizeof(tmpxyz); + //char* tmpC = DBG_NEW char[n]; + char* tmpC = new char[n]; + Conv.getchar(tmpxyz, n, tmpC); + + char *xyztype = new char[n + 1]; + //char *xyztype = DBG_NEW char[n + 1]; + strncpy_s(xyztype, n + 1, tmpC, n); + if (strncmp(xyztype, "XYZ ", n) != 0) + { + throw std::exception("Wrong Tag Type"); + return; + } + if (xyztype != NULL) + { + delete[] xyztype; + xyztype = NULL; + } + if (tmpC != NULL) + { + delete[] tmpC; + tmpC = NULL; + } + 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 Tango::ColorLib::ColorConverter::read_text_type(int offset, int data_size, std::string *textstr, + ConversionInput* conversionInput) +{ + // 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 = &(conversionInput->forwarddata.data[offset]); + int bytesread = 0; + NumConversions Conv; + int tmp = Conv.ByteToInt(buff, bytesread); + int n = sizeof((char*)&tmp); + //char *tmpC = DBG_NEW char[n]; + char *tmpC = new char[n]; + Conv.getchar(tmp, n, tmpC); + char *tagtype = new char[n + 1]; + //char *tagtype = DBG_NEW char[n + 1]; + strncpy_s(tagtype, n + 1, tmpC, n); + if (strcmp(tagtype, "text") != 0) + { + throw std::exception("invalid Tag Name"); + strstr << ""; + *textstr = strstr.str(); + return; + } + if (tagtype != NULL) + { + delete[] tagtype; + tagtype = NULL; + } + if (tmpC != NULL) + { + delete[]tmpC; + tmpC = NULL; + } + bytesread += 8; + uint8_t tmp1; + for (int i = bytesread; i < data_size; ++i) + { + tmp1 = buff[i]; + strstr.put(tmp1); + } + *textstr = strstr.str(); + return; +} + + +void Tango::ColorLib::ColorConverter::read_text_description_type(int offset, int data_size, std::string textdescstr, + ConversionInput* conversionInput) +{ + // 0 - 3 'desc' + // 4 - 7 reserved, must be 0 + // 8 - 11 ASCII invariant description count, including terminating NULL + // 12 - ASCII invariant description + + uint8_t *buff = &(conversionInput->forwarddata.data[offset]); + int bytesread = 0; + NumConversions Conv; + int tmp = Conv.ByteToInt(buff, bytesread); + int n = sizeof((char*)&tmp); + //char *tmpC= DBG_NEW char[n]; + char *tmpC = new char[n]; + Conv.getchar(tmp, n, tmpC); + char *tagtype = new char[n + 1]; + //char *tagtype = DBG_NEW char[n + 1]; + strncpy_s(tagtype, n + 1, tmpC, n); + std::stringstream strstr; + if (strcmp(tagtype, "desc") != 0) + { + throw std::exception("invalid Tag Name"); + strstr << ""; + textdescstr = strstr.str(); + return; + } + if (tagtype != NULL) + { + delete[] tagtype; + tagtype = NULL; + } + if (tmpC != NULL) + { + delete[]tmpC; + tmpC = NULL; + } + 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 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()) + m_AdaptWP = false; + return; +} + +//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 + + readCalibrationTables(conversionInput); + + //Initialize CIECAM02 transformation + Illum IL = D65; + SURROUND sur = average; + CAM02CS CS = UCS; + m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS); + //m_Conv02 = DBG_NEW ColorConvert(IL, IL, Y_b, L_A, sur, CS); + SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn()); + SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut()); + SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn()); + SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut()); + SetNumberOfInks(m_nB2AnSepOut); + + // Compare Strip White point to Color Table White Point + CompareWhitePoints(); + + if (numofInks != m_nB2AnSepOut) + throw std::exception("Number of available inks does not match ink tables"); + + VectorXd InkOut(m_nB2AnSepOut); + VectorXd RGBOut(3); + VectorXd LabOut(3); + VectorXd NLInkOut(m_nB2AnSepOut); + VectorXd Volume(m_nB2AnSepOut); + + C_RGB_XYZ_Lab DataLab; + //SURROUND sur = m_Conv02->getSurround(); + switch (conversionInput->colorspace) + { + case (COLOR_SPACE__RGB): + { + // Basic assumption: if data is given in RGB space, conversion should be in relative colorimetric, + //We expect that [255,255,255](white) will be mapped to the thread white, meaning all inks should be zero + // and the coverted RGB will refect the color of the thread + //The workflow is a follows: + //1. Convert RGB to Lab (Whitepoint is D65, same as tables) + //2.Fiond if Lab is InGamut + + RGBOut(0) = conversionInput->inputcoordinates->red; + RGBOut(1) = conversionInput->inputcoordinates->green; + RGBOut(2) = conversionInput->inputcoordinates->blue; + //convert to Lab + ColorConvert CConvertD65(D65, D65); //Destination, source + //double *LabIn = DBG_NEW double[3]; + //double *RGBOutP = DBG_NEW double[3]; + double *LabIn = new double[3]; + double *RGBOutP = new double[3]; + VectorToDouble(RGBOut, RGBOutP); + //RGB to Lab + CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65 + + //Is In Gamut? + InGamut = IsInGamut(LabIn, sur, 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 + //Check if Color Tables and Strip whitepoints are the same, otherwise convert + if (m_AdaptWP) + { + CConvertD65.ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables + } + double *LabInFinal2 = new double[3]; + //double *LabInFinal2 = DBG_NEW double[3]; + CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //to Relative + InGamut = IsInGamut(LabInFinal2, sur, CS, LabInFinal2); + LimitLab(LabInFinal2); + + if (LabIn != NULL) + { + delete[] LabIn; + LabIn = NULL; + } + if (LabInFinal1 != NULL) + { + delete[]LabInFinal1; + LabInFinal1 = NULL; + } + if (LabInFinal2 != NULL) + { + delete[]LabInFinal2; + LabInFinal2 = NULL; + } + break; + } + 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); +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.h new file mode 100644 index 000000000..8b354f42a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ColorConverter.h @@ -0,0 +1,138 @@ +#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 "GBD.h" +#include "ConversionOutput.pb-c.h" +#include "CalibrationData.pb-c.h" +#include "ConversionInput.pb-c.h" +#include "Interp.h" +#include "Curves.h" + +#pragma once +namespace Tango +{ + typedef struct + { + unsigned int TblSIze = 0; + unsigned int Version[3] = { 0,0,0 }; + char * ColorSpace; + char * ConnectionSpace; + char * DeviceManufacturer; + C_RGB_XYZ_Lab Illuminant; + unsigned char nGamutRegions=0; + double *GRegMaxLim; + } CT_Header; + + typedef enum { + XYZ, + Lab, + CMY, + CMYK + }ColorSpace; + + typedef enum { + A2B, + B2A, + cprt, + gbd, + wtpt, + desc, + lcrv +// GReg + }TagList; + + 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(ConversionInput* conversionInput, VectorXd &InkOut, VectorXd &RGBOut, VectorXd &LabOut, + int &GamutRegion, bool &InGamut); + void ConvertVolumeToRGBDisplay(ConversionInput* conversionInput, VectorXd &InkOut, VectorXd &RGBOut, + VectorXd &LabOut, int &GamutRegion); + size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer); + 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: + ColorTransf *m_B2ATransform; + ColorTransf *m_A2BTransform; +// ColorTransf *m_GRegTransform; + GBD *m_GBD; + Curves *m_LinCurves; + ColorConvert *m_Conv02; +// Interp *m_LinInterp; +// Interp *m_InvLinInterp; + C_RGB_XYZ_Lab m_whitepointLab; + C_RGB_XYZ_Lab m_whitepointXYZ_Strip; + C_RGB_XYZ_Lab m_whitepointXYZ_CT; + void LimitLab(double* LabIn); + int m_nGamutRegions; + double *m_GamutRegionMaxLim; + int m_nB2AnSepIn; + int m_nB2AnSepOut; + int m_nA2BnSepIn; + int m_nA2BnSepOut; + bool m_AdaptWP; + CalibData *m_CalibCurves; + int m_nInks; + int m_nVolumes; + int m_nProcessRanges; + //double *m_ProcessRangesMinP; + double *m_ProcessRangesMaxP; + //double *m_ProcessRangesMaxInkUptake; + //double *m_ProcessRangesMinInkUptake; + C_RGB_XYZ_Lab m_WP; + VectorXd m_maxNlPerCM; + void SetnB2AnSepIn(int nB2AnSepIn) { m_nB2AnSepIn = nB2AnSepIn; }; + void SetnB2AnSepOut(int nB2AnSepOut) { m_nB2AnSepOut = nB2AnSepOut; }; + void SetnA2BnSepIn(int nA2BnSepIn) { m_nA2BnSepIn = nA2BnSepIn; }; + void SetnA2BnSepOut(int nA2BnSepOut) { m_nA2BnSepOut = nA2BnSepOut; }; + void SetnGamutRegions(int nGamutRegions) { m_nGamutRegions = nGamutRegions; }; + void readColorTransformations(ConversionInput* conversionInput); + void readCalibrationTables(ConversionInput* conversionInput); + void SetCalibData(CalibrationData* calibrationData, int i, CalibData *tmpCurve); + void SetNumberofInks(int nInks) { m_nInks = nInks; }; + void SetNumberOfVolumes(int nVol) { m_nVolumes = nVol; }; + void SetNumberOfInks(int nInks) { m_nInks = nInks; }; + // void InitInterpolations(int numofInks, Interp *linearInterp, Interp *InvLinearInterp); + void fillRGB(OutputCoordinates *outputCoords, VectorXd RGBOut); + void fillLab(OutputCoordinates *outputCoords, VectorXd LabOut); + void fillVolume(OutputCoordinates *&outputCoords, VectorXd Volume); + void ProcessHiveNeighbors(ConversionInput *conversionInput, VectorXd LabC, VectorXd RGBC, VectorXd VolumeC, + int InGamutRegion, MatrixXd &RGBOut, MatrixXd & LabOut, MatrixXd &VolumeOut, + int nHive, int *&GamutRegion, int *indDataMax); + void ArrangeHiveData(MatrixXd LabHive, MatrixXd RGBTmpVec, MatrixXd VolumeHive, int *GamutRegion, + VectorXd xpos, VectorXd ypos, int nHive, MatrixXd &OLabHive, + MatrixXd &ORGBHive, MatrixXd &OVolumeHive, int *&OGamutRegion); + void FindTriplet(VectorXd Lab, MatrixXd Lab1, int nHive, int*indDataMax); + int CountNumberofInks(ConversionInput* conversionInput); + void VectorToDouble(VectorXd Vec, double *doub); + VectorXd DoubleToVector(double *doub, int nSize); + void CompareWhitePoints(); + bool IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord); + CT_Header read_header(ConversionInput* conversionInput, int &bytesread); + void read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput); + void read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *xyz, ConversionInput* conversionInput); + void read_text_type(int offset, int data_size, std::string *textstr, + ConversionInput* conversionInput); + void read_text_description_type(int offset, int data_size, std::string textdescstr, + ConversionInput* conversionInput); + }; + } +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.cpp new file mode 100644 index 000000000..b3f111455 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.cpp @@ -0,0 +1,36 @@ +#include +#include "Exports.h" +#include "ColorConverter.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); +} + diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Exports.h new file mode 100644 index 000000000..3f386f303 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/CalibrationData.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationData.pb-c.c new file mode 100644 index 000000000..981988d99 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/CalibrationData.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationData.pb-c.h new file mode 100644 index 000000000..ccecc327e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/CalibrationPoint.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationPoint.pb-c.c new file mode 100644 index 000000000..691a97ea6 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/CalibrationPoint.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/CalibrationPoint.pb-c.h new file mode 100644 index 000000000..a58bc1ec6 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/ColorSpace.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ColorSpace.pb-c.c new file mode 100644 index 000000000..8ea22ca90 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/ColorSpace.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ColorSpace.pb-c.h new file mode 100644 index 000000000..defb93aa2 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/ConversionInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionInput.pb-c.c new file mode 100644 index 000000000..3c1230489 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionInput.pb-c.c @@ -0,0 +1,235 @@ +/* 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[12] = +{ + { + "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 */ + }, +}; +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 */ + 11, /* field[11] = GenerateHive */ + 4, /* field[4] = InputCoordinates */ + 6, /* field[6] = InverseData */ + 10, /* field[10] = ProcessRanges */ + 7, /* field[7] = SegmentLength */ + 1, /* field[1] = ThreadA */ + 2, /* field[2] = ThreadB */ + 0, /* field[0] = ThreadL */ +}; +static const ProtobufCIntRange conversion_input__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 12 } +}; +const ProtobufCMessageDescriptor conversion_input__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "ConversionInput", + "ConversionInput", + "ConversionInput", + "", + sizeof(ConversionInput), + 12, + 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_v3/PMR/ColorLab/ConversionInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionInput.pb-c.h new file mode 100644 index 000000000..15c30fc10 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionInput.pb-c.h @@ -0,0 +1,96 @@ +/* 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; +}; +#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 } + + +/* 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_v3/PMR/ColorLab/ConversionOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionOutput.pb-c.c new file mode 100644 index 000000000..da44f28ac --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/ConversionOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ConversionOutput.pb-c.h new file mode 100644 index 000000000..c85c11bd7 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/GradientConversionInput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionInput.pb-c.c new file mode 100644 index 000000000..4de650d37 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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 */ + }, + { + "DeltaChroma", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientConversionInput, has_deltachroma), + offsetof(GradientConversionInput, deltachroma), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "DeltaL", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_DOUBLE, + offsetof(GradientConversionInput, has_deltal), + offsetof(GradientConversionInput, deltal), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Colors", + 8, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientConversionInput, n_colors), + offsetof(GradientConversionInput, colors), + &input_rgb__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "InputLiquids", + 9, + 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", + 10, + 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 */ + }, +}; +static const unsigned gradient_conversion_input__field_indices_by_name[] = { + 7, /* field[7] = Colors */ + 5, /* field[5] = DeltaChroma */ + 6, /* field[6] = DeltaL */ + 3, /* field[3] = ForwardData */ + 8, /* field[8] = InputLiquids */ + 9, /* field[9] = ProcessRanges */ + 4, /* field[4] = SegmentLength */ + 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_v3/PMR/ColorLab/GradientConversionInput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionInput.pb-c.h new file mode 100644 index 000000000..1de2b2aec --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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 "InputRGB.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; + protobuf_c_boolean has_deltachroma; + double deltachroma; + protobuf_c_boolean has_deltal; + double deltal; + size_t n_colors; + InputRGB **colors; + size_t n_inputliquids; + InputLiquid **inputliquids; + size_t n_processranges; + ProcessRange **processranges; +}; +#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, 0, 0, 0, 0,NULL, 0,NULL, 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_v3/PMR/ColorLab/GradientConversionOutput.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionOutput.pb-c.c new file mode 100644 index 000000000..cd5f260ef --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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] = +{ + { + "Coordinates", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(GradientConversionOutput, n_coordinates), + offsetof(GradientConversionOutput, coordinates), + &output_coordinates__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[] = { + 0, /* field[0] = Coordinates */ + 2, /* field[2] = ErrorMessage */ + 1, /* field[1] = HasError */ +}; +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_v3/PMR/ColorLab/GradientConversionOutput.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/GradientConversionOutput.pb-c.h new file mode 100644 index 000000000..f3471b0f1 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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 "OutputCoordinates.pb-c.h" + +typedef struct _GradientConversionOutput GradientConversionOutput; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _GradientConversionOutput +{ + ProtobufCMessage base; + size_t n_coordinates; + OutputCoordinates **coordinates; + 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_v3/PMR/ColorLab/InputCoordinates.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputCoordinates.pb-c.c new file mode 100644 index 000000000..a12759a89 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/InputCoordinates.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputCoordinates.pb-c.h new file mode 100644 index 000000000..0b159cd59 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/InputLiquid.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputLiquid.pb-c.c new file mode 100644 index 000000000..2d033e2a1 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/InputLiquid.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputLiquid.pb-c.h new file mode 100644 index 000000000..c2a47b166 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/InputRGB.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.c new file mode 100644 index 000000000..42df1977b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.c @@ -0,0 +1,118 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: InputRGB.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "InputRGB.pb-c.h" +void input_rgb__init + (InputRGB *message) +{ + static const InputRGB init_value = INPUT_RGB__INIT; + *message = init_value; +} +size_t input_rgb__get_packed_size + (const InputRGB *message) +{ + assert(message->base.descriptor == &input_rgb__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t input_rgb__pack + (const InputRGB *message, + uint8_t *out) +{ + assert(message->base.descriptor == &input_rgb__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t input_rgb__pack_to_buffer + (const InputRGB *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &input_rgb__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +InputRGB * + input_rgb__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (InputRGB *) + protobuf_c_message_unpack (&input_rgb__descriptor, + allocator, len, data); +} +void input_rgb__free_unpacked + (InputRGB *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &input_rgb__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor input_rgb__field_descriptors[3] = +{ + { + "Red", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputRGB, has_red), + offsetof(InputRGB, red), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Green", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputRGB, has_green), + offsetof(InputRGB, green), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "Blue", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_INT32, + offsetof(InputRGB, has_blue), + offsetof(InputRGB, blue), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned input_rgb__field_indices_by_name[] = { + 2, /* field[2] = Blue */ + 1, /* field[1] = Green */ + 0, /* field[0] = Red */ +}; +static const ProtobufCIntRange input_rgb__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor input_rgb__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "InputRGB", + "InputRGB", + "InputRGB", + "", + sizeof(InputRGB), + 3, + input_rgb__field_descriptors, + input_rgb__field_indices_by_name, + 1, input_rgb__number_ranges, + (ProtobufCMessageInit) input_rgb__init, + NULL,NULL,NULL /* reserved[123] */ +}; diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.h new file mode 100644 index 000000000..841071716 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/InputRGB.pb-c.h @@ -0,0 +1,76 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: InputRGB.proto */ + +#ifndef PROTOBUF_C_InputRGB_2eproto__INCLUDED +#define PROTOBUF_C_InputRGB_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 _InputRGB InputRGB; + + +/* --- enums --- */ + + +/* --- messages --- */ + +struct _InputRGB +{ + 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; +}; +#define INPUT_RGB__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&input_rgb__descriptor) \ + , 0, 0, 0, 0, 0, 0 } + + +/* InputRGB methods */ +void input_rgb__init + (InputRGB *message); +size_t input_rgb__get_packed_size + (const InputRGB *message); +size_t input_rgb__pack + (const InputRGB *message, + uint8_t *out); +size_t input_rgb__pack_to_buffer + (const InputRGB *message, + ProtobufCBuffer *buffer); +InputRGB * + input_rgb__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void input_rgb__free_unpacked + (InputRGB *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*InputRGB_Closure) + (const InputRGB *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCMessageDescriptor input_rgb__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_InputRGB_2eproto__INCLUDED */ diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.c new file mode 100644 index 000000000..e4baae5c6 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.c @@ -0,0 +1,47 @@ +/* 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[7] = +{ + { "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 }, +}; +static const ProtobufCIntRange liquid_type__value_ranges[] = { +{0, 0},{0, 7} +}; +static const ProtobufCEnumValueIndex liquid_type__enum_values_by_name[7] = +{ + { "Black", 3 }, + { "Cleaner", 6 }, + { "Cyan", 0 }, + { "Lubricant", 5 }, + { "Magenta", 1 }, + { "TransparentInk", 4 }, + { "Yellow", 2 }, +}; +const ProtobufCEnumDescriptor liquid_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "LiquidType", + "LiquidType", + "LiquidType", + "", + 7, + liquid_type__enum_values_by_number, + 7, + 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_v3/PMR/ColorLab/LiquidType.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.h new file mode 100644 index 000000000..da9ec1c60 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/LiquidType.pb-c.h @@ -0,0 +1,48 @@ +/* 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 + 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_v3/PMR/ColorLab/OutputCoordinates.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputCoordinates.pb-c.c new file mode 100644 index 000000000..85aeb6ee5 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/OutputCoordinates.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputCoordinates.pb-c.h new file mode 100644 index 000000000..749ba3e7b --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/OutputLiquid.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputLiquid.pb-c.c new file mode 100644 index 000000000..73f47bb20 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/OutputLiquid.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/OutputLiquid.pb-c.h new file mode 100644 index 000000000..5401b8114 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/ProcessRange.pb-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ProcessRange.pb-c.c new file mode 100644 index 000000000..f1caa25dc --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/PMR/ColorLab/ProcessRange.pb-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/PMR/ColorLab/ProcessRange.pb-c.h new file mode 100644 index 000000000..c7eedfd8a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/ReadMe.txt b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/ReadMe.txt new file mode 100644 index 000000000..d9b08497d --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/Tango.ColorLib_v3.vcxproj b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj new file mode 100644 index 000000000..627d41f38 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj @@ -0,0 +1,230 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A} + 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_v3/Tango.ColorLib_v3.vcxproj.filters b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj.filters new file mode 100644 index 000000000..28b3791ca --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Tango.ColorLib_v3.vcxproj.filters @@ -0,0 +1,198 @@ + + + + + {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 + + + 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 + + + Header Files + + + Header Files + + + + + 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 + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.cpp new file mode 100644 index 000000000..10d7aa243 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.cpp @@ -0,0 +1,183 @@ +#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) +{ +} + + + +// 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_v3/Utils/C_RGB_XYZ_Lab.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.h new file mode 100644 index 000000000..875adc84c --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/C_RGB_XYZ_Lab.h @@ -0,0 +1,47 @@ +#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(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_v3/Utils/CalibData.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.cpp new file mode 100644 index 000000000..5bc16221e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.cpp @@ -0,0 +1,72 @@ +#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) +{ + 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); +} \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.h new file mode 100644 index 000000000..f0c4b5a45 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/CalibData.h @@ -0,0 +1,32 @@ +#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 *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_v3/Utils/ColorConvert.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.cpp new file mode 100644 index 000000000..a0d773aee --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.cpp @@ -0,0 +1,1166 @@ +#include "ColorConvert.h" +#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 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)); + } + + 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(); + } + + 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); + } + + 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(); + } + + 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::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(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(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(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; + } \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.h new file mode 100644 index 000000000..aa1b323b1 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorConvert.h @@ -0,0 +1,131 @@ + +#ifndef __COLORCONVERT_H__ +#define __COLORCONVERT_H__ + +#include "C_RGB_XYZ_Lab.h" +#include "Dense" + +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); + void LabtoRGB(double*InLab, double* OutRGB ); + void ChangeWP(double *LabIn, double *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 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 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_v3/Utils/ColorTransf.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.cpp new file mode 100644 index 000000000..ae84c984d --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.cpp @@ -0,0 +1,521 @@ +#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) + { + + } + + 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::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((char*)&tmpB); + //char *tmpC = DBG_NEW char[n] ; + char *tmpC = new char[n]; + Conv.getchar(tmpB, n, tmpC); + char *luttype = new char[n+1]; + //char *luttype = DBG_NEW char[n + 1]; + strncpy_s(luttype, n+1,tmpC, n); + int TablePrecision; + if (strncmp(luttype, "prc1",n)==0) + TablePrecision = 1; + else if (strncmp(luttype, "prc2",n)==0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in Color Tables"); + return; + } + if (luttype != NULL) + { + delete[] luttype; + luttype = NULL; + } + if (tmpC != NULL) + { + delete[] tmpC; + tmpC = NULL; + } + + // 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); + 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; + m_ByteBuffer = new unsigned char[clut_size]; + int lSizeperSep = clut_size / m_SeparationsOut; + int indR = 0; + for (int i = 0; i < lSizeperSep; ++i) + { + for (int j = 0; j < m_SeparationsOut; ++j) + { + //m_ByteBuffer[indR] = Conv.ByteToShort(buffer, bytesread); + m_ByteBuffer[indR] = buffer[bytesread]; + bytesread += 1; + indR++; + } + } + m_InterpColor.InitData(m_ByteBuffer, m_SeparationsIn, m_SeparationsOut, m_nGridPoints, m_MSBShift); + } + else + { +// int lsizeH4 = (lSize - bytesread + 1) / 2; + m_DataBuffer = new unsigned short[clut_size]; + //m_DataBuffer = DBG_NEW unsigned short[lsizeH4]; + int lSizeperSep = clut_size / m_SeparationsOut; + int indR = 0; + for (int i = 0; i < lSizeperSep; ++i) + { + for (int j = 0; j < m_SeparationsOut; ++j) + { + m_DataBuffer[indR] = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + indR++; + } + } + // terminate reading data file + m_InterpColor.InitData(m_DataBuffer, m_SeparationsIn, m_SeparationsOut, m_nGridPoints, m_MSBShift); + } + + //Read Output Curves + double *xOut = new double[m_num_output_table_entries]; + double *yOut = new double[m_num_output_table_entries]; + m_OutputCurves = new Interp[m_SeparationsOut]; + //read Input tables + if (TablePrecision == 1) + { + 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]; + 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; +} + + +/* __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_v3/Utils/ColorTransf.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.h new file mode 100644 index 000000000..963b63deb --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/ColorTransf.h @@ -0,0 +1,53 @@ +#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 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; + + 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_v3/Utils/Curves.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Curves.cpp new file mode 100644 index 000000000..e6722a582 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Curves.cpp @@ -0,0 +1,154 @@ +#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) +{ + +} + +Curves::~Curves() +{ + if (m_InterpCurves != NULL) + { + delete[] m_InterpCurves; + m_InterpCurves = NULL; + } + +} + +void Curves::InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize) +{ + // 0-3 prec + //4-7 reserved, must be 0 + // 8-9 number of channels, uint8 + // 10-11 number of entry points, uint16 + // 12-n data + + if (colorTransformFileSize < 32) + { + throw std::exception("Init Curves, invalid size"); + } + + // Check for signature + unsigned char *buffer = colorTransformBuffer; + if (buffer == NULL) + { + throw std::exception("Memory Error, ColorTransf::InitData"); + } + NumConversions Conv; + + int bytesread = 0; + int tmpB = Conv.ByteToInt(buffer, 0); + bytesread += 4; + + int n = sizeof((char*)&tmpB); + //char *tmpC = DBG_NEW char[n] ; + char *tmpC = new char[n]; + Conv.getchar(tmpB, n, tmpC); + char *Curvetype = new char[n + 1]; + //char *luttype = DBG_NEW char[n + 1]; + strncpy_s(Curvetype, n + 1, tmpC, n); + int TablePrecision; + if (strncmp(Curvetype, "prc1", n) == 0) + TablePrecision = 1; + else if (strncmp(Curvetype, "prc2", n) == 0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in Color Tables"); + return; + } + if (Curvetype != NULL) + { + delete[] Curvetype; + Curvetype = NULL; + } + if (tmpC != NULL) + { + delete[] tmpC; + tmpC = NULL; + } + + // Skip past reserved padding bytes + bytesread += 4; + + uint8_t num_channels = buffer[bytesread]; + Set_nChannels((int)num_channels); //Numer of channels + bytesread += 1; + unsigned short nEntries = Conv.ByteToShort(buffer, bytesread); + bytesread += 2; + Set_nEntries((int)nEntries); + m_InterpCurves = new Interp[m_nChannels]; + + double *xIn = new double[m_nEntries]; + double *yIn = new double[m_nEntries]; + //read Input tables + if (TablePrecision == 1) + { + double deltax = 255.0 / (m_nEntries - 1); + for (int i = 0; i < m_nEntries; ++i) + xIn[i] = deltax *(double)i; + + for (int i = 0; i < m_nChannels; ++i) + { + for (int j = 0; j +#include "C_RGB_XYZ_Lab.h" +#include "Interp.h" +class Curves { +public: + Curves(); + ~Curves(); + int Get_nChannels() { return(m_nChannels); }; + int Get_nEntries() { return(m_nEntries); }; + void InitData(unsigned char* colorTransformBuffer, long colorTransformFileSize); + Interp *m_InterpCurves; +private: + int m_prec; + int m_nChannels; + int m_nEntries; + void Set_nChannels(int nChannels) { m_nChannels = nChannels; }; + void Set_nEntries(int nEntries) { m_nEntries = nEntries; }; +}; + +#endif diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/GBD.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/GBD.cpp new file mode 100644 index 000000000..05abf2335 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/GBD.cpp @@ -0,0 +1,347 @@ +#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((char*)&tmpB); + //char *tmpC = DBG_NEW char[n]; + char *tmpC = new char[n]; + Conv.getchar(tmpB, n, tmpC); + char *tableType = new char[n + 1]; + //char *tableType = DBG_NEW char[n + 1]; + strncpy_s(tableType, n + 1, tmpC, n); + + int TablePrecision; + if (strncmp(tableType, "prc1", n) == 0) + TablePrecision = 1; + else if (strncmp(tableType, "prc2", n) == 0) + TablePrecision = 2; + else + { + throw std::exception("Wrong precision in gbd tables"); + return; + } + if (tableType != NULL) + { + delete[] tableType; + tableType = NULL; + } + if (tmpC != NULL) + { + delete[] tmpC; + tmpC = NULL; + } + + + // 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; + } + m_vert0 = new double*[m_nTriangles]; + m_vert1 = new double*[m_nTriangles]; + 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_v3/Utils/GBD.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/GBD.h new file mode 100644 index 000000000..61aadf37a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/Utils/Interp.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Interp.cpp new file mode 100644 index 000000000..ba66ca114 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/Utils/Interp.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/Interp.h new file mode 100644 index 000000000..eef16546e --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/Utils/NDInterpUtils.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NDInterpUtils.cpp new file mode 100644 index 000000000..dc9c013b1 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NDInterpUtils.cpp @@ -0,0 +1,329 @@ +#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(); + m_Point = new unsigned short[m_nSeparationsIn + 1]; + m_tmpResult = new int[m_nSeparationsOut]; + //m_Point = DBG_NEW unsigned short[m_nSeparationsIn + 1]; + //m_tmpResult = DBG_NEW int[m_nSeparationsOut]; + } + + void NDInterpUtils::InitData(unsigned char *DataBuffer, int SeparationsIn, int SeparationsOut, int nGridPoints, int MSBShift) + { + SetMSBShift(MSBShift); + SetNDData((unsigned short *)DataBuffer); + SetSeparationsIn(SeparationsIn); + SetSeparationsOut(SeparationsOut); + SetNGridpoints(nGridPoints); + SetSubCubeSize(); + SetLastCubeComp(); + m_Point = new unsigned short[m_nSeparationsIn + 1]; + m_tmpResult = new int[m_nSeparationsOut]; + //m_Point = DBG_NEW unsigned short[m_nSeparationsIn + 1]; + //m_tmpResult = DBG_NEW int[m_nSeparationsOut]; + } + + NDInterpUtils::~NDInterpUtils() + { + if (m_Point != NULL) + 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_v3/Utils/NDInterpUtils.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NDInterpUtils.h new file mode 100644 index 000000000..992de082c --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/Utils/NumConversions.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.cpp new file mode 100644 index 000000000..cdbc98d00 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.cpp @@ -0,0 +1,64 @@ +#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, int &nlen, char *tmpC) +{ + char *getChar; + getChar = (char*)# + nlen = sizeof(getChar); + //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]; + } +// return(tmp); +} diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.h new file mode 100644 index 000000000..d18fd2a1c --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/Utils/NumConversions.h @@ -0,0 +1,17 @@ +#ifndef __NUMCONVER_H__ +#define __NUMCONVER_H__ +#include +#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, int &nlen, char *tmpC); + private: +}; +#endif //__NUMCONVERSIONS_H__ \ No newline at end of file diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/protobuf-c/protobuf-c.c b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/protobuf-c/protobuf-c.c new file mode 100644 index 000000000..5debac820 --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/protobuf-c/protobuf-c.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/protobuf-c/protobuf-c.h new file mode 100644 index 000000000..c8fa4fc2a --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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_v3/targetver.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/targetver.h new file mode 100644 index 000000000..87c0086de --- /dev/null +++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v3/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/Views/RmlView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlView.xaml index 50f6a6297..e34854046 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 @@ -191,7 +191,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs index 9d843369e..84c6142e1 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs @@ -4,5 +4,5 @@ using System.Runtime.InteropServices; [assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)] [assembly: AssemblyTitle("Tango - Machine Studio")] -[assembly: AssemblyVersion("4.0.31.0")] +[assembly: AssemblyVersion("4.0.32.0")] [assembly: ComVisible(false)] \ No newline at end of file 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 914f7ac2d..991eb9da6 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 @@ -351,6 +351,10 @@ Tango.ColorLib_v2.dll PreserveNewest + + Tango.ColorLib_v3.dll + PreserveNewest + TCC\benchmarks_rgb_lab.csv Always @@ -657,7 +661,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" - + \ No newline at end of file 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 a0ad5b44d..92576abde 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 @@ -335,6 +335,10 @@ Tango.ColorLib_v2.dll PreserveNewest + + Tango.ColorLib_v3.dll + PreserveNewest + @@ -575,7 +579,7 @@ if $(ConfigurationName) == Release del *.xml - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest b/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest index efc5f8179..d72e75011 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest @@ -16,7 +16,7 @@ Remove this element if your application requires this virtualization for backwards compatibility. --> - + diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index 5f764c29f..2e44863f0 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -311,6 +311,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tango.ColorLib_v1", "ColorL EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tango.ColorLib_v2", "ColorLib\Tango.ColorLib_v2\Tango.ColorLib_v2.vcxproj", "{1A3FC7FB-403C-4B3D-B705-28FCE11317DD}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tango.ColorLib_v3", "ColorLib\Tango.ColorLib_v3\Tango.ColorLib_v3.vcxproj", "{A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AppVeyor|Any CPU = AppVeyor|Any CPU @@ -5528,6 +5530,40 @@ Global {1A3FC7FB-403C-4B3D-B705-28FCE11317DD}.Release|x64.Build.0 = Release|x64 {1A3FC7FB-403C-4B3D-B705-28FCE11317DD}.Release|x86.ActiveCfg = Release|Win32 {1A3FC7FB-403C-4B3D-B705-28FCE11317DD}.Release|x86.Build.0 = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|Any CPU.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|Any CPU.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|ARM.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|ARM.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|ARM64.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|ARM64.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|x64.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|x64.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|x86.ActiveCfg = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.AppVeyor|x86.Build.0 = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|ARM.ActiveCfg = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|ARM64.ActiveCfg = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|x64.ActiveCfg = Debug|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|x64.Build.0 = Debug|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|x86.ActiveCfg = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Debug|x86.Build.0 = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|Any CPU.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|Any CPU.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|ARM.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|ARM.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|ARM64.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|ARM64.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|x64.ActiveCfg = Debug|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|x64.Build.0 = Debug|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|x86.ActiveCfg = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.DefaultBuild|x86.Build.0 = Debug|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|Any CPU.ActiveCfg = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|ARM.ActiveCfg = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|ARM64.ActiveCfg = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|x64.ActiveCfg = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|x64.Build.0 = Release|x64 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|x86.ActiveCfg = Release|Win32 + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5628,14 +5664,15 @@ Global {50119E79-5012-4B36-8438-953DD5FC06E6} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} {CF4C66B0-CD13-4D31-8133-339A01E7E6F2} = {7181F9DE-0760-46B7-AD8F-BDBCAEDEF1B7} {1A3FC7FB-403C-4B3D-B705-28FCE11317DD} = {7181F9DE-0760-46B7-AD8F-BDBCAEDEF1B7} + {A3A8ADA0-C150-4E30-A60D-11F291FDBF7A} = {7181F9DE-0760-46B7-AD8F-BDBCAEDEF1B7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - 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} + 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 EndGlobalSection EndGlobal -- cgit v1.3.1