2 changed files with 74 additions and 0 deletions
@ -0,0 +1,68 @@ |
|||
// Original source was written by Romain Guy and Francois Blavoet
|
|||
// and adopted from LottieSharp Project (https://github.com/ascora/LottieSharp).
|
|||
|
|||
using System; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation |
|||
{ |
|||
/// <summary>
|
|||
/// Animator that interpolates <see cref="Color"/> through
|
|||
/// gamma sRGB color space for better visual result.
|
|||
/// </summary>
|
|||
public class ColorAnimator : Animator<Color> |
|||
{ |
|||
// Opto-electronic conversion function for the sRGB color space
|
|||
// Takes a gamma-encoded sRGB value and converts it to a linear sRGB value
|
|||
private static double OECF_sRGB(double linear) |
|||
{ |
|||
// IEC 61966-2-1:1999
|
|||
return linear <= 0.0031308d ? linear * 12.92d : (double)(Math.Pow(linear, 1.0d / 2.4d) * 1.055d - 0.055d); |
|||
} |
|||
|
|||
// Electro-optical conversion function for the sRGB color space
|
|||
// Takes a linear sRGB value and converts it to a gamma-encoded sRGB value
|
|||
private static double EOCF_sRGB(double srgb) |
|||
{ |
|||
// IEC 61966-2-1:1999
|
|||
return srgb <= 0.04045d ? srgb / 12.92d : (double)Math.Pow((srgb + 0.055d) / 1.055d, 2.4d); |
|||
} |
|||
|
|||
protected override Color Interpolate(double fraction, Color start, Color end) |
|||
{ |
|||
var startA = start.A / 255d; |
|||
var startR = start.R / 255d; |
|||
var startG = start.G / 255d; |
|||
var startB = start.B / 255d; |
|||
|
|||
var endA = end.A / 255d; |
|||
var endR = end.R / 255d; |
|||
var endG = end.G / 255d; |
|||
var endB = end.B / 255d; |
|||
|
|||
// convert from sRGB to linear
|
|||
startR = EOCF_sRGB(startR); |
|||
startG = EOCF_sRGB(startG); |
|||
startB = EOCF_sRGB(startB); |
|||
|
|||
endR = EOCF_sRGB(endR); |
|||
endG = EOCF_sRGB(endG); |
|||
endB = EOCF_sRGB(endB); |
|||
|
|||
// compute the interpolated color in linear space
|
|||
var a = startA + fraction * (endA - startA); |
|||
var r = startR + fraction * (endR - startR); |
|||
var g = startG + fraction * (endG - startG); |
|||
var b = startB + fraction * (endB - startB); |
|||
|
|||
// convert back to sRGB in the [0..255] range
|
|||
a = a * 255.0d; |
|||
r = OECF_sRGB(r) * 255.0d; |
|||
g = OECF_sRGB(g) * 255.0d; |
|||
b = OECF_sRGB(b) * 255.0d; |
|||
|
|||
return new Color((byte)Math.Round(r), (byte)Math.Round(g), (byte)Math.Round(b), (byte)Math.Round(a)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue