chromaticity-color-utilities
Advanced tools
Comparing version 0.1.13-alpha to 0.2.0-alpha
@@ -1,96 +0,2 @@ | ||
export interface newColorArgs { | ||
round?: boolean; | ||
bitDepth?: number; | ||
bitRate?: number; | ||
normalize?: boolean; | ||
colorSpace?: string; | ||
referenceWhite?: string; | ||
kb?: number; | ||
kr?: number; | ||
pb?: number; | ||
pr?: number; | ||
yLower?: number; | ||
yUpper?: number; | ||
cLower?: number; | ||
cUpper?: number; | ||
gamma?: number; | ||
} | ||
export interface allColorProps { | ||
bitDepth?: number; | ||
normalized?: boolean; | ||
colorSpace?: string; | ||
referenceWhite?: string; | ||
kb?: number; | ||
kr?: number; | ||
pb?: number; | ||
pr?: number; | ||
pg?: number; | ||
yLower?: number; | ||
yUpper?: number; | ||
cLower?: number; | ||
cUpper?: number; | ||
gamma?: number; | ||
} | ||
export interface modifyArgs { | ||
method?: string; | ||
with?: colorType; | ||
amount?: number; | ||
round?: boolean; | ||
} | ||
export interface schemeArgs { | ||
angle?: number; | ||
colors?: number; | ||
distance?: number; | ||
distanceToBlack?: number; | ||
distanceToWhite?: number; | ||
round?: boolean; | ||
} | ||
export declare abstract class colorType { | ||
constructor(); | ||
bitDepth?: number; | ||
normalized?: boolean; | ||
colorSpace?: string; | ||
referenceWhite?: string; | ||
kb?: number; | ||
kr?: number; | ||
pb?: number; | ||
pr?: number; | ||
yLower?: number; | ||
yUpper?: number; | ||
cLower?: number; | ||
cUpper?: number; | ||
gamma?: number; | ||
a?: number; | ||
to(type: string, args?: newColorArgs): colorType | any; | ||
modify(modification: string, args?: modifyArgs): colorType; | ||
scheme(type: string, args?: schemeArgs): colorType[]; | ||
css(): string; | ||
protected torgb(args: newColorArgs): rgb; | ||
protected torec709(args: newColorArgs): rec709rgb; | ||
protected torec2020(args: newColorArgs): rec2020rgb; | ||
protected tohex(args: newColorArgs): hex; | ||
protected tohsv(args: newColorArgs): hsv; | ||
protected tohsl(args: newColorArgs): hsl; | ||
protected tohsi(args: newColorArgs): hsi; | ||
protected tohsp(args: newColorArgs): hsp; | ||
protected tocmyk(args: newColorArgs): cmyk; | ||
protected toyiq(args: newColorArgs): yiq; | ||
protected toxyz(args: newColorArgs): xyz; | ||
protected toxyy(args: newColorArgs): xyy; | ||
protected tolab(args: newColorArgs): lab; | ||
protected toluv(args: newColorArgs): luv; | ||
protected toypbpr(args: newColorArgs): ypbpr; | ||
protected toycbcr(args: newColorArgs): ycbcr; | ||
protected setArgs(args?: newColorArgs): newColorArgs; | ||
/** | ||
* Range check to make sure numeric value is within lower and upper limits | ||
* Throws error on fail, returns nothing | ||
* | ||
* @param {number} value | ||
* @param {number|boolean} lowerLimit number or false | ||
* @param {number|boolean} upperLimit number or false | ||
* @param {string} msg error message if fail | ||
*/ | ||
protected valueRangeCheck(value: number, lowerLimit: number | boolean, upperLimit: number | boolean, msg?: string): void; | ||
} | ||
import { newColorArgs, colorType } from './ColorType'; | ||
export declare class hex extends colorType { | ||
@@ -97,0 +3,0 @@ hex: string; |
@@ -36,405 +36,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.kelvin = exports.nm = exports.ycbcr = exports.ypbpr = exports.luv = exports.lab = exports.xyy = exports.xyz = exports.yiq = exports.cmyk = exports.hsp = exports.hsi = exports.hsl = exports.hsv = exports.rec2020rgb = exports.rec709rgb = exports.rgb = exports.rgbNormalized = exports.hex = exports.colorType = void 0; | ||
exports.kelvin = exports.nm = exports.ycbcr = exports.ypbpr = exports.luv = exports.lab = exports.xyy = exports.xyz = exports.yiq = exports.cmyk = exports.hsp = exports.hsi = exports.hsl = exports.hsv = exports.rec2020rgb = exports.rec709rgb = exports.rgb = exports.rgbNormalized = exports.hex = void 0; | ||
var Convert_1 = __importDefault(require("./Convert")); | ||
var Modify_1 = __importDefault(require("./Modify")); | ||
var Harmony_1 = __importDefault(require("./Harmony")); | ||
var colorType = /** @class */ (function () { | ||
function colorType() { | ||
} | ||
colorType.prototype.to = function (type, args) { | ||
args = this.setArgs(args); | ||
type = type.toLowerCase().replace(/[^a-z0-9]/, ''); | ||
switch (type) { | ||
case 'rgb': | ||
case 'rgba': | ||
return this.torgb(args); | ||
case 'hex': | ||
return this.tohex(args); | ||
case 'rec709': | ||
case 'rgb709': | ||
case 'rec709rgb': | ||
case 'rgbrec709': | ||
return this.torec709(args); | ||
case 'rec2020': | ||
case 'rgb2020': | ||
case 'rec2020rgb': | ||
case 'rgbrec2020': | ||
return this.torec2020(args); | ||
case 'hsv': | ||
case 'hsva': | ||
return this.tohsv(args); | ||
case 'hsl': | ||
case 'hsla': | ||
return this.tohsl(args); | ||
case 'hsi': | ||
case 'hsia': | ||
return this.tohsi(args); | ||
case 'hsp': | ||
case 'hspa': | ||
case 'hspb': | ||
case 'hspba': | ||
return this.tohsp(args); | ||
case 'cmyk': | ||
return this.tocmyk(args); | ||
case 'yiq': | ||
return this.toyiq(args); | ||
case 'xyz': | ||
return this.toxyz(args); | ||
case 'xyy': | ||
return this.toxyy(args); | ||
case 'lab': | ||
return this.tolab(args); | ||
case 'luv': | ||
return this.toluv(args); | ||
case 'ypbpr': | ||
return this.toypbpr(args); | ||
case 'ycbcr': | ||
return this.toycbcr(args); | ||
default: | ||
throw new Error('Unable to find conversion path'); | ||
} | ||
}; | ||
colorType.prototype.modify = function (modification, args) { | ||
if (typeof args == 'undefined') | ||
args = {}; | ||
var og = this.constructor['name']; | ||
var ogargs = { | ||
round: args.round, | ||
bitDepth: this.bitDepth, | ||
normalize: this.normalized, | ||
colorSpace: this.colorSpace, | ||
referenceWhite: this.referenceWhite, | ||
kb: this.kb, | ||
kr: this.kr, | ||
pb: this.pb, | ||
pr: this.pr, | ||
yLower: this.yLower, | ||
yUpper: this.yUpper, | ||
cLower: this.cLower, | ||
cUpper: this.cUpper, | ||
gamma: this.gamma | ||
}; | ||
var ogalpha = this.a; | ||
var modified; | ||
switch (modification) { | ||
case 'blend': | ||
if (typeof args.with === 'undefined') { | ||
throw new Error('Missing second color to blend with'); | ||
} | ||
if (typeof args.method === 'undefined') { | ||
args.method = 'rgb'; | ||
} | ||
var tmpColor1 = void 0, tmpColor2 = void 0; | ||
switch (args.method) { | ||
case 'rgb': | ||
case 'rgba': | ||
case 'hex': | ||
tmpColor1 = this.torgb({ round: false }); | ||
tmpColor2 = args.with.torgb({ round: false }); | ||
modified = Modify_1.default.rgbBlend(tmpColor1, tmpColor2, args.amount, args.round); | ||
break; | ||
case 'hsv': | ||
case 'hsva': | ||
tmpColor1 = this.tohsv({ round: false }); | ||
tmpColor2 = args.with.tohsv({ round: false }); | ||
modified = Modify_1.default.hsvBlend(tmpColor1, tmpColor2, args.amount, args.round); | ||
break; | ||
default: | ||
throw new Error('Unrecognized blending method'); | ||
} | ||
break; | ||
case 'darken': | ||
case 'darker': | ||
if (typeof args.method === 'undefined') { | ||
args.method = 'hsl'; | ||
} | ||
switch (args.method) { | ||
case 'hsl': | ||
case 'hsla': | ||
case 'lightness': | ||
modified = Modify_1.default.hslDarken(this.tohsl({ round: false }), args.amount, args.round); | ||
break; | ||
case 'hsp': | ||
case 'hspa': | ||
case 'brightness': | ||
case 'perceived brightness': | ||
case 'perceived': | ||
case 'perceivedbrightness': | ||
modified = Modify_1.default.hspDarken(this.tohsp({ round: false }), args.amount, args.round); | ||
break; | ||
default: | ||
throw new Error('Unrecognized darken method'); | ||
} | ||
break; | ||
case 'lighten': | ||
case 'lighter': | ||
if (typeof args.method === 'undefined') { | ||
args.method = 'hsl'; | ||
} | ||
switch (args.method) { | ||
case 'hsl': | ||
case 'hsla': | ||
case 'lightness': | ||
modified = Modify_1.default.hslLighten(this.tohsl({ round: false }), args.amount, args.round); | ||
break; | ||
case 'hsp': | ||
case 'hspa': | ||
case 'brightness': | ||
case 'perceived brightness': | ||
case 'perceived': | ||
case 'perceivedbrightness': | ||
modified = Modify_1.default.hspLighten(this.tohsp({ round: false }), args.amount, args.round); | ||
break; | ||
default: | ||
throw new Error('Unrecognized lighten method'); | ||
} | ||
break; | ||
case 'desaturate': | ||
case 'desat': | ||
if (typeof args.method === 'undefined') { | ||
args.method = 'hsl'; | ||
} | ||
switch (args.method) { | ||
case 'hsv': | ||
case 'hsva': | ||
case 'value': | ||
modified = Modify_1.default.hsvDesaturate(this.tohsv({ round: false }), args.amount, args.round); | ||
break; | ||
case 'hsl': | ||
case 'hsla': | ||
case 'lightness': | ||
modified = Modify_1.default.hslDesaturate(this.tohsl({ round: false }), args.amount, args.round); | ||
break; | ||
default: | ||
throw new Error('Unrecognized desaturate method'); | ||
} | ||
break; | ||
case 'saturate': | ||
case 'sat': | ||
if (typeof args.method === 'undefined') { | ||
args.method = 'hsl'; | ||
} | ||
switch (args.method) { | ||
case 'hsv': | ||
case 'hsva': | ||
case 'value': | ||
modified = Modify_1.default.hsvSaturate(this.tohsv({ round: false }), args.amount, args.round); | ||
break; | ||
case 'hsl': | ||
case 'hsla': | ||
case 'lightness': | ||
modified = Modify_1.default.hslSaturate(this.tohsl({ round: false }), args.amount, args.round); | ||
break; | ||
default: | ||
throw new Error('Unrecognized saturate method'); | ||
} | ||
break; | ||
default: | ||
throw new Error('Unrecognized modify action'); | ||
} | ||
var ogModified = modified.to(og, ogargs); | ||
if (typeof ogalpha !== 'undefined') | ||
ogModified.a = ogalpha; // otherwise this gets lost on some modifications | ||
return ogModified; | ||
}; | ||
colorType.prototype.scheme = function (type, args) { | ||
if (typeof args === 'undefined') | ||
args = {}; | ||
var og = this.constructor['name']; | ||
var ogargs = { | ||
round: args.round, | ||
bitDepth: this.bitDepth, | ||
normalize: this.normalized, | ||
colorSpace: this.colorSpace, | ||
referenceWhite: this.referenceWhite, | ||
kb: this.kb, | ||
kr: this.kr, | ||
pb: this.pb, | ||
pr: this.pr, | ||
yLower: this.yLower, | ||
yUpper: this.yUpper, | ||
cLower: this.cLower, | ||
cUpper: this.cUpper, | ||
gamma: this.gamma | ||
}; | ||
var ogalpha = this.a; | ||
var intScheme; | ||
var distance; | ||
type = type.toLowerCase(); | ||
switch (type) { | ||
case 'complement': | ||
case 'comp': | ||
intScheme = Harmony_1.default.complement(this.to('hsv', { round: false })); | ||
break; | ||
case 'analogous': | ||
intScheme = Harmony_1.default.analogous(this.to('hsv', { round: false }), args.angle); | ||
break; | ||
case 'split complement': | ||
case 'splitcomplement': | ||
case 'split': | ||
intScheme = Harmony_1.default.splitComplement(this.to('hsv', { round: false }), args.angle); | ||
break; | ||
case 'triadic': | ||
case 'triad': | ||
case 'triangle': | ||
intScheme = Harmony_1.default.triadic(this.to('hsv', { round: false }), args.angle); | ||
break; | ||
case 'tetradic': | ||
case 'tetrad': | ||
intScheme = Harmony_1.default.tetradic(this.to('hsv', { round: false }), args.angle); | ||
break; | ||
case 'square': | ||
intScheme = Harmony_1.default.square(this.to('hsv', { round: false })); | ||
break; | ||
case 'shade': | ||
case 'shades': | ||
case 'darken': | ||
if (typeof args.colors === 'undefined') { | ||
throw new Error('Must specify number of colors to include in scheme'); | ||
} | ||
distance = typeof args.distanceToBlack === 'undefined' ? args.distance : args.distanceToBlack; | ||
intScheme = Harmony_1.default.shade(this.to('hsl', { round: false }), args.colors, distance); | ||
break; | ||
case 'tint': | ||
case 'tints': | ||
case 'lighten': | ||
if (typeof args.colors === 'undefined') { | ||
throw new Error('Must specify number of colors to include in scheme'); | ||
} | ||
distance = typeof args.distanceToWhite === 'undefined' ? args.distance : args.distanceToWhite; | ||
intScheme = Harmony_1.default.tint(this.to('hsl', { round: false }), args.colors, distance); | ||
break; | ||
case 'tintshade': | ||
case 'tintsshades': | ||
case 'shadetint': | ||
case 'shadestints': | ||
case 'lightdark': | ||
case 'darklight': | ||
if (typeof args.colors === 'undefined') { | ||
throw new Error('Must specify number of colors to include in scheme'); | ||
} | ||
distance = typeof args.distanceToWhite === 'undefined' ? args.distance : args.distanceToWhite; | ||
intScheme = Harmony_1.default.shadetint(this.to('hsl', { round: false }), args.colors, distance, args.distanceToBlack); | ||
break; | ||
default: | ||
throw new Error('Unrecognized color scheme'); | ||
} | ||
var ogScheme = []; | ||
intScheme.forEach(function (color) { | ||
var ogColor = color.to(og, ogargs); | ||
if (typeof ogalpha !== 'undefined') | ||
ogColor.a = ogalpha; // otherwise this gets lost on some modifications | ||
ogScheme.push(ogColor); | ||
}); | ||
return ogScheme; | ||
}; | ||
colorType.prototype.css = function () { | ||
return 'not yet implemented'; | ||
}; | ||
colorType.prototype.torgb = function (args) { | ||
var rgbOverridden = new rgb(0, 0, 0); | ||
return rgbOverridden; | ||
}; | ||
colorType.prototype.torec709 = function (args) { | ||
if (typeof args.bitRate !== 'undefined') | ||
args.bitDepth = args.bitRate; | ||
else if (typeof args.bitDepth === 'undefined') | ||
args.bitDepth = 8; | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2rec709rgb(rgb, args.round, args.bitDepth); | ||
}; | ||
colorType.prototype.torec2020 = function (args) { | ||
if (typeof args.bitRate !== 'undefined') | ||
args.bitDepth = args.bitRate; | ||
else if (typeof args.bitDepth === 'undefined') | ||
args.bitDepth = 10; | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2rec2020rgb(rgb, args.round, args.bitDepth); | ||
}; | ||
colorType.prototype.tohex = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2hex(rgb); | ||
}; | ||
colorType.prototype.tohsv = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2hsv(rgb, args.round); | ||
}; | ||
colorType.prototype.tohsl = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2hsl(rgb, args.round); | ||
}; | ||
colorType.prototype.tohsi = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2hsi(rgb, args.round); | ||
}; | ||
colorType.prototype.tohsp = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2hsp(rgb, args.round, args.pb, args.pr); | ||
}; | ||
colorType.prototype.tocmyk = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2cmyk(rgb, args.round); | ||
}; | ||
colorType.prototype.toyiq = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2yiq(rgb, args.normalize, args.round); | ||
}; | ||
colorType.prototype.toxyz = function (args) { | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2xyz(rgb, args.colorSpace, args.referenceWhite); | ||
}; | ||
colorType.prototype.toxyy = function (args) { | ||
return Convert_1.default.xyz2xyy(this.toxyz(args)); | ||
}; | ||
colorType.prototype.tolab = function (args) { | ||
return Convert_1.default.xyz2lab(this.toxyz(args)); | ||
}; | ||
colorType.prototype.toluv = function (args) { | ||
return Convert_1.default.xyz2luv(this.toxyz(args)); | ||
}; | ||
colorType.prototype.toypbpr = function (args) { | ||
if (typeof args.kb === 'undefined' || typeof args.kr === 'undefined') { | ||
throw new Error('Missing arguments kb and kr'); | ||
} | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2ypbpr(rgb, args.kb, args.kr); | ||
}; | ||
colorType.prototype.toycbcr = function (args) { | ||
if (typeof args.kb === 'undefined' || typeof args.kr === 'undefined') { | ||
throw new Error('Missing arguments kb and kr'); | ||
} | ||
var rgb = this.torgb(args); | ||
return Convert_1.default.rgb2ycbcr(rgb, args.kb, args.kr); | ||
}; | ||
colorType.prototype.setArgs = function (args) { | ||
if (typeof args == 'undefined') | ||
args = {}; | ||
else if (typeof args.bitDepth === 'undefined' && typeof args.bitRate !== 'undefined') { | ||
args.bitDepth = args.bitRate; | ||
} | ||
return args; | ||
}; | ||
/** | ||
* Range check to make sure numeric value is within lower and upper limits | ||
* Throws error on fail, returns nothing | ||
* | ||
* @param {number} value | ||
* @param {number|boolean} lowerLimit number or false | ||
* @param {number|boolean} upperLimit number or false | ||
* @param {string} msg error message if fail | ||
*/ | ||
colorType.prototype.valueRangeCheck = function (value, lowerLimit, upperLimit, msg) { | ||
if (!isFinite(value)) { | ||
throw new Error('Invalid color value'); | ||
} | ||
if (lowerLimit && upperLimit && lowerLimit >= upperLimit) { | ||
throw new Error('Invalid range (lower limit must exceed upper limit)'); | ||
} | ||
if ((lowerLimit && value < lowerLimit) || (upperLimit && value > upperLimit)) { | ||
throw new Error(typeof msg !== 'undefined' ? msg : 'Color value out of range'); | ||
} | ||
}; | ||
return colorType; | ||
}()); | ||
exports.colorType = colorType; | ||
var ColorType_1 = require("./ColorType"); | ||
var hex = /** @class */ (function (_super) { | ||
@@ -471,3 +71,3 @@ __extends(hex, _super); | ||
return hex; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.hex = hex; | ||
@@ -494,3 +94,3 @@ var rgbNormalized = /** @class */ (function (_super) { | ||
return rgbNormalized; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.rgbNormalized = rgbNormalized; | ||
@@ -519,3 +119,3 @@ var rgb = /** @class */ (function (_super) { | ||
rgb.prototype.torgb = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.r = Math.round(this.r); | ||
@@ -529,3 +129,3 @@ this.g = Math.round(this.g); | ||
return rgb; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.rgb = rgb; | ||
@@ -560,3 +160,3 @@ var rec709rgb = /** @class */ (function (_super) { | ||
rec709rgb.prototype.torec709 = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.r = Math.round(this.r); | ||
@@ -570,3 +170,3 @@ this.g = Math.round(this.g); | ||
return rec709rgb; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.rec709rgb = rec709rgb; | ||
@@ -601,3 +201,3 @@ var rec2020rgb = /** @class */ (function (_super) { | ||
rec2020rgb.prototype.torec2020 = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.r = Math.round(this.r); | ||
@@ -611,3 +211,3 @@ this.g = Math.round(this.g); | ||
return rec2020rgb; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.rec2020rgb = rec2020rgb; | ||
@@ -633,3 +233,3 @@ var hsv = /** @class */ (function (_super) { | ||
hsv.prototype.tohsv = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.h = Math.round(this.h); | ||
@@ -649,3 +249,3 @@ this.s = Math.round(this.s); | ||
return hsv; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.hsv = hsv; | ||
@@ -674,3 +274,3 @@ var hsl = /** @class */ (function (_super) { | ||
hsl.prototype.tohsl = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.h = Math.round(this.h); | ||
@@ -687,3 +287,3 @@ this.s = Math.round(this.s); | ||
return hsl; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.hsl = hsl; | ||
@@ -715,3 +315,3 @@ var hsi = /** @class */ (function (_super) { | ||
hsi.prototype.tohsi = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.h = Math.round(this.h); | ||
@@ -725,3 +325,3 @@ this.s = Math.round(this.s); | ||
return hsi; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.hsi = hsi; | ||
@@ -755,3 +355,3 @@ var hsp = /** @class */ (function (_super) { | ||
hsp.prototype.tohsb = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.h = Math.round(this.h); | ||
@@ -765,3 +365,3 @@ this.s = Math.round(this.s); | ||
return hsp; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.hsp = hsp; | ||
@@ -786,3 +386,3 @@ var cmyk = /** @class */ (function (_super) { | ||
cmyk.prototype.tocmyk = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.c = Math.round(this.c); | ||
@@ -796,3 +396,3 @@ this.m = Math.round(this.m); | ||
return cmyk; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.cmyk = cmyk; | ||
@@ -832,3 +432,3 @@ var yiq = /** @class */ (function (_super) { | ||
yiq.prototype.toyiq = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.y = Math.round(this.y); | ||
@@ -841,3 +441,3 @@ this.i = Math.round(this.i); | ||
return yiq; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.yiq = yiq; | ||
@@ -868,3 +468,3 @@ var xyz = /** @class */ (function (_super) { | ||
return xyz; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.xyz = xyz; | ||
@@ -894,3 +494,3 @@ var xyy = /** @class */ (function (_super) { | ||
return xyy; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.xyy = xyy; | ||
@@ -926,3 +526,3 @@ var lab = /** @class */ (function (_super) { | ||
lab.prototype.tolab = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.l = Math.round(this.l); | ||
@@ -935,3 +535,3 @@ this.a = Math.round(this.a); | ||
return lab; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.lab = lab; | ||
@@ -969,3 +569,3 @@ var luv = /** @class */ (function (_super) { | ||
luv.prototype.toluv = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.l = Math.round(this.l); | ||
@@ -978,3 +578,3 @@ this.u = Math.round(this.u); | ||
return luv; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.luv = luv; | ||
@@ -1011,3 +611,3 @@ var ypbpr = /** @class */ (function (_super) { | ||
return ypbpr; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.ypbpr = ypbpr; | ||
@@ -1048,3 +648,3 @@ var ycbcr = /** @class */ (function (_super) { | ||
ycbcr.prototype.toycbcr = function (args) { | ||
if (args.round) { | ||
if (args.round !== false) { | ||
this.y = Math.round(this.y); | ||
@@ -1057,3 +657,3 @@ this.cb = Math.round(this.cb); | ||
return ycbcr; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.ycbcr = ycbcr; | ||
@@ -1072,3 +672,3 @@ var nm = /** @class */ (function (_super) { | ||
return nm; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.nm = nm; | ||
@@ -1087,3 +687,3 @@ var kelvin = /** @class */ (function (_super) { | ||
return kelvin; | ||
}(colorType)); | ||
}(ColorType_1.colorType)); | ||
exports.kelvin = kelvin; |
@@ -372,2 +372,18 @@ import * as Colors from './Colors'; | ||
* Convert a color temperature in Kelvin to RGB | ||
* Adapted from 'RGB VALUES FOR HOT OBJECTS' by William T. Bridgman, NASA, 2000 | ||
* http://www.physics.sfasu.edu/astro/color/blackbodyc.txt | ||
* | ||
* A black body approximation is used where the temperature, | ||
* T, is given in Kelvin. The XYZ values are determined by | ||
* "integrating" the product of the wavelength distribution of | ||
* energy and the XYZ functions for a uniform source. | ||
* | ||
* @param {Colors.kelvin} kelvin Color temperature in degrees Kelvin; must fall between 1000 and 40000 | ||
* @param {boolean} [round=true] | ||
* @param {number} [bitDepth=8] | ||
* @return {Colors.rgb} | ||
*/ | ||
static kelvin2rgb(kelvin: Colors.kelvin, round?: boolean, bitDepth?: number): Colors.rgb; | ||
/** | ||
* Convert a color temperature in Kelvin to RGB | ||
* Not accurate for scientific purposes | ||
@@ -382,3 +398,3 @@ * Original algorithm from: | ||
*/ | ||
static kelvin2rgb(kelvin: Colors.kelvin, round?: boolean, bitDepth?: number): Colors.rgb; | ||
static kelvin2rgb_deprecated(kelvin: Colors.kelvin, round?: boolean, bitDepth?: number): Colors.rgb; | ||
/** | ||
@@ -385,0 +401,0 @@ * Convert HEX to RGB |
@@ -1484,2 +1484,79 @@ "use strict"; | ||
* Convert a color temperature in Kelvin to RGB | ||
* Adapted from 'RGB VALUES FOR HOT OBJECTS' by William T. Bridgman, NASA, 2000 | ||
* http://www.physics.sfasu.edu/astro/color/blackbodyc.txt | ||
* | ||
* A black body approximation is used where the temperature, | ||
* T, is given in Kelvin. The XYZ values are determined by | ||
* "integrating" the product of the wavelength distribution of | ||
* energy and the XYZ functions for a uniform source. | ||
* | ||
* @param {Colors.kelvin} kelvin Color temperature in degrees Kelvin; must fall between 1000 and 40000 | ||
* @param {boolean} [round=true] | ||
* @param {number} [bitDepth=8] | ||
* @return {Colors.rgb} | ||
*/ | ||
Convert.kelvin2rgb = function (kelvin, round, bitDepth) { | ||
if (round === void 0) { round = true; } | ||
if (bitDepth === void 0) { bitDepth = 8; } | ||
// initialize accumulators | ||
var xx = 0, yy = 0, zz = 0; | ||
var con = 1240.0 / 8.617e-5; | ||
var dis, wavelength, weight; | ||
var band, nbands = Reference_1.xyzWavelengths.vectors.length; | ||
// loop over wavelength bands | ||
// integration by trapezoid method | ||
for (band = 0; band < nbands; band++) { | ||
weight = (band == 0 || band == nbands - 1) ? 0.5 : 1; | ||
wavelength = 380 + band * 5; | ||
// generate a black body spectrum | ||
dis = 3.74183e-16 * (1 / Math.pow(wavelength, 5)) / (Math.exp(con / (wavelength * kelvin.k)) - 1); | ||
// simple integration over bands | ||
xx += weight * dis * Reference_1.xyzWavelengths.vectors[band][0]; | ||
yy += weight * dis * Reference_1.xyzWavelengths.vectors[band][1]; | ||
zz += weight * dis * Reference_1.xyzWavelengths.vectors[band][2]; | ||
} | ||
// re-normalize | ||
var xxyyzzMax = Math.max(xx, yy, zz); | ||
var x = xx / xxyyzzMax; | ||
var y = yy / xxyyzzMax; | ||
var z = zz / xxyyzzMax; | ||
var xr = Reference_1.xyzWavelengths.chromaticityCoordinates.r[0]; | ||
var yr = Reference_1.xyzWavelengths.chromaticityCoordinates.r[1]; | ||
var zr = 1 - xr - yr; | ||
var xg = Reference_1.xyzWavelengths.chromaticityCoordinates.g[0]; | ||
var yg = Reference_1.xyzWavelengths.chromaticityCoordinates.g[1]; | ||
var zg = 1 - xg - yg; | ||
var xb = Reference_1.xyzWavelengths.chromaticityCoordinates.b[0]; | ||
var yb = Reference_1.xyzWavelengths.chromaticityCoordinates.b[1]; | ||
var zb = 1 - xb - yb; | ||
// convert to rgb | ||
var denominator = (xr * yg - xg * yr) * zb + (xb * yr - xr * yb) * zg + (xg * yb - xb * yg) * zr; | ||
var r = ((x * yg - xg * y) * zb + (xg * yb - xb * yg) * z + (xb * y - x * yb) * zg) / denominator; | ||
var g = ((xr * y - x * yr) * zb + (xb * yr - xr * yb) * z + (x * yb - xb * y) * zr) / denominator; | ||
var b = ((xr * yg - xg * yr) * z + (x * yr - xr * y) * zg + (xg * y - x * yg) * zr) / denominator; | ||
r = Math.min(Math.max(r, 0), 1); | ||
g = Math.min(Math.max(g, 0), 1); | ||
b = Math.min(Math.max(b, 0), 1); | ||
// adjust gamma | ||
var rangeMax = Math.max(1.0e-10, r, g, b); | ||
r = Math.pow(r / rangeMax, Reference_1.xyzWavelengths.gamma); | ||
g = Math.pow(g / rangeMax, Reference_1.xyzWavelengths.gamma); | ||
b = Math.pow(b / rangeMax, Reference_1.xyzWavelengths.gamma); | ||
// adjust to given bit depth | ||
var depth = (Math.pow(2, bitDepth)) - 1; | ||
r *= depth; | ||
g *= depth; | ||
b *= depth; | ||
r = Math.min(r, depth); | ||
g = Math.min(g, depth); | ||
b = Math.min(b, depth); | ||
if (round) { | ||
r = Math.round(r); | ||
g = Math.round(g); | ||
b = Math.round(b); | ||
} | ||
return new Colors.rgb(r, g, b, depth, bitDepth); | ||
}; | ||
/** | ||
* Convert a color temperature in Kelvin to RGB | ||
* Not accurate for scientific purposes | ||
@@ -1494,3 +1571,3 @@ * Original algorithm from: | ||
*/ | ||
Convert.kelvin2rgb = function (kelvin, round, bitDepth) { | ||
Convert.kelvin2rgb_deprecated = function (kelvin, round, bitDepth) { | ||
if (round === void 0) { round = true; } | ||
@@ -1497,0 +1574,0 @@ if (bitDepth === void 0) { bitDepth = 8; } |
@@ -52,6 +52,49 @@ import * as Colors from './Colors'; | ||
static square(hsv: Colors.hsv): Array<Colors.hsv>; | ||
/** | ||
* Returns an array of colors of a darker shade | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToBlack=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
*/ | ||
static shade(hsl: Colors.hsl, colors: number, distanceToBlack?: number): Colors.hsl[]; | ||
/** | ||
* Returns an array of colors of a lighter tint | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToWhite=1] 0-1, where 1 is all the way to white | ||
* @returns | ||
*/ | ||
static tint(hsl: Colors.hsl, colors: number, distanceToWhite?: number): Colors.hsl[]; | ||
/** | ||
* Returns an array of colors of darker shades and lighter tints | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distance=1] 0-1, where 1 is all the way to closest bound OR white, if distanceShade given | ||
* @param {number} [distanceShade=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
*/ | ||
static shadetint(hsl: Colors.hsl, colors: number, distance?: number, distanceShade?: number): Colors.hsl[]; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via rgb | ||
* | ||
* @param {Colors.rgb} color1 | ||
* @param {Colors.rgb} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
*/ | ||
static rgbGradient(color1: Colors.rgb, color2: Colors.rgb, colors: number): Colors.rgb[]; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via hsv | ||
* | ||
* @param {Colors.hsv} color1 | ||
* @param {Colors.hsv} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
*/ | ||
static hsvGradient(color1: Colors.hsv, color2: Colors.hsv, colors: number): Colors.hsv[]; | ||
} | ||
export = Harmony; |
@@ -127,2 +127,10 @@ "use strict"; | ||
}; | ||
/** | ||
* Returns an array of colors of a darker shade | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToBlack=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
*/ | ||
Harmony.shade = function (hsl, colors, distanceToBlack) { | ||
@@ -140,2 +148,10 @@ if (distanceToBlack === void 0) { distanceToBlack = 1; } | ||
}; | ||
/** | ||
* Returns an array of colors of a lighter tint | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToWhite=1] 0-1, where 1 is all the way to white | ||
* @returns | ||
*/ | ||
Harmony.tint = function (hsl, colors, distanceToWhite) { | ||
@@ -153,2 +169,11 @@ if (distanceToWhite === void 0) { distanceToWhite = 1; } | ||
}; | ||
/** | ||
* Returns an array of colors of darker shades and lighter tints | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distance=1] 0-1, where 1 is all the way to closest bound OR white, if distanceShade given | ||
* @param {number} [distanceShade=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
*/ | ||
Harmony.shadetint = function (hsl, colors, distance, distanceShade) { | ||
@@ -189,4 +214,48 @@ if (distance === void 0) { distance = 1; } | ||
}; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via rgb | ||
* | ||
* @param {Colors.rgb} color1 | ||
* @param {Colors.rgb} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
*/ | ||
Harmony.rgbGradient = function (color1, color2, colors) { | ||
if (colors < 2) { | ||
throw new Error('Unable to generate gradient with less than two colors'); | ||
} | ||
var inBetweenColors = colors - 2; | ||
var gradient = []; | ||
gradient.push(color1); | ||
for (var i = 0; i < inBetweenColors; i++) { | ||
var amount = (i + 1) / (inBetweenColors + 1); | ||
gradient.push(Modify_1.default.rgbBlend(color1, color2, amount, false)); | ||
} | ||
gradient.push(color2); | ||
return gradient; | ||
}; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via hsv | ||
* | ||
* @param {Colors.hsv} color1 | ||
* @param {Colors.hsv} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
*/ | ||
Harmony.hsvGradient = function (color1, color2, colors) { | ||
if (colors < 2) { | ||
throw new Error('Unable to generate gradient with less than two colors'); | ||
} | ||
var inBetweenColors = colors - 2; | ||
var gradient = []; | ||
gradient.push(color1); | ||
for (var i = 0; i < inBetweenColors; i++) { | ||
var amount = (i + 1) / (inBetweenColors + 1); | ||
gradient.push(Modify_1.default.hsvBlend(color1, color2, amount, false)); | ||
} | ||
gradient.push(color2); | ||
return gradient; | ||
}; | ||
return Harmony; | ||
}()); | ||
module.exports = Harmony; |
@@ -1,2 +0,2 @@ | ||
import * as Colors from './Colors'; | ||
import { colorType } from './ColorType'; | ||
interface newColorArgs { | ||
@@ -18,8 +18,8 @@ bitDepth?: number; | ||
interface colorDef { | ||
from(type: string, value: number[] | string, args?: newColorArgs): Colors.colorType; | ||
from(type: string, value: number[] | string, args?: newColorArgs): colorType; | ||
} | ||
declare class Color implements colorDef { | ||
from(type: string, value: number[] | number | string, args?: newColorArgs): Colors.colorType; | ||
from(type: string, value: number[] | number | string, args?: newColorArgs): colorType; | ||
} | ||
declare const _default: Color; | ||
export = _default; |
@@ -529,1 +529,18 @@ /** | ||
}; | ||
/** | ||
* William T. Bridgman, NASA; Dan Bruton, SFASU. "RGB Values for Hot Objects". (2000) | ||
* http://www.physics.sfasu.edu/astro/color/blackbodyc.txt | ||
* | ||
* CIE Color Matching Vectors (x_bar,y_bar,z_bar) | ||
* for wavelenghts in 5 nm increments from 380 nm to 780 nm. | ||
*/ | ||
export declare const xyzWavelengths: { | ||
gamma: number; | ||
chromaticityCoordinates: { | ||
r: number[]; | ||
g: number[]; | ||
b: number[]; | ||
w: number[]; | ||
}; | ||
vectors: number[][]; | ||
}; |
@@ -18,3 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.colorSpaces = exports.stdIlluminants = exports.cieK = exports.cieE = void 0; | ||
exports.xyzWavelengths = exports.colorSpaces = exports.stdIlluminants = exports.cieK = exports.cieE = void 0; | ||
/** | ||
@@ -752,1 +752,100 @@ * CIE Constants of L* Function | ||
}; | ||
/** | ||
* William T. Bridgman, NASA; Dan Bruton, SFASU. "RGB Values for Hot Objects". (2000) | ||
* http://www.physics.sfasu.edu/astro/color/blackbodyc.txt | ||
* | ||
* CIE Color Matching Vectors (x_bar,y_bar,z_bar) | ||
* for wavelenghts in 5 nm increments from 380 nm to 780 nm. | ||
*/ | ||
exports.xyzWavelengths = { | ||
gamma: 0.8, | ||
chromaticityCoordinates: { | ||
r: [0.64, 0.33], | ||
g: [0.29, 0.60], | ||
b: [0.15, 0.06], | ||
w: [0.3127, 0.3291] | ||
}, | ||
vectors: [ | ||
[0.0014, 0.0000, 0.0065], | ||
[0.0022, 0.0001, 0.0105], | ||
[0.0042, 0.0001, 0.0201], | ||
[0.0076, 0.0002, 0.0362], | ||
[0.0143, 0.0004, 0.0679], | ||
[0.0232, 0.0006, 0.1102], | ||
[0.0435, 0.0012, 0.2074], | ||
[0.0776, 0.0022, 0.3713], | ||
[0.1344, 0.0040, 0.6456], | ||
[0.2148, 0.0073, 1.0391], | ||
[0.2839, 0.0116, 1.3856], | ||
[0.3285, 0.0168, 1.6230], | ||
[0.3483, 0.0230, 1.7471], | ||
[0.3481, 0.0298, 1.7826], | ||
[0.3362, 0.0380, 1.7721], | ||
[0.3187, 0.0480, 1.7441], | ||
[0.2908, 0.0600, 1.6692], | ||
[0.2511, 0.0739, 1.5281], | ||
[0.1954, 0.0910, 1.2876], | ||
[0.1421, 0.1126, 1.0419], | ||
[0.0956, 0.1390, 0.8130], | ||
[0.0580, 0.1693, 0.6162], | ||
[0.0320, 0.2080, 0.4652], | ||
[0.0147, 0.2586, 0.3533], | ||
[0.0049, 0.3230, 0.2720], | ||
[0.0024, 0.4073, 0.2123], | ||
[0.0093, 0.5030, 0.1582], | ||
[0.0291, 0.6082, 0.1117], | ||
[0.0633, 0.7100, 0.0782], | ||
[0.1096, 0.7932, 0.0573], | ||
[0.1655, 0.8620, 0.0422], | ||
[0.2257, 0.9149, 0.0298], | ||
[0.2904, 0.9540, 0.0203], | ||
[0.3597, 0.9803, 0.0134], | ||
[0.4334, 0.9950, 0.0087], | ||
[0.5121, 1.0000, 0.0057], | ||
[0.5945, 0.9950, 0.0039], | ||
[0.6784, 0.9786, 0.0027], | ||
[0.7621, 0.9520, 0.0021], | ||
[0.8425, 0.9154, 0.0018], | ||
[0.9163, 0.8700, 0.0017], | ||
[0.9786, 0.8163, 0.0014], | ||
[1.0263, 0.7570, 0.0011], | ||
[1.0567, 0.6949, 0.0010], | ||
[1.0622, 0.6310, 0.0008], | ||
[1.0456, 0.5668, 0.0006], | ||
[1.0026, 0.5030, 0.0003], | ||
[0.9384, 0.4412, 0.0002], | ||
[0.8544, 0.3810, 0.0002], | ||
[0.7514, 0.3210, 0.0001], | ||
[0.6424, 0.2650, 0.0000], | ||
[0.5419, 0.2170, 0.0000], | ||
[0.4479, 0.1750, 0.0000], | ||
[0.3608, 0.1382, 0.0000], | ||
[0.2835, 0.1070, 0.0000], | ||
[0.2187, 0.0816, 0.0000], | ||
[0.1649, 0.0610, 0.0000], | ||
[0.1212, 0.0446, 0.0000], | ||
[0.0874, 0.0320, 0.0000], | ||
[0.0636, 0.0232, 0.0000], | ||
[0.0468, 0.0170, 0.0000], | ||
[0.0329, 0.0119, 0.0000], | ||
[0.0227, 0.0082, 0.0000], | ||
[0.0158, 0.0057, 0.0000], | ||
[0.0114, 0.0041, 0.0000], | ||
[0.0081, 0.0029, 0.0000], | ||
[0.0058, 0.0021, 0.0000], | ||
[0.0041, 0.0015, 0.0000], | ||
[0.0029, 0.0010, 0.0000], | ||
[0.0020, 0.0007, 0.0000], | ||
[0.0014, 0.0005, 0.0000], | ||
[0.0010, 0.0004, 0.0000], | ||
[0.0007, 0.0002, 0.0000], | ||
[0.0005, 0.0002, 0.0000], | ||
[0.0003, 0.0001, 0.0000], | ||
[0.0002, 0.0001, 0.0000], | ||
[0.0002, 0.0001, 0.0000], | ||
[0.0001, 0.0000, 0.0000], | ||
[0.0001, 0.0000, 0.0000], | ||
[0.0001, 0.0000, 0.0000], | ||
[0.0000, 0.0000, 0.0000] | ||
] | ||
}; |
{ | ||
"name": "chromaticity-color-utilities", | ||
"version": "0.1.13-alpha", | ||
"version": "0.2.0-alpha", | ||
"description": "Color utilities for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "dist/main.js", |
183
README.md
@@ -43,2 +43,3 @@ # chromaticity-color-utilities | ||
* [Tint & Shade Scale](#tint--shade-scale) | ||
* [Gradients](#gradients) | ||
* [Mathematics](#mathematics) | ||
@@ -69,3 +70,3 @@ * [Normalizing RGB](#normalizing-rgb) | ||
* [XYZ to xyY](#xyz-to-xyy) | ||
* [xyY to XYZ](#xyy-to-xyz) | ||
* [xyY to XYZ](#xyy-to-xyz)te | ||
* [XYZ to L\*a\*b\*](#xyz-to-lab) | ||
@@ -78,2 +79,3 @@ * [L\*a\*b\* to XYZ](#lab-to-xyz) | ||
* [YCbCr to YPbPr](#ycbcr-to-ypbpr) | ||
* [Temperature (Kelvin) to RGB](#temperature-kelvin-to-rgb) | ||
* [Compiling from Source](#compiling-from-source) | ||
@@ -648,3 +650,3 @@ * [To Do List](#to-do-list) | ||
This is a one-way approximatin. There is no `.to('kelvin')` method option. | ||
This is a one-way approximation. There is no `.to('kelvin')` method option. This method uses trapezoid integration to sum the wavelength distribution of energy through a black body tensor. While an approximation, it is a rather accurate one. Temperatures above 10k°K may be less accurate, but the method allows for temperatures up to 40k°K | ||
@@ -655,4 +657,12 @@ ```ts | ||
// e.g. | ||
let color1 = Color.from('kelvin',3500).to('rgb') | ||
// rgb { r: 255, g: 193, b: 141, a: 255, bitDepth: 8, max: 255 } | ||
let color1 = Color.from('kelvin',1000).to('rgb') | ||
// rgb { r: 255, g: 13, b: 0, a: 255, bitDepth: 8, max: 255 } | ||
let color1 = Color.from('kelvin',2000).to('rgb') | ||
// rgb { r: 255, g: 169, b: 7, a: 255, bitDepth: 8, max: 255 } | ||
let color1 = Color.from('kelvin',4000).to('rgb') | ||
// rgb { r: 240, g: 255, b: 174, a: 255, bitDepth: 8, max: 255 } | ||
let color1 = Color.from('kelvin',8000).to('rgb') | ||
// rgb { r: 143, g: 232, b: 255, a: 255, bitDepth: 8, max: 255 } | ||
let color1 = Color.from('kelvin',10000).to('rgb') | ||
// rgb { r: 121, g: 210, b: 255, a: 255, bitDepth: 8, max: 255 } | ||
``` | ||
@@ -1009,2 +1019,41 @@ | ||
### Gradients | ||
Generate an array of colors from color1 to color2. Methods available are `rgb` and `hsv`. | ||
```ts | ||
.scheme('gradient',{ | ||
color2: colorType, // REQUIRED, second color, of any type, to blend with | ||
colors: number, // REQUIRED, number of colors to be returned, must be > 2 | ||
method: string, // optional, defaults to 'rgb' | ||
round: boolean // optional, defaults to true | ||
}) | ||
// e.g. | ||
let gradient1 = Color.from('rgb',[255,0,255]).scheme('gradient',{ | ||
with: Color.from('hex',0x00FF00), | ||
colors: 5 | ||
}) | ||
// [ | ||
// rgb { r: 255, g: 0, b: 255, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 191, g: 64, b: 191, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 128, g: 128, b: 128, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 64, g: 191, b: 64, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 0, g: 255, b: 0, a: 255, bitDepth: 8, max: 255 } | ||
// ] | ||
let gradient1 = Color.from('rgb',[255,0,255]).scheme('gradient',{ | ||
with: Color.from('hex','00ff00'), | ||
colors: 5, | ||
method: 'hsv' | ||
}) | ||
// [ | ||
// rgb { r: 255, g: 0, b: 255, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 64, g: 0, b: 255, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 0, g: 128, b: 255, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 0, g: 255, b: 191, a: 255, bitDepth: 8, max: 255 }, | ||
// rgb { r: 0, g: 255, b: 0, a: 255, bitDepth: 8, max: 255 } | ||
// ] | ||
``` | ||
## Mathematics | ||
@@ -1069,2 +1118,13 @@ | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsl-h.png) | ||
<!-- | ||
H=\begin{cases} | ||
0 & \text{ if } C=0 \\ | ||
\frac{G - B}{C} & \text{ if } V=R \\ | ||
\frac{B - R}{C} + 2 & \text{ if } V=G \\ | ||
\frac{R - G}{C} + 4 & \text{ if } V=B \\ | ||
\end{cases} | ||
--> | ||
### HSL to RGB | ||
@@ -1694,2 +1754,90 @@ | ||
### Temperature (Kelvin) to RGB | ||
Where v is a tensor of XYZ color matching vectors for wavelengths in 5nm increments from 380nm to 780nm and T is the given temperature in Kelvin. Trapezoid integration is used to sum the the XYZ values from a black body spectrum generated from the tensor v based on temperature. <sup>[[9]](#references)</sup> | ||
In other words, a black body emission spectrum is generated for a given temperature, from which a summation of each XYZ set of values in the spectrum, normalized, gives an average XYZ, the mish-mash of wavelengths that we perceive as a single color. Then that XYZ color is simply converted to RGB. | ||
I'm not 100% positive on my notation—f(v<sub>ki</sub>) is a function of each index of each vector in the tensor v. | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/kelvin-to-xyz.png) | ||
C is the set of chromaticity coordinates associated with the black body tensor. <sup>[[9]](#references)</sup> The associated coordinates for white align with a D65 standard illuminant, but I've been unable to find any further information regarding the given RGB tristimulus values. | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/kelvin-xyz-to-rgb.png) | ||
<!-- | ||
KELVIN TO XYZ | ||
\begin{align*} | ||
v &= \begin{bmatrix}\bar{X}_1\\\bar{Y}_1\\\bar{Z}_1\end{bmatrix}_1, | ||
\begin{bmatrix}\bar{X}_2\\\bar{Y}_2\\\bar{Z}_2\end{bmatrix}_2 | ||
\cdots | ||
\begin{bmatrix}\bar{X}_n\\\bar{Y}_n\\\bar{Z}_n\end{bmatrix}_n | ||
\\ | ||
\:\\ | ||
c &= \frac{1240}{8.617e^{-5}} \\ | ||
\:\\ | ||
\lambda &= 380 + 5k \\ | ||
f(v_k_i) &= | ||
(3.74183e^{-16} \cdot \frac{\frac{1}{\lambda^5}}{e^{(c * T)} - 1}) | ||
\cdot v_k_i \\ | ||
\begin{bmatrix}X'\\Y'\\Z'\end{bmatrix} &= | ||
\sum^N_{k=1} | ||
\frac{f(\vec{v_{k-1}}) + f(\vec{v_{k}})}{2} | ||
\Delta \vec{v_k} \\ | ||
\begin{bmatrix}X\\Y\\Z\end{bmatrix} &= | ||
\begin{bmatrix}X'\\Y'\\Z'\end{bmatrix} \cdot \frac{1}{max(X',Y',Z')} | ||
\end{align*} | ||
XYZ TO RGB | ||
\begin{align*} | ||
C &= | ||
\begin{bmatrix} | ||
X_R & X_G & X_B \\ | ||
Y_R & Y_G & Y_B \\ | ||
Z_R & Z_G & Z_B | ||
\end{bmatrix} | ||
= | ||
\begin{bmatrix} | ||
0.64 & 0.29 & 0.15 \\ | ||
0.33 & 0.60 & 0.06 \\ | ||
0.03 & 0.11 & 0.79 | ||
\end{bmatrix} | ||
\\ | ||
\vec{p} &= | ||
\begin{bmatrix} | ||
R''\\G''\\B'' | ||
\end{bmatrix} | ||
= | ||
C | ||
\begin{bmatrix} | ||
X\\Y\\Z | ||
\end{bmatrix} \\ | ||
\vec{q} &= | ||
\begin{bmatrix} | ||
R'\\G'\\B' | ||
\end{bmatrix} | ||
= | ||
min(max(p_i,0),1)\\ | ||
\gamma &= 0.8 \\ | ||
m &= max(1.0e^{-10},R',G',B') \\ | ||
\begin{bmatrix} | ||
R\\G\\B | ||
\end{bmatrix} &= | ||
min(\frac{q_i}{m}^\gamma,1) | ||
\:\\ | ||
\end{align*} | ||
--> | ||
## Compiling from Source | ||
@@ -1710,18 +1858,15 @@ | ||
* note to self: rec709 does gamma conversion before while rec2020 does gamma conversion after when converting to ypbpr (I think) | ||
* Generate gradients given two colors | ||
* Generate triangular gradients based on three colors | ||
* Modification methods that retain luma | ||
Review: | ||
http://www.physics.sfasu.edu/astro/color/blackbodyc.txt | ||
## References | ||
1. International Telecommunications Union. *Recommendation ITU-R BT.2020-2*. "Parameter values for ultra-high definition television systems for productionand international programme exchange". (2015) | ||
1. International Telecommunications Union. *Recommendation ITU-R BT.2020-2*. | ||
"Parameter values for ultra-high definition television systems for productionand international programme exchange". (2015) | ||
https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-2-201510-I!!PDF-E.pdf | ||
2. International Telecommunications Union. *Recommendation ITU-R BT.709-6*. "Parameter values for the HDTV standards for production and international programme exchange". (2015) | ||
2. International Telecommunications Union. *Recommendation ITU-R BT.709-6*. | ||
"Parameter values for the HDTV standards for production and international programme exchange". (2015) | ||
https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-6-201506-I!!PDF-E.pdf | ||
3. International Telecommunications Union. *Recommendation ITU-R BT.601-7*. "Studio encoding parameters of digital television for standard 4:3and wide-screen 16:9 aspect ratios". (2011) | ||
3. International Telecommunications Union. *Recommendation ITU-R BT.601-7*. | ||
"Studio encoding parameters of digital television for standard 4:3and wide-screen 16:9 aspect ratios". (2011) | ||
https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf | ||
@@ -1738,8 +1883,10 @@ | ||
7. Tanner Helland. "Converting temperature (Kelvin) to RGB". (2012) | ||
https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html | ||
8. Darel Rex Finley. "HSP Color Model — Alternative to HSV (HSB) and HSL". (2006) | ||
7. Darel Rex Finley. "HSP Color Model — Alternative to HSV (HSB) and HSL". (2006) | ||
https://alienryderflex.com/hsp.html | ||
9. Michael Stokes (Hewlett-Packard), Matthew Anderson (Microsoft), Srinivasan Chandrasekar (Microsoft), Ricardo Motta (Hewlett-Packard). "A Standard Default Color Space for the Internet - sRGB". (1996) https://www.w3.org/Graphics/Color/sRGB.html | ||
8. Michael Stokes (Hewlett-Packard), Matthew Anderson (Microsoft), Srinivasan Chandrasekar (Microsoft), Ricardo Motta (Hewlett-Packard). | ||
"A Standard Default Color Space for the Internet - sRGB". (1996) | ||
https://www.w3.org/Graphics/Color/sRGB.html | ||
9. William T. Bridgman, NASA; Dan Bruton, SFASU. "RGB Values for Hot Objects". (2000) | ||
http://www.physics.sfasu.edu/astro/color/blackbodyc.txt |
313364
23
6054
1882