Created
June 9, 2014 00:24
-
-
Save mstefarov/3b59867705350c3c32ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2013 Matvei Stefarov <[email protected]> | |
using System; | |
using JetBrains.Annotations; | |
using RgbColor = System.Drawing.Color; | |
namespace fCraft.Drawing { | |
/// <summary> Represents a palette of Minecraft blocks, | |
/// that allows matching RGB colors to their closest block equivalents. </summary> | |
public class BlockPalette { | |
// XN/YN/ZN are illuminant D65 tristimulus values | |
const double XN = 95.047, | |
YN = 100.000, | |
ZN = 108.883; | |
// these constant are used in CIEXYZ -> CIELAB conversion | |
const double LinearThreshold = (6/29d)*(6/29d)*(6/29d), | |
LinearMultiplier = (1/3d)*(29/6d)*(29/6d), | |
LinearConstant = (4/29d); | |
// CIE76 formula for Delta-E, over CIELAB color space | |
static double ColorDifference( LabColor color1, LabColor color2 ) { | |
return | |
// NOTE: multiplying delta-L by 1.2 is optional and not part of vanilla deltaE formula. | |
// It is done here subjectively to emphasize luminance difference over hue/saturation difference. | |
Math.Sqrt( (color2.L - color1.L)*(color2.L - color1.L)*1.2 + | |
(color2.a - color1.a)*(color2.a - color1.a) + | |
(color2.b - color1.b)*(color2.b - color1.b) ); | |
} | |
// Conversion from RGB to CIELAB, using illuminant D65. | |
static LabColor RgbToLab( RgbColor color ) { | |
// RGB are assumed to be in [0...255] range | |
double R = color.R/255d; | |
double G = color.G/255d; | |
double B = color.B/255d; | |
// CIEXYZ coordinates are normalized to [0...1] | |
double x = 0.4124564*R + 0.3575761*G + 0.1804375*B; | |
double y = 0.2126729*R + 0.7151522*G + 0.0721750*B; | |
double z = 0.0193339*R + 0.1191920*G + 0.9503041*B; | |
double xRatio = x/XN; | |
double yRatio = y/YN; | |
double zRatio = z/ZN; | |
LabColor result = new LabColor { | |
// L is normalized to [0...100] | |
L = 116*XyzToLab( yRatio ) - 16, | |
a = 500*(XyzToLab( xRatio ) - XyzToLab( yRatio )), | |
b = 200*(XyzToLab( yRatio ) - XyzToLab( zRatio )) | |
}; | |
return result; | |
} | |
static double XyzToLab( double ratio ) { | |
if( ratio > LinearThreshold ) { | |
return Math.Pow( ratio, 1/3d ); | |
} else { | |
return LinearMultiplier*ratio + LinearConstant; | |
} | |
} | |
protected struct LabColor { | |
public double L, a, b; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment