Added unit tests
This commit is contained in:
Родитель
5bb4339824
Коммит
2832f27493
|
@ -9,6 +9,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorBlender", "src\ColorBl
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorBlenderAvalonia", "src\ColorBlenderAvalonia\ColorBlenderAvalonia.csproj", "{D6EC3C00-F0B9-4531-9563-3487B7ED3512}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BE9A54A0-F80F-43A7-90F4-98A147169F9B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{D57E2975-0E47-4153-B3ED-3C4D0252EB22}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9B03B35A-F57E-4BCB-9990-36FB6D1E8787}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBlender.UnitTests", "tests\ColorBlender.UnitTests\ColorBlender.UnitTests.csproj", "{81B01D79-7142-4C77-84FC-26FAACC0D308}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -27,10 +35,20 @@ Global
|
|||
{D6EC3C00-F0B9-4531-9563-3487B7ED3512}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D6EC3C00-F0B9-4531-9563-3487B7ED3512}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D6EC3C00-F0B9-4531-9563-3487B7ED3512}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81B01D79-7142-4C77-84FC-26FAACC0D308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81B01D79-7142-4C77-84FC-26FAACC0D308}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81B01D79-7142-4C77-84FC-26FAACC0D308}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{81B01D79-7142-4C77-84FC-26FAACC0D308}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{F42E593E-39A3-4C44-A909-1AE1FEBAFA37} = {D57E2975-0E47-4153-B3ED-3C4D0252EB22}
|
||||
{B52C44BA-D099-42E8-94A7-5234E08480FD} = {BE9A54A0-F80F-43A7-90F4-98A147169F9B}
|
||||
{D6EC3C00-F0B9-4531-9563-3487B7ED3512} = {D57E2975-0E47-4153-B3ED-3C4D0252EB22}
|
||||
{81B01D79-7142-4C77-84FC-26FAACC0D308} = {9B03B35A-F57E-4BCB-9990-36FB6D1E8787}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5C5DD029-8617-4D20-829C-DA0F7E582C6E}
|
||||
EndGlobalSection
|
||||
|
|
18
README.md
18
README.md
|
@ -13,6 +13,24 @@ ColorBlender .NET version is based on sources from: http://www.colorblender.com/
|
|||
The old version of ColorBlender can be found here: http://www.colormatch5k.com/
|
||||
The new version of ColorBlender can be found here: http://www.colorexplorer.com/colormatch.aspx
|
||||
|
||||
## Algorithms
|
||||
|
||||
Color matching algorithms:
|
||||
* classic - ColorMatch 5K Classic
|
||||
* colorexplorer - ColorExplorer - "Sweet Spot Offset"
|
||||
* singlehue - Single Hue
|
||||
* complementary - Complementary
|
||||
* splitcomplementary - Split-Complementary
|
||||
* analogue - Analogue
|
||||
* triadic - Triadic
|
||||
* square - Square
|
||||
|
||||
All work is done in HSV color space, because all
|
||||
calculations are based on hue, saturation and value of the working color.
|
||||
|
||||
The hue spectrum is divided into sections, are the matching colors are
|
||||
calculated differently depending on the hue of the color.
|
||||
|
||||
## Screenshots
|
||||
|
||||
![](images/avalonia.png)
|
||||
|
|
|
@ -11,35 +11,35 @@ namespace ColorBlender.Algorithms
|
|||
Blend outp = new Blend();
|
||||
outp.Colors[0] = new HSV(hsv);
|
||||
|
||||
var w = MathHelpers.HueToWheel(hsv.h);
|
||||
var w = MathHelpers.HueToWheel(hsv.H);
|
||||
HSV z = new HSV
|
||||
{
|
||||
h = MathHelpers.WheelToHue((w + 30) % 360),
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = MathHelpers.WheelToHue((w + 30) % 360),
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
z = new HSV
|
||||
{
|
||||
h = MathHelpers.WheelToHue((w + 60) % 360),
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = MathHelpers.WheelToHue((w + 60) % 360),
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z = new HSV
|
||||
{
|
||||
s = 0,
|
||||
h = 0,
|
||||
v = 100 - hsv.v
|
||||
S = 0,
|
||||
H = 0,
|
||||
V = 100 - hsv.V
|
||||
};
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z.v = Math.Round(hsv.v * 1.3) % 100;
|
||||
z.V = Math.Round(hsv.V * 1.3) % 100;
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.v = Math.Round(hsv.v / 1.3) % 100;
|
||||
z.V = Math.Round(hsv.V / 1.3) % 100;
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -13,68 +13,68 @@ namespace ColorBlender.Algorithms
|
|||
HSV y = new HSV();
|
||||
HSV yx = new HSV();
|
||||
|
||||
y.s = hsv.s;
|
||||
y.h = hsv.h;
|
||||
if (hsv.v > 70) { y.v = hsv.v - 30; } else { y.v = hsv.v + 30; };
|
||||
y.S = hsv.S;
|
||||
y.H = hsv.H;
|
||||
if (hsv.V > 70) { y.V = hsv.V - 30; } else { y.V = hsv.V + 30; };
|
||||
outp.Colors[1] = new HSV(y);
|
||||
|
||||
if ((hsv.h >= 0) && (hsv.h < 30))
|
||||
if ((hsv.H >= 0) && (hsv.H < 30))
|
||||
{
|
||||
yx.h = y.h = hsv.h + 30; yx.s = y.s = hsv.s; y.v = hsv.v;
|
||||
if (hsv.v > 70) { yx.v = hsv.v - 30; } else { yx.v = hsv.v + 30; }
|
||||
yx.H = y.H = hsv.H + 30; yx.S = y.S = hsv.S; y.V = hsv.V;
|
||||
if (hsv.V > 70) { yx.V = hsv.V - 30; } else { yx.V = hsv.V + 30; }
|
||||
}
|
||||
|
||||
if ((hsv.h >= 30) && (hsv.h < 60))
|
||||
if ((hsv.H >= 30) && (hsv.H < 60))
|
||||
{
|
||||
yx.h = y.h = hsv.h + 150;
|
||||
y.s = MathHelpers.RC(hsv.s - 30, 100);
|
||||
y.v = MathHelpers.RC(hsv.v - 20, 100);
|
||||
yx.s = MathHelpers.RC(hsv.s - 50, 100);
|
||||
yx.v = MathHelpers.RC(hsv.v + 20, 100);
|
||||
yx.H = y.H = hsv.H + 150;
|
||||
y.S = MathHelpers.RC(hsv.S - 30, 100);
|
||||
y.V = MathHelpers.RC(hsv.V - 20, 100);
|
||||
yx.S = MathHelpers.RC(hsv.S - 50, 100);
|
||||
yx.V = MathHelpers.RC(hsv.V + 20, 100);
|
||||
}
|
||||
|
||||
if ((hsv.h >= 60) && (hsv.h < 180))
|
||||
if ((hsv.H >= 60) && (hsv.H < 180))
|
||||
{
|
||||
yx.h = y.h = hsv.h - 40;
|
||||
y.s = yx.s = hsv.s;
|
||||
y.v = hsv.v; if (hsv.v > 70) { yx.v = hsv.v - 30; } else { yx.v = hsv.v + 30; }
|
||||
yx.H = y.H = hsv.H - 40;
|
||||
y.S = yx.S = hsv.S;
|
||||
y.V = hsv.V; if (hsv.V > 70) { yx.V = hsv.V - 30; } else { yx.V = hsv.V + 30; }
|
||||
}
|
||||
|
||||
if ((hsv.h >= 180) && (hsv.h < 220))
|
||||
if ((hsv.H >= 180) && (hsv.H < 220))
|
||||
{
|
||||
yx.h = hsv.h - 170;
|
||||
y.h = hsv.h - 160;
|
||||
yx.s = y.s = hsv.s;
|
||||
y.v = hsv.v;
|
||||
if (hsv.v > 70) { yx.v = hsv.v - 30; } else { yx.v = hsv.v + 30; }
|
||||
yx.H = hsv.H - 170;
|
||||
y.H = hsv.H - 160;
|
||||
yx.S = y.S = hsv.S;
|
||||
y.V = hsv.V;
|
||||
if (hsv.V > 70) { yx.V = hsv.V - 30; } else { yx.V = hsv.V + 30; }
|
||||
|
||||
}
|
||||
if ((hsv.h >= 220) && (hsv.h < 300))
|
||||
if ((hsv.H >= 220) && (hsv.H < 300))
|
||||
{
|
||||
yx.h = y.h = hsv.h;
|
||||
yx.s = y.s = MathHelpers.RC(hsv.s - 40, 100);
|
||||
y.v = hsv.v;
|
||||
if (hsv.v > 70) { yx.v = hsv.v - 30; } else { yx.v = hsv.v + 30; }
|
||||
yx.H = y.H = hsv.H;
|
||||
yx.S = y.S = MathHelpers.RC(hsv.S - 40, 100);
|
||||
y.V = hsv.V;
|
||||
if (hsv.V > 70) { yx.V = hsv.V - 30; } else { yx.V = hsv.V + 30; }
|
||||
}
|
||||
if (hsv.h >= 300)
|
||||
if (hsv.H >= 300)
|
||||
{
|
||||
if (hsv.s > 50) { y.s = yx.s = hsv.s - 40; } else { y.s = yx.s = hsv.s + 40; }
|
||||
yx.h = y.h = (hsv.h + 20) % 360;
|
||||
y.v = hsv.v;
|
||||
if (hsv.v > 70) { yx.v = hsv.v - 30; } else { yx.v = hsv.v + 30; }
|
||||
if (hsv.S > 50) { y.S = yx.S = hsv.S - 40; } else { y.S = yx.S = hsv.S + 40; }
|
||||
yx.H = y.H = (hsv.H + 20) % 360;
|
||||
y.V = hsv.V;
|
||||
if (hsv.V > 70) { yx.V = hsv.V - 30; } else { yx.V = hsv.V + 30; }
|
||||
}
|
||||
|
||||
outp.Colors[2] = new HSV(y);
|
||||
outp.Colors[3] = new HSV(yx);
|
||||
|
||||
y.h = 0;
|
||||
y.s = 0;
|
||||
y.v = 100 - hsv.v;
|
||||
y.H = 0;
|
||||
y.S = 0;
|
||||
y.V = 100 - hsv.V;
|
||||
outp.Colors[4] = new HSV(y);
|
||||
|
||||
y.h = 0;
|
||||
y.s = 0;
|
||||
y.v = hsv.v;
|
||||
y.H = 0;
|
||||
y.S = 0;
|
||||
y.V = hsv.V;
|
||||
outp.Colors[5] = new HSV(y);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -13,29 +13,29 @@ namespace ColorBlender.Algorithms
|
|||
|
||||
HSV z = new HSV
|
||||
{
|
||||
h = hsv.h,
|
||||
s = Math.Round(hsv.s * 0.3),
|
||||
v = Math.Min(Math.Round(hsv.v * 1.3), 100)
|
||||
H = hsv.H,
|
||||
S = Math.Round(hsv.S * 0.3),
|
||||
V = Math.Min(Math.Round(hsv.V * 1.3), 100)
|
||||
};
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
z = new HSV
|
||||
{
|
||||
h = (hsv.h + 300) % 360,
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = (hsv.H + 300) % 360,
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z.s = Math.Min(Math.Round(z.s * 1.2), 100);
|
||||
z.v = Math.Min(Math.Round(z.v * 0.5), 100);
|
||||
z.S = Math.Min(Math.Round(z.S * 1.2), 100);
|
||||
z.V = Math.Min(Math.Round(z.V * 0.5), 100);
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z.s = 0;
|
||||
z.v = (hsv.v + 50) % 100;
|
||||
z.S = 0;
|
||||
z.V = (hsv.V + 50) % 100;
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.v = (z.v + 50) % 100;
|
||||
z.V = (z.V + 50) % 100;
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -13,31 +13,31 @@ namespace ColorBlender.Algorithms
|
|||
|
||||
HSV z = new HSV
|
||||
{
|
||||
h = hsv.h,
|
||||
s = (hsv.s > 50) ? (hsv.s * 0.5) : (hsv.s * 2),
|
||||
v = (hsv.v < 50) ? (Math.Min(hsv.v * 1.5, 100)) : (hsv.v / 1.5)
|
||||
H = hsv.H,
|
||||
S = (hsv.S > 50) ? (hsv.S * 0.5) : (hsv.S * 2),
|
||||
V = (hsv.V < 50) ? (Math.Min(hsv.V * 1.5, 100)) : (hsv.V / 1.5)
|
||||
};
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
var w = MathHelpers.HueToWheel(hsv.h);
|
||||
z.h = MathHelpers.WheelToHue((w + 180) % 360);
|
||||
z.s = hsv.s;
|
||||
z.v = hsv.v;
|
||||
var w = MathHelpers.HueToWheel(hsv.H);
|
||||
z.H = MathHelpers.WheelToHue((w + 180) % 360);
|
||||
z.S = hsv.S;
|
||||
z.V = hsv.V;
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z.s = (z.s > 50) ? (z.s * 0.5) : (z.s * 2);
|
||||
z.v = (z.v < 50) ? (Math.Min(z.v * 1.5, 100)) : (z.v / 1.5);
|
||||
z.S = (z.S > 50) ? (z.S * 0.5) : (z.S * 2);
|
||||
z.V = (z.V < 50) ? (Math.Min(z.V * 1.5, 100)) : (z.V / 1.5);
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z = new HSV
|
||||
{
|
||||
s = 0,
|
||||
h = 0,
|
||||
v = hsv.v
|
||||
S = 0,
|
||||
H = 0,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.v = 100 - hsv.v;
|
||||
z.V = 100 - hsv.V;
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -12,26 +12,26 @@ namespace ColorBlender.Algorithms
|
|||
|
||||
HSV z = new HSV
|
||||
{
|
||||
h = hsv.h,
|
||||
s = hsv.s,
|
||||
v = hsv.v + ((hsv.v < 50) ? 20 : -20)
|
||||
H = hsv.H,
|
||||
S = hsv.S,
|
||||
V = hsv.V + ((hsv.V < 50) ? 20 : -20)
|
||||
};
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
z.s = hsv.s;
|
||||
z.v = hsv.v + ((hsv.v < 50) ? 40 : -40);
|
||||
z.S = hsv.S;
|
||||
z.V = hsv.V + ((hsv.V < 50) ? 40 : -40);
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z.s = hsv.s + ((hsv.s < 50) ? 20 : -20);
|
||||
z.v = hsv.v;
|
||||
z.S = hsv.S + ((hsv.S < 50) ? 20 : -20);
|
||||
z.V = hsv.V;
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z.s = hsv.s + ((hsv.s < 50) ? 40 : -40);
|
||||
z.v = hsv.v;
|
||||
z.S = hsv.S + ((hsv.S < 50) ? 40 : -40);
|
||||
z.V = hsv.V;
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.s = hsv.s + ((hsv.s < 50) ? 40 : -40);
|
||||
z.v = hsv.v + ((hsv.v < 50) ? 40 : -40);
|
||||
z.S = hsv.S + ((hsv.S < 50) ? 40 : -40);
|
||||
z.V = hsv.V + ((hsv.V < 50) ? 40 : -40);
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -10,34 +10,34 @@ namespace ColorBlender.Algorithms
|
|||
Blend outp = new Blend();
|
||||
outp.Colors[0] = new HSV(hsv);
|
||||
|
||||
var w = MathHelpers.HueToWheel(hsv.h);
|
||||
var w = MathHelpers.HueToWheel(hsv.H);
|
||||
HSV z = new HSV
|
||||
{
|
||||
h = hsv.h,
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = hsv.H,
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
|
||||
z.h = MathHelpers.WheelToHue((w + 150) % 360);
|
||||
z.s = hsv.s;
|
||||
z.v = hsv.v;
|
||||
z.H = MathHelpers.WheelToHue((w + 150) % 360);
|
||||
z.S = hsv.S;
|
||||
z.V = hsv.V;
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
z.h = MathHelpers.WheelToHue((w + 210) % 360);
|
||||
z.s = hsv.s;
|
||||
z.v = hsv.v;
|
||||
z.H = MathHelpers.WheelToHue((w + 210) % 360);
|
||||
z.S = hsv.S;
|
||||
z.V = hsv.V;
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z.s = 0;
|
||||
z.v = hsv.s;
|
||||
z.S = 0;
|
||||
z.V = hsv.S;
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z.s = 0;
|
||||
z.v = hsv.v;
|
||||
z.S = 0;
|
||||
z.V = hsv.V;
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.s = 0;
|
||||
z.v = (100 - hsv.v);
|
||||
z.S = 0;
|
||||
z.V = (100 - hsv.V);
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -10,29 +10,29 @@ namespace ColorBlender.Algorithms
|
|||
Blend outp = new Blend();
|
||||
outp.Colors[0] = new HSV(hsv);
|
||||
|
||||
var w = MathHelpers.HueToWheel(hsv.h);
|
||||
var w = MathHelpers.HueToWheel(hsv.H);
|
||||
HSV z = new HSV
|
||||
{
|
||||
h = MathHelpers.WheelToHue((w + 90) % 360),
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = MathHelpers.WheelToHue((w + 90) % 360),
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
z.h = MathHelpers.WheelToHue((w + 180) % 360);
|
||||
z.s = hsv.s;
|
||||
z.v = hsv.v;
|
||||
z.H = MathHelpers.WheelToHue((w + 180) % 360);
|
||||
z.S = hsv.S;
|
||||
z.V = hsv.V;
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z.h = MathHelpers.WheelToHue((w + 270) % 360);
|
||||
z.s = hsv.s;
|
||||
z.v = hsv.v;
|
||||
z.H = MathHelpers.WheelToHue((w + 270) % 360);
|
||||
z.S = hsv.S;
|
||||
z.V = hsv.V;
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z.s = 0;
|
||||
z.S = 0;
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.v = 100 - z.v;
|
||||
z.V = 100 - z.V;
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -10,35 +10,35 @@ namespace ColorBlender.Algorithms
|
|||
Blend outp = new Blend();
|
||||
outp.Colors[0] = new HSV(hsv);
|
||||
|
||||
var w = MathHelpers.HueToWheel(hsv.h);
|
||||
var w = MathHelpers.HueToWheel(hsv.H);
|
||||
HSV z = new HSV
|
||||
{
|
||||
s = hsv.s,
|
||||
h = hsv.h,
|
||||
v = 100 - hsv.v
|
||||
S = hsv.S,
|
||||
H = hsv.H,
|
||||
V = 100 - hsv.V
|
||||
};
|
||||
outp.Colors[1] = new HSV(z);
|
||||
|
||||
z = new HSV
|
||||
{
|
||||
h = MathHelpers.WheelToHue((w + 120) % 360),
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = MathHelpers.WheelToHue((w + 120) % 360),
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[2] = new HSV(z);
|
||||
|
||||
z.v = 100 - z.v;
|
||||
z.V = 100 - z.V;
|
||||
outp.Colors[3] = new HSV(z);
|
||||
|
||||
z = new HSV
|
||||
{
|
||||
h = MathHelpers.WheelToHue((w + 240) % 360),
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = MathHelpers.WheelToHue((w + 240) % 360),
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
outp.Colors[4] = new HSV(z);
|
||||
|
||||
z.v = 100 - z.v;
|
||||
z.V = 100 - z.V;
|
||||
outp.Colors[5] = new HSV(z);
|
||||
|
||||
return outp;
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System;
|
||||
using ColorBlender.Algorithms;
|
||||
|
||||
namespace ColorBlender
|
||||
{
|
||||
// Color matching algorithms:
|
||||
// "classic" ColorMatch 5K Classic
|
||||
// "colorexplorer" ColorExplorer - "Sweet Spot Offset"
|
||||
// "singlehue" Single Hue
|
||||
// "complementary" Complementary
|
||||
// "splitcomplementary" Split-Complementary
|
||||
// "analogue" Analogue
|
||||
// "triadic" Triadic
|
||||
// "square" Square
|
||||
// Color matching algorithm. All work is done in HSV color space, because all
|
||||
// calculations are based on hue, saturation and value of the working color.
|
||||
// The hue spectrum is divided into sections, are the matching colors are
|
||||
// calculated differently depending on the hue of the color.
|
||||
public static class ColorMatch
|
||||
{
|
||||
public static Blend Match(HSV hs, string method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case "classic":
|
||||
return new Classic().Match(hs);
|
||||
case "colorexplorer":
|
||||
return new ColorExplorer().Match(hs);
|
||||
case "singlehue":
|
||||
return new SingleHue().Match(hs);
|
||||
case "complementary":
|
||||
return new Complementary().Match(hs);
|
||||
case "splitcomplementary":
|
||||
return new SplitComplementary().Match(hs);
|
||||
case "analogue":
|
||||
return new Analogue().Match(hs);
|
||||
case "triadic":
|
||||
return new Triadic().Match(hs);
|
||||
case "square":
|
||||
return new Square().Match(hs);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,67 +6,67 @@ namespace ColorBlender
|
|||
{
|
||||
public class HSV
|
||||
{
|
||||
public double h;
|
||||
public double s;
|
||||
public double v;
|
||||
public double H;
|
||||
public double S;
|
||||
public double V;
|
||||
|
||||
public HSV() { }
|
||||
|
||||
public HSV(double h, double s, double v)
|
||||
{
|
||||
this.h = h;
|
||||
this.s = s;
|
||||
this.v = v;
|
||||
this.H = h;
|
||||
this.S = s;
|
||||
this.V = v;
|
||||
}
|
||||
|
||||
public HSV(HSV hs)
|
||||
{
|
||||
this.h = hs.h;
|
||||
this.s = hs.s;
|
||||
this.v = hs.v;
|
||||
this.H = hs.H;
|
||||
this.S = hs.S;
|
||||
this.V = hs.V;
|
||||
}
|
||||
|
||||
public HSV(RGB rg)
|
||||
{
|
||||
HSV hs = rg.ToHSV();
|
||||
this.h = hs.h;
|
||||
this.s = hs.s;
|
||||
this.v = hs.v;
|
||||
this.H = hs.H;
|
||||
this.S = hs.S;
|
||||
this.V = hs.V;
|
||||
}
|
||||
|
||||
public RGB ToRGB()
|
||||
{
|
||||
RGB rg = new RGB();
|
||||
HSV hsx = new HSV(this.h, this.s, this.v);
|
||||
HSV hsx = new HSV(this.H, this.S, this.V);
|
||||
|
||||
if (hsx.s == 0)
|
||||
if (hsx.S == 0)
|
||||
{
|
||||
rg.r = rg.g = rg.b = Math.Round(hsx.v * 2.55); return (rg);
|
||||
rg.R = rg.G = rg.B = Math.Round(hsx.V * 2.55); return (rg);
|
||||
}
|
||||
|
||||
hsx.s = hsx.s / 100;
|
||||
hsx.v = hsx.v / 100;
|
||||
hsx.h /= 60;
|
||||
hsx.S = hsx.S / 100;
|
||||
hsx.V = hsx.V / 100;
|
||||
hsx.H /= 60;
|
||||
|
||||
var i = Math.Floor(hsx.h);
|
||||
var f = hsx.h - i;
|
||||
var p = hsx.v * (1 - hsx.s);
|
||||
var q = hsx.v * (1 - hsx.s * f);
|
||||
var t = hsx.v * (1 - hsx.s * (1 - f));
|
||||
var i = Math.Floor(hsx.H);
|
||||
var f = hsx.H - i;
|
||||
var p = hsx.V * (1 - hsx.S);
|
||||
var q = hsx.V * (1 - hsx.S * f);
|
||||
var t = hsx.V * (1 - hsx.S * (1 - f));
|
||||
|
||||
switch ((int)i)
|
||||
{
|
||||
case 0: rg.r = hsx.v; rg.g = t; rg.b = p; break;
|
||||
case 1: rg.r = q; rg.g = hsx.v; rg.b = p; break;
|
||||
case 2: rg.r = p; rg.g = hsx.v; rg.b = t; break;
|
||||
case 3: rg.r = p; rg.g = q; rg.b = hsx.v; break;
|
||||
case 4: rg.r = t; rg.g = p; rg.b = hsx.v; break;
|
||||
default: rg.r = hsx.v; rg.g = p; rg.b = q; break;
|
||||
case 0: rg.R = hsx.V; rg.G = t; rg.B = p; break;
|
||||
case 1: rg.R = q; rg.G = hsx.V; rg.B = p; break;
|
||||
case 2: rg.R = p; rg.G = hsx.V; rg.B = t; break;
|
||||
case 3: rg.R = p; rg.G = q; rg.B = hsx.V; break;
|
||||
case 4: rg.R = t; rg.G = p; rg.B = hsx.V; break;
|
||||
default: rg.R = hsx.V; rg.G = p; rg.B = q; break;
|
||||
}
|
||||
|
||||
rg.r = Math.Round(rg.r * 255);
|
||||
rg.g = Math.Round(rg.g * 255);
|
||||
rg.b = Math.Round(rg.b * 255);
|
||||
rg.R = Math.Round(rg.R * 255);
|
||||
rg.G = Math.Round(rg.G * 255);
|
||||
rg.B = Math.Round(rg.B * 255);
|
||||
|
||||
return rg;
|
||||
}
|
||||
|
|
|
@ -6,61 +6,61 @@ namespace ColorBlender
|
|||
{
|
||||
public class RGB
|
||||
{
|
||||
public double r;
|
||||
public double g;
|
||||
public double b;
|
||||
public double R;
|
||||
public double G;
|
||||
public double B;
|
||||
|
||||
public RGB() { }
|
||||
|
||||
public RGB(double r, double g, double b)
|
||||
{
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.R = r;
|
||||
this.G = g;
|
||||
this.B = b;
|
||||
}
|
||||
|
||||
public RGB(RGB rg)
|
||||
{
|
||||
this.r = rg.r;
|
||||
this.g = rg.g;
|
||||
this.b = rg.b;
|
||||
this.R = rg.R;
|
||||
this.G = rg.G;
|
||||
this.B = rg.B;
|
||||
}
|
||||
|
||||
public RGB(HSV hs)
|
||||
{
|
||||
RGB rg = hs.ToRGB();
|
||||
this.r = rg.r;
|
||||
this.g = rg.g;
|
||||
this.b = rg.b;
|
||||
this.R = rg.R;
|
||||
this.G = rg.G;
|
||||
this.B = rg.B;
|
||||
}
|
||||
|
||||
public HSV ToHSV()
|
||||
{
|
||||
HSV hs = new HSV();
|
||||
RGB rg = new RGB(this.r, this.g, this.b);
|
||||
RGB rg = new RGB(this.R, this.G, this.B);
|
||||
|
||||
var m = rg.r;
|
||||
if (rg.g < m) { m = rg.g; }
|
||||
if (rg.b < m) { m = rg.b; }
|
||||
var v = rg.r;
|
||||
if (rg.g > v) { v = rg.g; }
|
||||
if (rg.b > v) { v = rg.b; }
|
||||
var m = rg.R;
|
||||
if (rg.G < m) { m = rg.G; }
|
||||
if (rg.B < m) { m = rg.B; }
|
||||
var v = rg.R;
|
||||
if (rg.G > v) { v = rg.G; }
|
||||
if (rg.B > v) { v = rg.B; }
|
||||
var value = 100 * v / 255;
|
||||
var delta = v - m;
|
||||
if (v == 0.0) { hs.s = 0; } else { hs.s = 100 * delta / v; }
|
||||
if (v == 0.0) { hs.S = 0; } else { hs.S = 100 * delta / v; }
|
||||
|
||||
if (hs.s == 0) { hs.h = 0; }
|
||||
if (hs.S == 0) { hs.H = 0; }
|
||||
else
|
||||
{
|
||||
if (rg.r == v) { hs.h = 60.0 * (rg.g - rg.b) / delta; }
|
||||
else if (rg.g == v) { hs.h = 120.0 + 60.0 * (rg.b - rg.r) / delta; }
|
||||
else if (rg.b == v) { hs.h = 240.0 + 60.0 * (rg.r - rg.g) / delta; }
|
||||
if (hs.h < 0.0) { hs.h = hs.h + 360.0; }
|
||||
if (rg.R == v) { hs.H = 60.0 * (rg.G - rg.B) / delta; }
|
||||
else if (rg.G == v) { hs.H = 120.0 + 60.0 * (rg.B - rg.R) / delta; }
|
||||
else if (rg.B == v) { hs.H = 240.0 + 60.0 * (rg.R - rg.G) / delta; }
|
||||
if (hs.H < 0.0) { hs.H = hs.H + 360.0; }
|
||||
}
|
||||
|
||||
hs.h = Math.Round(hs.h);
|
||||
hs.s = Math.Round(hs.s);
|
||||
hs.v = Math.Round(value);
|
||||
hs.H = Math.Round(hs.H);
|
||||
hs.S = Math.Round(hs.S);
|
||||
hs.V = Math.Round(value);
|
||||
|
||||
return hs;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace ColorBlenderAvalonia
|
|||
public static Color ToColor(this RGB rgb)
|
||||
{
|
||||
return Color.FromRgb(
|
||||
(byte)Math.Round(rgb.r),
|
||||
(byte)Math.Round(rgb.g),
|
||||
(byte)Math.Round(rgb.b));
|
||||
(byte)Math.Round(rgb.R),
|
||||
(byte)Math.Round(rgb.G),
|
||||
(byte)Math.Round(rgb.B));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,16 +12,7 @@
|
|||
<Grid ColumnDefinitions="*,*,*,*,*,*" Grid.Column="0" Grid.Row="0">
|
||||
<TextBlock Text="Current Blend" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="5,2,5,2" HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||
<TextBlock Text="algorithm:" Grid.Column="2" Grid.Row="0" Grid.ColumnSpan="2" Margin="5,2,5,2" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<DropDown x:Name="algorithm" Grid.Column="4" Grid.Row="0" Grid.ColumnSpan="2" SelectedIndex="0">
|
||||
<DropDownItem Content="classic" />
|
||||
<DropDownItem Content="colorexplorer" />
|
||||
<DropDownItem Content="singlehue" />
|
||||
<DropDownItem Content="complementary" />
|
||||
<DropDownItem Content="splitcomplementary" />
|
||||
<DropDownItem Content="analogue" />
|
||||
<DropDownItem Content="triadic" />
|
||||
<DropDownItem Content="square" />
|
||||
</DropDown>
|
||||
<DropDown x:Name="algorithm" Grid.Column="4" Grid.Row="0" Grid.ColumnSpan="2" Items="{Binding Algorithms}" SelectedItem="{Binding CurrentAlgorithm}"/>
|
||||
</Grid>
|
||||
<Grid x:Name="swatches" ColumnDefinitions="*,*,*,*,*,*" Grid.Row="1">
|
||||
<local:Swatch x:Name="swatch1" Grid.Column="0" Margin="2" />
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Shapes;
|
||||
|
@ -8,17 +11,12 @@ using Avalonia.Input;
|
|||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using ColorBlender;
|
||||
using ColorBlender.Algorithms;
|
||||
|
||||
namespace ColorBlenderAvalonia
|
||||
{
|
||||
public class MainWindow : Window
|
||||
{
|
||||
private RGB rgb;
|
||||
private HSV hsv;
|
||||
private Blend z;
|
||||
private RGB[] vRGB = new RGB[7];
|
||||
private RGB[] vHSV = new RGB[9];
|
||||
private bool updatingSliders = false;
|
||||
private DropDown algorithm;
|
||||
private Slider sliderR;
|
||||
private Slider sliderG;
|
||||
|
@ -49,16 +47,56 @@ namespace ColorBlenderAvalonia
|
|||
private Swatch swatch5;
|
||||
private Swatch swatch6;
|
||||
|
||||
private string Algorithm
|
||||
{
|
||||
get { return (algorithm.SelectedItem as DropDownItem).Content.ToString(); }
|
||||
}
|
||||
private RGB rgb;
|
||||
private HSV hsv;
|
||||
private Blend z;
|
||||
private RGB[] vRGB = new RGB[7];
|
||||
private RGB[] vHSV = new RGB[9];
|
||||
private bool updatingSliders = false;
|
||||
|
||||
public IList<IAlgorithm> Algorithms { get; set; }
|
||||
public IAlgorithm CurrentAlgorithm { get; set; }
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.AttachDevTools();
|
||||
this.InitializeNames();
|
||||
|
||||
Algorithms = new ObservableCollection<IAlgorithm>()
|
||||
{
|
||||
new Classic(),
|
||||
new ColorExplorer(),
|
||||
new SingleHue(),
|
||||
new Complementary(),
|
||||
new SplitComplementary(),
|
||||
new Analogue(),
|
||||
new Triadic(),
|
||||
new Square()
|
||||
};
|
||||
|
||||
CurrentAlgorithm = Algorithms.FirstOrDefault();
|
||||
|
||||
DataContext = this;
|
||||
|
||||
hsv = new HSV(213, 46, 49);
|
||||
rgb = new RGB(hsv);
|
||||
z = CurrentAlgorithm.Match(hsv);
|
||||
|
||||
UpdateSliderRGB();
|
||||
UpdateSliderHSV();
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
InitializeEventHandlers();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InitializeNames()
|
||||
{
|
||||
algorithm = this.FindControl<DropDown>("algorithm");
|
||||
sliderR = this.FindControl<Slider>("sliderR");
|
||||
sliderG = this.FindControl<Slider>("sliderG");
|
||||
|
@ -88,16 +126,10 @@ namespace ColorBlenderAvalonia
|
|||
swatch4 = this.FindControl<Swatch>("swatch4");
|
||||
swatch5 = this.FindControl<Swatch>("swatch5");
|
||||
swatch6 = this.FindControl<Swatch>("swatch6");
|
||||
}
|
||||
|
||||
hsv = new HSV(213, 46, 49);
|
||||
rgb = new RGB(hsv);
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
|
||||
UpdateSliderRGB();
|
||||
UpdateSliderHSV();
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
|
||||
private void InitializeEventHandlers()
|
||||
{
|
||||
sliderR.GetObservable(Slider.ValueProperty).Subscribe(value => SliderRGB_ValueChanged());
|
||||
sliderG.GetObservable(Slider.ValueProperty).Subscribe(value => SliderRGB_ValueChanged());
|
||||
sliderB.GetObservable(Slider.ValueProperty).Subscribe(value => SliderRGB_ValueChanged());
|
||||
|
@ -112,6 +144,7 @@ namespace ColorBlenderAvalonia
|
|||
rgbvar5.PointerPressed += Rectangle_PointerPressed;
|
||||
rgbvar6.PointerPressed += Rectangle_PointerPressed;
|
||||
rgbvar7.PointerPressed += Rectangle_PointerPressed;
|
||||
|
||||
hsvvar1.PointerPressed += Rectangle_PointerPressed;
|
||||
hsvvar2.PointerPressed += Rectangle_PointerPressed;
|
||||
hsvvar3.PointerPressed += Rectangle_PointerPressed;
|
||||
|
@ -121,23 +154,20 @@ namespace ColorBlenderAvalonia
|
|||
hsvvar7.PointerPressed += Rectangle_PointerPressed;
|
||||
hsvvar8.PointerPressed += Rectangle_PointerPressed;
|
||||
hsvvar9.PointerPressed += Rectangle_PointerPressed;
|
||||
|
||||
swatch1.col.PointerPressed += Rectangle_PointerPressed;
|
||||
swatch2.col.PointerPressed += Rectangle_PointerPressed;
|
||||
swatch3.col.PointerPressed += Rectangle_PointerPressed;
|
||||
swatch4.col.PointerPressed += Rectangle_PointerPressed;
|
||||
swatch5.col.PointerPressed += Rectangle_PointerPressed;
|
||||
swatch6.col.PointerPressed += Rectangle_PointerPressed;
|
||||
algorithm.SelectionChanged += Algorithm_SelectionChanged;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
algorithm.SelectionChanged += Algorithm_SelectionChanged;
|
||||
}
|
||||
|
||||
private void Algorithm_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
z = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
@ -173,7 +203,7 @@ namespace ColorBlenderAvalonia
|
|||
UpdateSliderHSV();
|
||||
updatingSliders = false;
|
||||
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
z = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
@ -190,16 +220,16 @@ namespace ColorBlenderAvalonia
|
|||
|
||||
private void UpdateSliderRGB()
|
||||
{
|
||||
sliderR.Value = rgb.r;
|
||||
sliderG.Value = rgb.g;
|
||||
sliderB.Value = rgb.b;
|
||||
sliderR.Value = rgb.R;
|
||||
sliderG.Value = rgb.G;
|
||||
sliderB.Value = rgb.B;
|
||||
}
|
||||
|
||||
private void UpdateSliderHSV()
|
||||
{
|
||||
sliderH.Value = hsv.h;
|
||||
sliderS.Value = hsv.s;
|
||||
sliderV.Value = hsv.v;
|
||||
sliderH.Value = hsv.H;
|
||||
sliderS.Value = hsv.S;
|
||||
sliderV.Value = hsv.V;
|
||||
}
|
||||
|
||||
private double AddLimit(double x, double d, double min, double max)
|
||||
|
@ -217,13 +247,13 @@ namespace ColorBlenderAvalonia
|
|||
var rgbobj = new RGB();
|
||||
var hsvobj = new HSV
|
||||
{
|
||||
h = hsv.h,
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = hsv.H,
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
|
||||
hsvobj.s = AddLimit(hsvobj.s, addsat, 0, 99);
|
||||
hsvobj.v = AddLimit(hsvobj.v, addval, 0, 99);
|
||||
hsvobj.S = AddLimit(hsvobj.S, addsat, 0, 99);
|
||||
hsvobj.V = AddLimit(hsvobj.V, addval, 0, 99);
|
||||
|
||||
rgbobj = hsvobj.ToRGB();
|
||||
|
||||
|
@ -235,13 +265,13 @@ namespace ColorBlenderAvalonia
|
|||
double vv = 20;
|
||||
double vw = 10;
|
||||
|
||||
vRGB[0] = new RGB(AddLimit(rgb.r, -vw, 0, 255), AddLimit(rgb.g, vv, 0, 255), AddLimit(rgb.b, -vw, 0, 255));
|
||||
vRGB[1] = new RGB(AddLimit(rgb.r, vw, 0, 255), AddLimit(rgb.g, vw, 0, 255), AddLimit(rgb.b, -vv, 0, 255));
|
||||
vRGB[2] = new RGB(AddLimit(rgb.r, -vv, 0, 255), AddLimit(rgb.g, vw, 0, 255), AddLimit(rgb.b, vw, 0, 255));
|
||||
vRGB[3] = new RGB(rgb.r, rgb.g, rgb.b);
|
||||
vRGB[4] = new RGB(AddLimit(rgb.r, vv, 0, 255), AddLimit(rgb.g, -vw, 0, 255), AddLimit(rgb.b, -vw, 0, 255));
|
||||
vRGB[5] = new RGB(AddLimit(rgb.r, -vw, 0, 255), AddLimit(rgb.g, -vw, 0, 255), AddLimit(rgb.b, vv, 0, 255));
|
||||
vRGB[6] = new RGB(AddLimit(rgb.r, vw, 0, 255), AddLimit(rgb.g, -vv, 0, 255), AddLimit(rgb.b, vw, 0, 255));
|
||||
vRGB[0] = new RGB(AddLimit(rgb.R, -vw, 0, 255), AddLimit(rgb.G, vv, 0, 255), AddLimit(rgb.B, -vw, 0, 255));
|
||||
vRGB[1] = new RGB(AddLimit(rgb.R, vw, 0, 255), AddLimit(rgb.G, vw, 0, 255), AddLimit(rgb.B, -vv, 0, 255));
|
||||
vRGB[2] = new RGB(AddLimit(rgb.R, -vv, 0, 255), AddLimit(rgb.G, vw, 0, 255), AddLimit(rgb.B, vw, 0, 255));
|
||||
vRGB[3] = new RGB(rgb.R, rgb.G, rgb.B);
|
||||
vRGB[4] = new RGB(AddLimit(rgb.R, vv, 0, 255), AddLimit(rgb.G, -vw, 0, 255), AddLimit(rgb.B, -vw, 0, 255));
|
||||
vRGB[5] = new RGB(AddLimit(rgb.R, -vw, 0, 255), AddLimit(rgb.G, -vw, 0, 255), AddLimit(rgb.B, vv, 0, 255));
|
||||
vRGB[6] = new RGB(AddLimit(rgb.R, vw, 0, 255), AddLimit(rgb.G, -vv, 0, 255), AddLimit(rgb.B, vw, 0, 255));
|
||||
}
|
||||
|
||||
private void UpdateVariationsHSV()
|
||||
|
@ -285,9 +315,9 @@ namespace ColorBlenderAvalonia
|
|||
|
||||
private void HandleSliderValueChangedRGB()
|
||||
{
|
||||
rgb.r = sliderR.Value;
|
||||
rgb.g = sliderG.Value;
|
||||
rgb.b = sliderB.Value;
|
||||
rgb.R = sliderR.Value;
|
||||
rgb.G = sliderG.Value;
|
||||
rgb.B = sliderB.Value;
|
||||
|
||||
hsv = rgb.ToHSV();
|
||||
rgb = hsv.ToRGB();
|
||||
|
@ -296,16 +326,16 @@ namespace ColorBlenderAvalonia
|
|||
UpdateSliderHSV();
|
||||
updatingSliders = false;
|
||||
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
z = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
||||
private void HandleSliderValueChangedHSV()
|
||||
{
|
||||
hsv.h = sliderH.Value;
|
||||
hsv.s = sliderS.Value;
|
||||
hsv.v = sliderV.Value;
|
||||
hsv.H = sliderH.Value;
|
||||
hsv.S = sliderS.Value;
|
||||
hsv.V = sliderV.Value;
|
||||
|
||||
rgb = hsv.ToRGB();
|
||||
|
||||
|
@ -313,7 +343,7 @@ namespace ColorBlenderAvalonia
|
|||
UpdateSliderRGB();
|
||||
updatingSliders = false;
|
||||
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
z = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace ColorBlenderWPF
|
|||
public static Color ToColor(this RGB rgb)
|
||||
{
|
||||
return Color.FromRgb(
|
||||
(byte)Math.Round(rgb.r),
|
||||
(byte)Math.Round(rgb.g),
|
||||
(byte)Math.Round(rgb.b));
|
||||
(byte)Math.Round(rgb.R),
|
||||
(byte)Math.Round(rgb.G),
|
||||
(byte)Math.Round(rgb.B));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,16 +30,7 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Current Blend" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="5,2,5,2" HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||
<TextBlock Text="algorithm:" Grid.Column="2" Grid.Row="0" Grid.ColumnSpan="2" Margin="5,2,5,2" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<ComboBox x:Name="algorithm" Grid.Column="4" Grid.Row="0" Grid.ColumnSpan="2" SelectedIndex="0">
|
||||
<ComboBoxItem Content="classic" />
|
||||
<ComboBoxItem Content="colorexplorer" />
|
||||
<ComboBoxItem Content="singlehue" />
|
||||
<ComboBoxItem Content="complementary" />
|
||||
<ComboBoxItem Content="splitcomplementary" />
|
||||
<ComboBoxItem Content="analogue" />
|
||||
<ComboBoxItem Content="triadic" />
|
||||
<ComboBoxItem Content="square" />
|
||||
</ComboBox>
|
||||
<ComboBox x:Name="algorithm" Grid.Column="4" Grid.Row="0" Grid.ColumnSpan="2" ItemsSource="{Binding Algorithms}" SelectedItem="{Binding CurrentAlgorithm}"/>
|
||||
</Grid>
|
||||
<Grid x:Name="swatches" Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using ColorBlender;
|
||||
using ColorBlender.Algorithms;
|
||||
|
||||
namespace ColorBlenderWPF
|
||||
{
|
||||
|
@ -13,35 +17,54 @@ namespace ColorBlenderWPF
|
|||
{
|
||||
private RGB rgb;
|
||||
private HSV hsv;
|
||||
private Blend z;
|
||||
private Blend blend;
|
||||
private RGB[] vRGB = new RGB[7];
|
||||
private RGB[] vHSV = new RGB[9];
|
||||
private bool updatingSliders = false;
|
||||
|
||||
private string Algorithm
|
||||
{
|
||||
get { return (algorithm.SelectedItem as ComboBoxItem).Content.ToString(); }
|
||||
}
|
||||
public IList<IAlgorithm> Algorithms { get; set; }
|
||||
public IAlgorithm CurrentAlgorithm { get; set; }
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Algorithms = new ObservableCollection<IAlgorithm>()
|
||||
{
|
||||
new Classic(),
|
||||
new ColorExplorer(),
|
||||
new SingleHue(),
|
||||
new Complementary(),
|
||||
new SplitComplementary(),
|
||||
new Analogue(),
|
||||
new Triadic(),
|
||||
new Square()
|
||||
};
|
||||
|
||||
CurrentAlgorithm = Algorithms.FirstOrDefault();
|
||||
|
||||
DataContext = this;
|
||||
|
||||
hsv = new HSV(213, 46, 49);
|
||||
rgb = new RGB(hsv);
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
blend = CurrentAlgorithm.Match(hsv);
|
||||
|
||||
UpdateSliderRGB();
|
||||
UpdateSliderHSV();
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
InitializeEventHandlers();
|
||||
}
|
||||
|
||||
private void InitializeEventHandlers()
|
||||
{
|
||||
sliderR.ValueChanged += SliderRGB_ValueChanged;
|
||||
sliderG.ValueChanged += SliderRGB_ValueChanged;
|
||||
sliderB.ValueChanged += SliderRGB_ValueChanged;
|
||||
sliderH.ValueChanged += SliderHSV_ValueChanged;
|
||||
sliderS.ValueChanged += SliderHSV_ValueChanged;
|
||||
sliderV.ValueChanged += SliderHSV_ValueChanged;
|
||||
|
||||
rgbvar1.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
rgbvar2.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
rgbvar3.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
|
@ -49,6 +72,7 @@ namespace ColorBlenderWPF
|
|||
rgbvar5.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
rgbvar6.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
rgbvar7.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
|
||||
hsvvar1.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
hsvvar2.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
hsvvar3.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
|
@ -58,18 +82,20 @@ namespace ColorBlenderWPF
|
|||
hsvvar7.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
hsvvar8.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
hsvvar9.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
|
||||
swatch1.col.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
swatch2.col.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
swatch3.col.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
swatch4.col.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
swatch5.col.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
swatch6.col.MouseLeftButtonDown += Rectangle_MouseLeftButtonDown;
|
||||
|
||||
algorithm.SelectionChanged += Algorithm_SelectionChanged;
|
||||
}
|
||||
|
||||
private void Algorithm_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
blend = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
@ -105,33 +131,33 @@ namespace ColorBlenderWPF
|
|||
UpdateSliderHSV();
|
||||
updatingSliders = false;
|
||||
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
blend = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
||||
private void UpdateSwatches()
|
||||
{
|
||||
swatch1.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(z.Colors[0]));
|
||||
swatch2.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(z.Colors[1]));
|
||||
swatch3.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(z.Colors[2]));
|
||||
swatch4.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(z.Colors[3]));
|
||||
swatch5.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(z.Colors[4]));
|
||||
swatch6.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(z.Colors[5]));
|
||||
swatch1.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(blend.Colors[0]));
|
||||
swatch2.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(blend.Colors[1]));
|
||||
swatch3.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(blend.Colors[2]));
|
||||
swatch4.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(blend.Colors[3]));
|
||||
swatch5.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(blend.Colors[4]));
|
||||
swatch6.col.Fill = new SolidColorBrush(ColorExtensions.ToColor(blend.Colors[5]));
|
||||
}
|
||||
|
||||
private void UpdateSliderRGB()
|
||||
{
|
||||
sliderR.Value = rgb.r;
|
||||
sliderG.Value = rgb.g;
|
||||
sliderB.Value = rgb.b;
|
||||
sliderR.Value = rgb.R;
|
||||
sliderG.Value = rgb.G;
|
||||
sliderB.Value = rgb.B;
|
||||
}
|
||||
|
||||
private void UpdateSliderHSV()
|
||||
{
|
||||
sliderH.Value = hsv.h;
|
||||
sliderS.Value = hsv.s;
|
||||
sliderV.Value = hsv.v;
|
||||
sliderH.Value = hsv.H;
|
||||
sliderS.Value = hsv.S;
|
||||
sliderV.Value = hsv.V;
|
||||
}
|
||||
|
||||
private double AddLimit(double x, double d, double min, double max)
|
||||
|
@ -149,13 +175,13 @@ namespace ColorBlenderWPF
|
|||
var rgbobj = new RGB();
|
||||
var hsvobj = new HSV
|
||||
{
|
||||
h = hsv.h,
|
||||
s = hsv.s,
|
||||
v = hsv.v
|
||||
H = hsv.H,
|
||||
S = hsv.S,
|
||||
V = hsv.V
|
||||
};
|
||||
|
||||
hsvobj.s = AddLimit(hsvobj.s, addsat, 0, 99);
|
||||
hsvobj.v = AddLimit(hsvobj.v, addval, 0, 99);
|
||||
hsvobj.S = AddLimit(hsvobj.S, addsat, 0, 99);
|
||||
hsvobj.V = AddLimit(hsvobj.V, addval, 0, 99);
|
||||
|
||||
rgbobj = hsvobj.ToRGB();
|
||||
|
||||
|
@ -167,13 +193,13 @@ namespace ColorBlenderWPF
|
|||
double vv = 20;
|
||||
double vw = 10;
|
||||
|
||||
vRGB[0] = new RGB(AddLimit(rgb.r, -vw, 0, 255), AddLimit(rgb.g, vv, 0, 255), AddLimit(rgb.b, -vw, 0, 255));
|
||||
vRGB[1] = new RGB(AddLimit(rgb.r, vw, 0, 255), AddLimit(rgb.g, vw, 0, 255), AddLimit(rgb.b, -vv, 0, 255));
|
||||
vRGB[2] = new RGB(AddLimit(rgb.r, -vv, 0, 255), AddLimit(rgb.g, vw, 0, 255), AddLimit(rgb.b, vw, 0, 255));
|
||||
vRGB[3] = new RGB(rgb.r, rgb.g, rgb.b);
|
||||
vRGB[4] = new RGB(AddLimit(rgb.r, vv, 0, 255), AddLimit(rgb.g, -vw, 0, 255), AddLimit(rgb.b, -vw, 0, 255));
|
||||
vRGB[5] = new RGB(AddLimit(rgb.r, -vw, 0, 255), AddLimit(rgb.g, -vw, 0, 255), AddLimit(rgb.b, vv, 0, 255));
|
||||
vRGB[6] = new RGB(AddLimit(rgb.r, vw, 0, 255), AddLimit(rgb.g, -vv, 0, 255), AddLimit(rgb.b, vw, 0, 255));
|
||||
vRGB[0] = new RGB(AddLimit(rgb.R, -vw, 0, 255), AddLimit(rgb.G, vv, 0, 255), AddLimit(rgb.B, -vw, 0, 255));
|
||||
vRGB[1] = new RGB(AddLimit(rgb.R, vw, 0, 255), AddLimit(rgb.G, vw, 0, 255), AddLimit(rgb.B, -vv, 0, 255));
|
||||
vRGB[2] = new RGB(AddLimit(rgb.R, -vv, 0, 255), AddLimit(rgb.G, vw, 0, 255), AddLimit(rgb.B, vw, 0, 255));
|
||||
vRGB[3] = new RGB(rgb.R, rgb.G, rgb.B);
|
||||
vRGB[4] = new RGB(AddLimit(rgb.R, vv, 0, 255), AddLimit(rgb.G, -vw, 0, 255), AddLimit(rgb.B, -vw, 0, 255));
|
||||
vRGB[5] = new RGB(AddLimit(rgb.R, -vw, 0, 255), AddLimit(rgb.G, -vw, 0, 255), AddLimit(rgb.B, vv, 0, 255));
|
||||
vRGB[6] = new RGB(AddLimit(rgb.R, vw, 0, 255), AddLimit(rgb.G, -vv, 0, 255), AddLimit(rgb.B, vw, 0, 255));
|
||||
}
|
||||
|
||||
private void UpdateVariationsHSV()
|
||||
|
@ -217,9 +243,9 @@ namespace ColorBlenderWPF
|
|||
|
||||
private void HandleSliderValueChangedRGB()
|
||||
{
|
||||
rgb.r = sliderR.Value;
|
||||
rgb.g = sliderG.Value;
|
||||
rgb.b = sliderB.Value;
|
||||
rgb.R = sliderR.Value;
|
||||
rgb.G = sliderG.Value;
|
||||
rgb.B = sliderB.Value;
|
||||
|
||||
hsv = rgb.ToHSV();
|
||||
rgb = hsv.ToRGB();
|
||||
|
@ -228,16 +254,16 @@ namespace ColorBlenderWPF
|
|||
UpdateSliderHSV();
|
||||
updatingSliders = false;
|
||||
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
blend = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
||||
private void HandleSliderValueChangedHSV()
|
||||
{
|
||||
hsv.h = sliderH.Value;
|
||||
hsv.s = sliderS.Value;
|
||||
hsv.v = sliderV.Value;
|
||||
hsv.H = sliderH.Value;
|
||||
hsv.S = sliderS.Value;
|
||||
hsv.V = sliderV.Value;
|
||||
|
||||
rgb = hsv.ToRGB();
|
||||
|
||||
|
@ -245,7 +271,7 @@ namespace ColorBlenderWPF
|
|||
UpdateSliderRGB();
|
||||
updatingSliders = false;
|
||||
|
||||
z = ColorMatch.Match(hsv, Algorithm);
|
||||
blend = CurrentAlgorithm.Match(hsv);
|
||||
UpdateSwatches();
|
||||
UpdateVariations();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) Wies³aw Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using ColorBlender.Algorithms;
|
||||
using Xunit;
|
||||
|
||||
namespace ColorBlender.UnitTests
|
||||
{
|
||||
public class AlgorithmsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Classic_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new Classic();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(213, 46, 79),
|
||||
new HSV(53, 46, 49),
|
||||
new HSV(43, 46, 79),
|
||||
new HSV(0, 0, 51),
|
||||
new HSV(0, 0, 49)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ColorExplorer_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new ColorExplorer();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(213, 14, 64),
|
||||
new HSV(153, 55, 24),
|
||||
new HSV(153, 46, 49),
|
||||
new HSV(153, 0, 99),
|
||||
new HSV(153, 0, 49)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SingleHue_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new SingleHue();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(213, 46, 69),
|
||||
new HSV(213, 46, 89),
|
||||
new HSV(213, 66, 49),
|
||||
new HSV(213, 86, 49),
|
||||
new HSV(213, 86, 89)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Complementary_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new Complementary();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(213, 92, 73.5),
|
||||
new HSV(47, 46, 49),
|
||||
new HSV(47, 92, 73.5),
|
||||
new HSV(0, 0, 49),
|
||||
new HSV(0, 0, 51)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitComplementary_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new SplitComplementary();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(27, 46, 49),
|
||||
new HSV(67, 46, 49),
|
||||
new HSV(67, 0, 46),
|
||||
new HSV(67, 0, 49),
|
||||
new HSV(67, 0, 51)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Analogue_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new Analogue();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(253, 46, 49),
|
||||
new HSV(293, 46, 49),
|
||||
new HSV(0, 0, 51),
|
||||
new HSV(0, 0, 64),
|
||||
new HSV(0, 0, 38)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Triadic_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new Triadic();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(213, 46, 51),
|
||||
new HSV(7, 46, 49),
|
||||
new HSV(7, 46, 51),
|
||||
new HSV(87, 46, 49),
|
||||
new HSV(87, 46, 51)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Square_Match()
|
||||
{
|
||||
var hsv = new HSV(213, 46, 49);
|
||||
var algorithm = new Square();
|
||||
var actual = algorithm.Match(hsv);
|
||||
var expected = new Blend()
|
||||
{
|
||||
Colors = new[]
|
||||
{
|
||||
new HSV(213, 46, 49),
|
||||
new HSV(333, 46, 49),
|
||||
new HSV(47, 46, 49),
|
||||
new HSV(107, 46, 49),
|
||||
new HSV(107, 0, 49),
|
||||
new HSV(107, 0, 51)
|
||||
}
|
||||
};
|
||||
Assert.Equal(expected, actual, new BlendEqualityComparer());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) Wiesław Šoltés. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ColorBlender.UnitTests
|
||||
{
|
||||
internal class BlendEqualityComparer : IEqualityComparer<Blend>
|
||||
{
|
||||
public bool Equals(Blend x, Blend y)
|
||||
{
|
||||
return x.Colors[0].H == y.Colors[0].H
|
||||
&& x.Colors[0].S == y.Colors[0].S
|
||||
&& x.Colors[0].V == y.Colors[0].V
|
||||
&& x.Colors[1].H == y.Colors[1].H
|
||||
&& x.Colors[1].S == y.Colors[1].S
|
||||
&& x.Colors[1].V == y.Colors[1].V
|
||||
&& x.Colors[2].H == y.Colors[2].H
|
||||
&& x.Colors[2].S == y.Colors[2].S
|
||||
&& x.Colors[2].V == y.Colors[2].V
|
||||
&& x.Colors[3].H == y.Colors[3].H
|
||||
&& x.Colors[3].S == y.Colors[3].S
|
||||
&& x.Colors[3].V == y.Colors[3].V
|
||||
&& x.Colors[4].H == y.Colors[4].H
|
||||
&& x.Colors[4].S == y.Colors[4].S
|
||||
&& x.Colors[4].V == y.Colors[4].V
|
||||
&& x.Colors[5].H == y.Colors[5].H
|
||||
&& x.Colors[5].S == y.Colors[5].S
|
||||
&& x.Colors[5].V == y.Colors[5].V;
|
||||
}
|
||||
|
||||
public int GetHashCode(Blend obj)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
|
||||
<PackageReference Include="xunit" Version="2.2.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\ColorBlender\ColorBlender.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче