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 --- .../Tango.MachineStudio.UI.csproj | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj') 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 -- 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/Tango.MachineStudio.UI.csproj') 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/Tango.MachineStudio.UI.csproj') 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