diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml
index 6470c94..e510cff 100644
--- a/.github/workflows/dotnet-core.yml
+++ b/.github/workflows/dotnet-core.yml
@@ -1,28 +1,31 @@
-name: .NET Core
+name: CI
on:
push:
- branches: [ master ]
+ branches: [ master, develop ]
pull_request:
- branches: [ master ]
+ branches: [ master, develop ]
jobs:
- build:
-
- runs-on: ubuntu-latest
-
+ build-and-test:
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ test-framework: ['net9.0']
+ #test-framework: [ 'net8.0', 'net9.0', 'net48', 'net481' ]
steps:
- - uses: actions/checkout@v2
- - name: Setup .NET Core
- uses: actions/setup-dotnet@v1
- with:
- dotnet-version: 3.1.101
- - name: Install dependencies
- working-directory: src
- run: dotnet restore
- - name: Build
- working-directory: src
- run: dotnet build --configuration Release --no-restore
- - name: Test
- working-directory: src
- run: dotnet test --no-restore --verbosity normal
+ - uses: actions/checkout@v2
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version:
+ 9.0.x
+ - name: Install dependencies
+ working-directory: src
+ run: dotnet restore
+ - name: Build
+ working-directory: src
+ run: dotnet build --configuration Release --no-restore
+ - name: Test
+ working-directory: src
+ run: dotnet test --no-restore --verbosity normal --framework ${{ matrix.test-framework }}
diff --git a/.gitignore b/.gitignore
index 3e759b7..51db318 100644
--- a/.gitignore
+++ b/.gitignore
@@ -328,3 +328,4 @@ ASALocalRun/
# MFractors (Xamarin productivity tool) working folder
.mfractor/
+/src/ColorHashSharp.Tests/coverage.json
diff --git a/Benchmark.md b/Benchmark.md
new file mode 100644
index 0000000..55f6744
--- /dev/null
+++ b/Benchmark.md
@@ -0,0 +1,20 @@
+# ColorHashSharp Benchmark
+
+### Benchmark NET6 & NET7
+
+BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22000.1281/21H2)
+Intel Core i7-8550U CPU 1.80GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
+.NET SDK=7.0.100
+ [Host] : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 [AttachedDebugger]
+ .NET 6.0 : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2
+ .NET 7.0 : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2
+
+
+| Method | Job | Runtime | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
+|------- |--------- |--------- |---------:|----------:|----------:|---------:|------:|--------:|-------:|----------:|------------:|
+| Hsl | .NET 6.0 | .NET 6.0 | 1.289 us | 0.0292 us | 0.0789 us | 1.263 us | 1.00 | 0.00 | 0.5360 | 2.2 KB | 1.00 |
+| Rgb | .NET 6.0 | .NET 6.0 | 1.296 us | 0.0256 us | 0.0639 us | 1.280 us | 1.00 | 0.08 | 0.5360 | 2.2 KB | 1.00 |
+| Hex | .NET 6.0 | .NET 6.0 | 1.435 us | 0.0284 us | 0.0433 us | 1.432 us | 1.09 | 0.07 | 0.5741 | 2.35 KB | 1.07 |
+| Hsl | .NET 7.0 | .NET 7.0 | 1.432 us | 0.0674 us | 0.1911 us | 1.372 us | 1.12 | 0.17 | 0.5360 | 2.2 KB | 1.00 |
+| Rgb | .NET 7.0 | .NET 7.0 | 1.497 us | 0.0678 us | 0.1890 us | 1.448 us | 1.15 | 0.15 | 0.5360 | 2.2 KB | 1.00 |
+| Hex | .NET 7.0 | .NET 7.0 | 1.358 us | 0.0272 us | 0.0381 us | 1.350 us | 1.03 | 0.07 | 0.5741 | 2.35 KB | 1.07 |
\ No newline at end of file
diff --git a/Links.md b/Links.md
new file mode 100644
index 0000000..75bf708
--- /dev/null
+++ b/Links.md
@@ -0,0 +1,17 @@
+# ColorHashSharp resources links
+
+#### Links
+- [Packaging Icon within the nupkg](https://github.com/NuGet/Home/wiki/Packaging-Icon-within-the-nupkg)
+- [Supporting Multiple Target Frameworks](https://learn.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks)
+- [NuGet Package Explorer](https://apps.microsoft.com/detail/9WZDNCRDMDM3?hl=en-us&gl=AR&ocid=pdpshare)
+- [NuGet Package Explorer GitHub](https://github.com/NuGetPackageExplorer/NuGetPackageExplorer)
+
+#### Command to push a package to NuGet
+```bash
+dotnet nuget push file.nupkg -k {YOUR_API_KEY_HERE} -s https://api.nuget.org/v3/index.json
+```
+
+#### Command to pack a project
+```bash
+dotnet pack --configuration Release
+```
\ No newline at end of file
diff --git a/README.md b/README.md
index 6761901..41fa831 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,17 @@
# ColorHashSharp
Generate color based on the given string. C# port of [ColorHash Javascript Library](https://github.com/zenozeng/color-hash).
-[](https://www.nuget.org/packages/ColorHashSharp/)
-
-[](https://fernandezja.visualstudio.com/ColorHashSharp/_build/latest?definitionId=4)
+[](https://www.nuget.org/packages/ColorHashSharp/) [](https://www.nuget.org/packages/Serilog/)
+
+[](https://github.com/fernandezja/ColorHashSharp/actions/workflows/dotnet-core.yml) [](https://fernandezja.visualstudio.com/ColorHashSharp/_build/latest?definitionId=4)
+
+#### Status
+
+
+|Actions |master |develop |
+|--- |--- |--- |
+|CI |[](https://github.com/fernandezja/ColorHashSharp/actions/workflows/dotnet-core.yml) |[](https://github.com/fernandezja/ColorHashSharp/actions/workflows/dotnet-core.yml) |
+
#### Basic
diff --git a/assets/icon/ColorHashSharp-icon.png b/assets/icon/ColorHashSharp-icon.png
index b311eb8..a998d1b 100644
Binary files a/assets/icon/ColorHashSharp-icon.png and b/assets/icon/ColorHashSharp-icon.png differ
diff --git a/assets/icon/ColorHashSharp.png b/assets/icon/ColorHashSharp.png
new file mode 100644
index 0000000..b311eb8
Binary files /dev/null and b/assets/icon/ColorHashSharp.png differ
diff --git a/src/ColorHashSharp.Benchmarks/ColorHashSharp.Benchmarks.csproj b/src/ColorHashSharp.Benchmarks/ColorHashSharp.Benchmarks.csproj
new file mode 100644
index 0000000..ffaa1a7
--- /dev/null
+++ b/src/ColorHashSharp.Benchmarks/ColorHashSharp.Benchmarks.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net8.0;net9.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ColorHashSharp.Benchmarks/ColorHashSharpBenchmarks.cs b/src/ColorHashSharp.Benchmarks/ColorHashSharpBenchmarks.cs
new file mode 100644
index 0000000..6ef1e87
--- /dev/null
+++ b/src/ColorHashSharp.Benchmarks/ColorHashSharpBenchmarks.cs
@@ -0,0 +1,44 @@
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+using Fernandezja.ColorHashSharp;
+using Fernandezja.ColorHashSharp.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ColorHashSharp.Benchmarks
+{
+ [MemoryDiagnoser]
+ [SimpleJob(RuntimeMoniker.Net48)]
+ [SimpleJob(RuntimeMoniker.Net481)]
+ [SimpleJob(RuntimeMoniker.Net80, baseline: true)]
+ [SimpleJob(RuntimeMoniker.Net90)]
+ [SimpleJob(RuntimeMoniker.Net10_0)]
+ public class ColorHashSharpBenchmarks
+ {
+ private const string STRING_TO_HASH = "The Force will be with you always";
+
+ private ColorHash _colorHash = new();
+
+
+ [Benchmark(Baseline = true)]
+ public void Hsl()
+ {
+ _ = _colorHash.Hsl(STRING_TO_HASH);
+ }
+
+ [Benchmark]
+ public void Rgb()
+ {
+ _ = _colorHash.Rgb(STRING_TO_HASH);
+ }
+
+ [Benchmark]
+ public void Hex()
+ {
+ _ = _colorHash.Hex(STRING_TO_HASH);
+ }
+ }
+}
diff --git a/src/ColorHashSharp.Benchmarks/Program.cs b/src/ColorHashSharp.Benchmarks/Program.cs
new file mode 100644
index 0000000..e2e060f
--- /dev/null
+++ b/src/ColorHashSharp.Benchmarks/Program.cs
@@ -0,0 +1,8 @@
+using BenchmarkDotNet.Running;
+using ColorHashSharp.Benchmarks;
+
+Console.WriteLine("ColorHashSharp benchmarks!");
+
+_ = BenchmarkRunner.Run();
+
+Console.ReadKey();
\ No newline at end of file
diff --git a/src/ColorHashSharp.Tests/ColorHashSharp.Tests.csproj b/src/ColorHashSharp.Tests/ColorHashSharp.Tests.csproj
index 287bf41..51e27a4 100644
--- a/src/ColorHashSharp.Tests/ColorHashSharp.Tests.csproj
+++ b/src/ColorHashSharp.Tests/ColorHashSharp.Tests.csproj
@@ -1,15 +1,18 @@
- netcoreapp3.0
-
+ net9.0
false
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/src/ColorHashSharp.Tests/ColorHashTest.cs b/src/ColorHashSharp.Tests/ColorHashTest.cs
index 73a770d..914c9d4 100644
--- a/src/ColorHashSharp.Tests/ColorHashTest.cs
+++ b/src/ColorHashSharp.Tests/ColorHashTest.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
@@ -42,6 +43,53 @@ public void BuildToHsl_ShouldCreateAColorInHSL(
Assert.Equal(lExpected, result.L);
}
+
+ [Theory(DisplayName = "BuildToHsl_ShouldCreateAColorInHSLWithCustomHueOption")]
+ [InlineData("yoda", 90, 90, 0.35, 0.35)]
+ [InlineData("yoda", 270, 270, 0.35, 0.35)]
+ public void BuildToHsl_ShouldCreateAColorInHSLWithCustomHueOption(
+ string phrase, int hue,
+ int hExpected, double sExpected, double lExpected)
+ {
+ var options = new Options();
+ options.SetHue(hue);
+
+ var colorHash = new Fernandezja.ColorHashSharp.ColorHash(options);
+
+ var result = colorHash.BuildToHsl(phrase);
+
+ Assert.NotNull(result);
+ Assert.Equal(hExpected, result.H);
+ Assert.Equal(sExpected, result.S);
+ Assert.Equal(lExpected, result.L);
+
+
+ }
+
+
+
+ [Theory(DisplayName = "BuildToHsl_ShouldCreateAColorInHexWithCustomHueOption")]
+ [InlineData("yoda", 90, "59783A")]
+ [InlineData("yoda", 210, "3A5978")]
+ [InlineData("yoda", 270, "593A78")]
+ [InlineData("yoda", 360, "783A3A")]
+ public void BuildToHsl_ShouldCreateAColorInHexWithCustomHueOption(
+ string phrase, int hue, string hexExpected)
+ {
+ var options = new Options();
+ options.SetHue(hue);
+
+ var colorHash = new Fernandezja.ColorHashSharp.ColorHash(options);
+
+ var result = colorHash.BuildToHex(phrase);
+
+ Assert.NotNull(result);
+
+ Assert.Equal(hexExpected, result);
+
+
+ }
+
[Theory(DisplayName = "BuildToHex_ShouldCreateAColorInHex")]
[InlineData("yoda", "68783A")]
[InlineData("Yoda", "D279BE")]
diff --git a/src/ColorHashSharp.Tests/OptionsTest.cs b/src/ColorHashSharp.Tests/OptionsTest.cs
index 987bf71..66a7124 100644
--- a/src/ColorHashSharp.Tests/OptionsTest.cs
+++ b/src/ColorHashSharp.Tests/OptionsTest.cs
@@ -46,5 +46,61 @@ public void GetLS_ArrayValues()
}
+ [Theory(DisplayName = "SetHue_SimpleValue")]
+ [InlineData(90)]
+ [InlineData(0.35)]
+ public void SetHue_SimpleValue(int value)
+ {
+ var options = new Fernandezja.ColorHashSharp.Options();
+ options.SetHue(value);
+
+ Assert.NotNull(options.HueRanges);
+ Assert.Single(options.HueRanges);
+ Assert.Equal(value, options.HueRanges[0].Min);
+ Assert.Equal(value, options.HueRanges[0].Max);
+ }
+
+
+ [Fact(DisplayName = "SetHue_ListValues")]
+ public void SetHue_ListValues()
+ {
+ var options = new Fernandezja.ColorHashSharp.Options();
+
+ var hueValues = new List<(int Min, int Max)>();
+ hueValues.Add((90, 270));
+
+ options.SetHue(hueValues);
+
+ Assert.NotNull(options.HueRanges);
+ Assert.Single(options.HueRanges);
+ Assert.Equal(90, options.HueRanges[0].Min);
+ Assert.Equal(270, options.HueRanges[0].Max);
+ }
+
+ [Fact(DisplayName = "SetHue_ListValues2")]
+ public void SetHue_ListValues2()
+ {
+ var options = new Fernandezja.ColorHashSharp.Options();
+
+ var hueValues = new List<(int Min, int Max)>();
+ hueValues.Add((30, 90));
+ hueValues.Add((180, 210));
+ hueValues.Add((270, 285));
+
+ options.SetHue(hueValues);
+
+ Assert.NotNull(options.HueRanges);
+ Assert.Equal(3, options.HueRanges.Count);
+
+ Assert.Equal(30, options.HueRanges[0].Min);
+ Assert.Equal(90, options.HueRanges[0].Max);
+
+ Assert.Equal(180, options.HueRanges[1].Min);
+ Assert.Equal(210, options.HueRanges[1].Max);
+
+ Assert.Equal(270, options.HueRanges[2].Min);
+ Assert.Equal(285, options.HueRanges[2].Max);
+ }
+
}
}
diff --git a/src/ColorHashSharp.sln b/src/ColorHashSharp.sln
index 3c2c754..2f25105 100644
--- a/src/ColorHashSharp.sln
+++ b/src/ColorHashSharp.sln
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.168
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33103.201
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorHashSharp", "ColorHashSharp\ColorHashSharp.csproj", "{68766358-4CA1-4A57-94B9-0E1CF0F809BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorHashSharp.Tests", "ColorHashSharp.Tests\ColorHashSharp.Tests.csproj", "{2170724A-3466-4604-B243-D3B0936B44A3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorHashSharp.Benchmarks", "ColorHashSharp.Benchmarks\ColorHashSharp.Benchmarks.csproj", "{2CC808B2-AF1F-4556-B601-C755129CCEB0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
{2170724A-3466-4604-B243-D3B0936B44A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2170724A-3466-4604-B243-D3B0936B44A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2170724A-3466-4604-B243-D3B0936B44A3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2CC808B2-AF1F-4556-B601-C755129CCEB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2CC808B2-AF1F-4556-B601-C755129CCEB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2CC808B2-AF1F-4556-B601-C755129CCEB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2CC808B2-AF1F-4556-B601-C755129CCEB0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/ColorHashSharp/.editorconfig b/src/ColorHashSharp/.editorconfig
new file mode 100644
index 0000000..2a5e964
--- /dev/null
+++ b/src/ColorHashSharp/.editorconfig
@@ -0,0 +1,71 @@
+
+[*.{cs,vb}]
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+
+[*.cs]
+csharp_indent_labels = one_less_than_current
+csharp_using_directive_placement = outside_namespace:silent
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_prefer_braces = true:silent
+csharp_style_namespace_declarations = block_scoped:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_prefer_primary_constructors = true:suggestion
+csharp_prefer_system_threading_lock = true:suggestion
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
\ No newline at end of file
diff --git a/src/ColorHashSharp/ColorHash.cs b/src/ColorHashSharp/ColorHash.cs
index 99e0c63..8a85060 100644
--- a/src/ColorHashSharp/ColorHash.cs
+++ b/src/ColorHashSharp/ColorHash.cs
@@ -18,6 +18,11 @@ public ColorHash()
_options = new Options();
}
+ public ColorHash(Options options)
+ {
+ _options = options;
+ }
+
#region IColorHash
public string Build(string value)
diff --git a/src/ColorHashSharp/ColorHashSharp.csproj b/src/ColorHashSharp/ColorHashSharp.csproj
index 856f450..a0eeaf0 100644
--- a/src/ColorHashSharp/ColorHashSharp.csproj
+++ b/src/ColorHashSharp/ColorHashSharp.csproj
@@ -1,22 +1,32 @@
- netstandard2.1
+ netstandard2.0;netstandard2.1;net48;net481;net8.0;net9.0
Fernandezja.ColorHashSharp
false
- 1.0.0.0
- 1.0.0
- 1.0.0
+ 1.1.0.0
+ 1.1.0
+ 1.1.0
Generate color based on the given string
Generate color based on the given string. C# port of ColorHash Javascript Library.
Jose A. Fernandez
- https://licenses.nuget.org/MIT
+ https://licenses.nuget.org/MIT
- https://raw.githubusercontent.com/fernandezja/ColorHashSharp/master/assets/icon/ColorHashSharp-icon.png
+ ColorHashSharp-icon.png
https://github.com/fernandezja/ColorHashSharp
color hash string hsl hex hexadecimal
Generate color based on the given string. C# port of ColorHash Javascript Library. See https://github.com/fernandezja/ColorHashSharp
true
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ColorHashSharp/ColorHashSharp.nuspec b/src/ColorHashSharp/ColorHashSharp.nuspec
new file mode 100644
index 0000000..8a5372a
--- /dev/null
+++ b/src/ColorHashSharp/ColorHashSharp.nuspec
@@ -0,0 +1,27 @@
+
+
+
+ ColorHashSharp
+ 1.1.0
+ Jose A. Fernandez
+ Jose A. Fernandez
+ MIT
+ https://github.com/fernandezja/ColorHashSharp
+ ColorHashSharp-icon.png
+ false
+ Generate color based on the given string. C# port of ColorHash Javascript Library.
+ Generate color based on the given string. C# port of ColorHash Javascript Library.
+ Generate color based on the given string. C# port of ColorHash Javascript Library. See https://github.com/fernandezja/ColorHashSharp
+ color hash string hsl hex hexadecimal
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ColorHashSharp/Entities/Hue.cs b/src/ColorHashSharp/Entities/Hue.cs
index 7d44389..fa1a10f 100644
--- a/src/ColorHashSharp/Entities/Hue.cs
+++ b/src/ColorHashSharp/Entities/Hue.cs
@@ -18,6 +18,12 @@ public Hue()
Max = 360;
}
+ public Hue(int min, int max)
+ {
+ Min = min;
+ Max = max;
+ }
+
public int Min { get; set; }
public int Max { get; set; }
diff --git a/src/ColorHashSharp/Images/ColorHashSharp-icon.png b/src/ColorHashSharp/Images/ColorHashSharp-icon.png
new file mode 100644
index 0000000..a998d1b
Binary files /dev/null and b/src/ColorHashSharp/Images/ColorHashSharp-icon.png differ
diff --git a/src/ColorHashSharp/Options.cs b/src/ColorHashSharp/Options.cs
index f1bdf10..7306ece 100644
--- a/src/ColorHashSharp/Options.cs
+++ b/src/ColorHashSharp/Options.cs
@@ -1,4 +1,5 @@
-using System;
+using Fernandezja.ColorHashSharp.Entities;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
@@ -7,7 +8,9 @@ namespace Fernandezja.ColorHashSharp
{
public class Options
{
- public ArrayList HueRanges { get; set; }
+ public List HueRanges { get; set; }
+
+ //public List Hue { get; set; }
///
/// Saturation
@@ -25,7 +28,7 @@ public Options()
S = GetLS(new ArrayList() { 0.35, 0.5, 0.65 });
L = GetLS(new ArrayList() { 0.35, 0.5, 0.65 });
- HueRanges = new ArrayList();
+ HueRanges = new List();
}
@@ -61,5 +64,22 @@ internal protected ArrayList GetLS()
}
+ internal protected void SetHue(int value)
+ {
+ HueRanges = new List();
+ HueRanges.Add(new Hue(value, value));
+ }
+
+ internal protected void SetHue(List<(int Min, int Max)> values)
+ {
+ HueRanges = new List();
+
+ foreach (var value in values)
+ {
+ HueRanges.Add(new Hue(value.Min, value.Max));
+ }
+ }
+
+
}
}
diff --git a/src/ColorHashSharp/SimpleColorTransforms.cs b/src/ColorHashSharp/SimpleColorTransforms.cs
new file mode 100644
index 0000000..9cdd6d6
--- /dev/null
+++ b/src/ColorHashSharp/SimpleColorTransforms.cs
@@ -0,0 +1,396 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using SystemMath = System.Math;
+
+namespace Fernandezja.ColorHashSharp
+{
+ class SimpleColorTransforms
+ {
+ private static double tolerance
+ => 0.000000000000001;
+
+
+ ///
+ /// Defines brightness levels.
+ ///
+ public enum Brightness
+ : byte
+ {
+ Bright = 255,
+ MediumBright = 210,
+ Medium = 142,
+ Dim = 98,
+ XDim = 50
+ }
+
+
+ ///
+ /// Defines alpha levels.
+ ///
+ public enum Alpha
+ : byte
+ {
+ Opaque = 255,
+ MediumHigh = 230,
+ Medium = 175,
+ MediumLow = 142,
+ Low = 109,
+ XLow = 45
+ }
+
+
+ ///
+ /// Defines hint alpha levels.
+ ///
+ public enum HintAlpha
+ : byte
+ {
+ Low = 64,
+ XLow = 48,
+ XxLow = 32,
+ XxxLow = 16
+ }
+
+
+ ///
+ /// Specifies a mode for argb transformations.
+ ///
+ public enum ColorTransformMode
+ : byte
+ {
+ Hsl,
+ Hsb
+ }
+
+
+ ///
+ /// Converts RGB to HSL. Alpha is ignored.
+ /// Output is: { H: [0, 360], S: [0, 1], L: [0, 1] }.
+ ///
+ /// The color to convert.
+ public static double[] RgBtoHsl(Color color)
+ {
+ double h = 0D;
+ double s = 0D;
+ double l;
+
+ // normalize red, green, blue values
+ double r = color.R / 255D;
+ double g = color.G / 255D;
+ double b = color.B / 255D;
+
+ double max = SystemMath.Max(r, SystemMath.Max(g, b));
+ double min = SystemMath.Min(r, SystemMath.Min(g, b));
+
+ // hue
+ if (SystemMath.Abs(max - min) < SimpleColorTransforms.tolerance)
+ h = 0D; // undefined
+ else if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
+ && (g >= b))
+ h = (60D * (g - b)) / (max - min);
+ else if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
+ && (g < b))
+ h = ((60D * (g - b)) / (max - min)) + 360D;
+ else if (SystemMath.Abs(max - g) < SimpleColorTransforms.tolerance)
+ h = ((60D * (b - r)) / (max - min)) + 120D;
+ else if (SystemMath.Abs(max - b) < SimpleColorTransforms.tolerance)
+ h = ((60D * (r - g)) / (max - min)) + 240D;
+
+ // luminance
+ l = (max + min) / 2D;
+
+ // saturation
+ if ((SystemMath.Abs(l) < SimpleColorTransforms.tolerance)
+ || (SystemMath.Abs(max - min) < SimpleColorTransforms.tolerance))
+ s = 0D;
+ else if ((0D < l)
+ && (l <= .5D))
+ s = (max - min) / (max + min);
+ else if (l > .5D)
+ s = (max - min) / (2D - (max + min)); //(max-min > 0)?
+
+ return new[]
+ {
+ SystemMath.Max(0D, SystemMath.Min(360D, double.Parse($"{h:0.##}"))),
+ SystemMath.Max(0D, SystemMath.Min(1D, double.Parse($"{s:0.##}"))),
+ SystemMath.Max(0D, SystemMath.Min(1D, double.Parse($"{l:0.##}")))
+ };
+ }
+
+
+ ///
+ /// Converts HSL to RGB, with a specified output Alpha.
+ /// Arguments are limited to the defined range:
+ /// does not raise exceptions.
+ ///
+ /// Hue, must be in [0, 360].
+ /// Saturation, must be in [0, 1].
+ /// Luminance, must be in [0, 1].
+ /// Output Alpha, must be in [0, 255].
+ public static Color HsLtoRgb(double h, double s, double l, int a = 255)
+ {
+ h = SystemMath.Max(0D, SystemMath.Min(360D, h));
+ s = SystemMath.Max(0D, SystemMath.Min(1D, s));
+ l = SystemMath.Max(0D, SystemMath.Min(1D, l));
+ a = SystemMath.Max(0, SystemMath.Min(255, a));
+
+ // achromatic argb (gray scale)
+ if (SystemMath.Abs(s) < SimpleColorTransforms.tolerance)
+ {
+ return Color.FromArgb(
+ a,
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{l * 255D:0.00}")))),
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{l * 255D:0.00}")))),
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{l * 255D:0.00}")))));
+ }
+
+ double q = l < .5D
+ ? l * (1D + s)
+ : (l + s) - (l * s);
+ double p = (2D * l) - q;
+
+ double hk = h / 360D;
+ double[] T = new double[3];
+ T[0] = hk + (1D / 3D); // Tr
+ T[1] = hk; // Tb
+ T[2] = hk - (1D / 3D); // Tg
+
+ for (int i = 0; i < 3; i++)
+ {
+ if (T[i] < 0D)
+ T[i] += 1D;
+ if (T[i] > 1D)
+ T[i] -= 1D;
+
+ if ((T[i] * 6D) < 1D)
+ T[i] = p + ((q - p) * 6D * T[i]);
+ else if ((T[i] * 2D) < 1)
+ T[i] = q;
+ else if ((T[i] * 3D) < 2)
+ T[i] = p + ((q - p) * ((2D / 3D) - T[i]) * 6D);
+ else
+ T[i] = p;
+ }
+
+ return Color.FromArgb(
+ a,
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{T[0] * 255D:0.00}")))),
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{T[1] * 255D:0.00}")))),
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{T[2] * 255D:0.00}")))));
+ }
+
+
+ ///
+ /// Converts RGB to HSB. Alpha is ignored.
+ /// Output is: { H: [0, 360], S: [0, 1], B: [0, 1] }.
+ ///
+ /// The color to convert.
+ public static double[] RgBtoHsb(Color color)
+ {
+ // normalize red, green and blue values
+ double r = color.R / 255D;
+ double g = color.G / 255D;
+ double b = color.B / 255D;
+
+ // conversion start
+ double max = SystemMath.Max(r, SystemMath.Max(g, b));
+ double min = SystemMath.Min(r, SystemMath.Min(g, b));
+
+ double h = 0D;
+ if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
+ && (g >= b))
+ h = (60D * (g - b)) / (max - min);
+ else if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
+ && (g < b))
+ h = ((60D * (g - b)) / (max - min)) + 360D;
+ else if (SystemMath.Abs(max - g) < SimpleColorTransforms.tolerance)
+ h = ((60D * (b - r)) / (max - min)) + 120D;
+ else if (SystemMath.Abs(max - b) < SimpleColorTransforms.tolerance)
+ h = ((60D * (r - g)) / (max - min)) + 240D;
+
+ double s = SystemMath.Abs(max) < SimpleColorTransforms.tolerance
+ ? 0D
+ : 1D - (min / max);
+
+ return new[]
+ {
+ SystemMath.Max(0D, SystemMath.Min(360D, h)),
+ SystemMath.Max(0D, SystemMath.Min(1D, s)),
+ SystemMath.Max(0D, SystemMath.Min(1D, max))
+ };
+ }
+
+
+ ///
+ /// Converts HSB to RGB, with a specified output Alpha.
+ /// Arguments are limited to the defined range:
+ /// does not raise exceptions.
+ ///
+ /// Hue, must be in [0, 360].
+ /// Saturation, must be in [0, 1].
+ /// Brightness, must be in [0, 1].
+ /// Output Alpha, must be in [0, 255].
+ public static Color HsBtoRgb(double h, double s, double b, int a = 255)
+ {
+ h = SystemMath.Max(0D, SystemMath.Min(360D, h));
+ s = SystemMath.Max(0D, SystemMath.Min(1D, s));
+ b = SystemMath.Max(0D, SystemMath.Min(1D, b));
+ a = SystemMath.Max(0, SystemMath.Min(255, a));
+
+ double r = 0D;
+ double g = 0D;
+ double bl = 0D;
+
+ if (SystemMath.Abs(s) < SimpleColorTransforms.tolerance)
+ r = g = bl = b;
+ else
+ {
+ // the argb wheel consists of 6 sectors. Figure out which sector
+ // you're in.
+ double sectorPos = h / 60D;
+ int sectorNumber = (int)SystemMath.Floor(sectorPos);
+ // get the fractional part of the sector
+ double fractionalSector = sectorPos - sectorNumber;
+
+ // calculate values for the three axes of the argb.
+ double p = b * (1D - s);
+ double q = b * (1D - (s * fractionalSector));
+ double t = b * (1D - (s * (1D - fractionalSector)));
+
+ // assign the fractional colors to r, g, and b based on the sector
+ // the angle is in.
+ switch (sectorNumber)
+ {
+ case 0:
+ r = b;
+ g = t;
+ bl = p;
+ break;
+ case 1:
+ r = q;
+ g = b;
+ bl = p;
+ break;
+ case 2:
+ r = p;
+ g = b;
+ bl = t;
+ break;
+ case 3:
+ r = p;
+ g = q;
+ bl = b;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ bl = b;
+ break;
+ case 5:
+ r = b;
+ g = p;
+ bl = q;
+ break;
+ }
+ }
+
+ return Color.FromArgb(
+ a,
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{r * 255D:0.00}")))),
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{g * 255D:0.00}")))),
+ SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{bl * 250D:0.00}")))));
+ }
+
+
+ ///
+ /// Multiplies the Color's Luminance or Brightness by the argument;
+ /// and optionally specifies the output Alpha.
+ ///
+ /// The color to transform.
+ /// Transform mode.
+ /// The transformation multiplier.
+ /// Can optionally specify the Alpha to directly
+ /// set on the output. If null, then the input
+ /// Alpha is used.
+ public static Color TransformBrightness(
+ Color color,
+ ColorTransformMode colorTransformMode,
+ double brightnessTransform,
+ byte? outputAlpha = null)
+ {
+ double[] hsl = colorTransformMode == ColorTransformMode.Hsl
+ ? SimpleColorTransforms.RgBtoHsl(color)
+ : SimpleColorTransforms.RgBtoHsb(color);
+ if ((SystemMath.Abs(hsl[2]) < SimpleColorTransforms.tolerance)
+ && (brightnessTransform > 1D))
+ hsl[2] = brightnessTransform - 1D;
+ else
+ hsl[2] *= brightnessTransform;
+ return colorTransformMode == ColorTransformMode.Hsl
+ ? SimpleColorTransforms.HsLtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A)
+ : SimpleColorTransforms.HsBtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A);
+ }
+
+
+ ///
+ /// Multiplies the Color's Saturation, and Luminance or Brightness by the argument;
+ /// and optionally specifies the output Alpha.
+ ///
+ /// The color to transform.
+ /// Transform mode.
+ /// The transformation multiplier.
+ /// The transformation multiplier.
+ /// Can optionally specify the Alpha to directly
+ /// set on the output. If null, then the input
+ /// Alpha is used.
+ public static Color TransformSaturationAndBrightness(
+ Color color,
+ ColorTransformMode colorTransformMode,
+ double saturationTransform,
+ double brightnessTransform,
+ byte? outputAlpha = null)
+ {
+ double[] hsl = colorTransformMode == ColorTransformMode.Hsl
+ ? SimpleColorTransforms.RgBtoHsl(color)
+ : SimpleColorTransforms.RgBtoHsb(color);
+ if ((SystemMath.Abs(hsl[1]) < SimpleColorTransforms.tolerance)
+ && (saturationTransform > 1D))
+ hsl[1] = saturationTransform - 1D;
+ else
+ hsl[1] *= saturationTransform;
+ if ((SystemMath.Abs(hsl[2]) < SimpleColorTransforms.tolerance)
+ && (brightnessTransform > 1D))
+ hsl[2] = brightnessTransform - 1D;
+ else
+ hsl[2] *= brightnessTransform;
+ return colorTransformMode == ColorTransformMode.Hsl
+ ? SimpleColorTransforms.HsLtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A)
+ : SimpleColorTransforms.HsBtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A);
+ }
+
+
+ ///
+ /// Creates a new Color by combining R, G, and B from each Color, scaled by the Color's Alpha.
+ /// The R, G, B of each Color is scaled by the Color's Alpha. The R, G, B of both results is
+ /// then added together and divided by 2. The valuea are limited to [0, 255].
+ /// The Alpha of the output Color is specified; and is also limited to [0, 255]
+ /// (does not raise exceptions).
+ ///
+ /// Combined by scaling RGB by the A.
+ /// Combined by scaling RGB by the A.
+ /// The Alpha of the output Color.
+ public static Color AlphaCombine(Color color1, Color color2, byte outputAlpha)
+ {
+ double a1 = color1.A / 255D;
+ double a2 = color2.A / 255D;
+ return Color.FromArgb(
+ outputAlpha,
+ (byte)SystemMath.Max(0D, SystemMath.Min(255D, ((color1.R * a1) + (color2.R * a2)) * .5D)),
+ (byte)SystemMath.Max(0D, SystemMath.Min(255D, ((color1.G * a1) + (color2.G * a2)) * .5D)),
+ (byte)SystemMath.Max(0D, SystemMath.Min(255D, ((color1.B * a1) + (color2.B * a2)) * .5D)));
+ }
+
+ }
+}