chromaticity-color-utilities
Advanced tools
Comparing version 0.1.5-alpha to 0.1.7-alpha
@@ -10,2 +10,4 @@ export interface newColorArgs { | ||
kr?: number; | ||
pb?: number; | ||
pr?: number; | ||
yLower?: number; | ||
@@ -17,2 +19,18 @@ yUpper?: 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 { | ||
@@ -22,2 +40,3 @@ method?: string; | ||
amount?: number; | ||
round?: boolean; | ||
} | ||
@@ -29,2 +48,14 @@ export interface schemeArgs { | ||
constructor(); | ||
bitDepth?: number; | ||
normalized?: boolean; | ||
colorSpace?: string; | ||
referenceWhite?: string; | ||
kb?: number; | ||
kr?: number; | ||
yLower?: number; | ||
yUpper?: number; | ||
cLower?: number; | ||
cUpper?: number; | ||
gamma?: number; | ||
a?: number; | ||
to(type: string, args?: newColorArgs): colorType | any; | ||
@@ -41,2 +72,3 @@ modify(modification: string, args?: modifyArgs): colorType; | ||
protected tohsi(args: newColorArgs): hsi; | ||
protected tohsp(args: newColorArgs): hsp; | ||
protected tocmyk(args: newColorArgs): cmyk; | ||
@@ -64,3 +96,3 @@ protected toyiq(args: newColorArgs): yiq; | ||
hex: string; | ||
constructor(hex: string); | ||
constructor(hex: string | number); | ||
protected torgb(args: newColorArgs): rgb; | ||
@@ -142,2 +174,14 @@ protected tohex(args: newColorArgs): hex; | ||
} | ||
export declare class hsp extends colorType { | ||
h: number; | ||
s: number; | ||
p: number; | ||
a: number; | ||
pr: number; | ||
pg: number; | ||
pb: number; | ||
constructor(h: number, s: number, p: number, a?: number, pb?: number, pr?: number); | ||
protected torgb(args: newColorArgs): rgb; | ||
protected tohsb(args: newColorArgs): hsp; | ||
} | ||
export declare class cmyk extends colorType { | ||
@@ -232,3 +276,5 @@ c: number; | ||
pr: number; | ||
constructor(y: number, pb: number, pr: number); | ||
kb: number; | ||
kr: number; | ||
constructor(y: number, pb: number, pr: number, kb: number, kr: number); | ||
protected torgb(args: newColorArgs): rgb; | ||
@@ -242,3 +288,7 @@ protected toypbpr(args: newColorArgs): ypbpr; | ||
cr: number; | ||
constructor(y: number, cb: number, cr: number); | ||
yLower: number; | ||
yUpper: number; | ||
cLower: number; | ||
cUpper: number; | ||
constructor(y: number, cb: number, cr: number, yLower?: number, yUpper?: number, cLower?: number, cUpper?: number); | ||
protected torgb(args: newColorArgs): rgb; | ||
@@ -245,0 +295,0 @@ protected toypbpr(args: newColorArgs): ypbpr; |
@@ -36,4 +36,3 @@ "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.hsi = exports.hsl = exports.hsv = exports.rec2020rgb = exports.rec709rgb = exports.rgb = exports.rgbNormalized = exports.hex = exports.colorType = void 0; | ||
var Util_1 = __importDefault(require("./Util")); | ||
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; | ||
var Convert_1 = __importDefault(require("./Convert")); | ||
@@ -73,2 +72,7 @@ var Modify_1 = __importDefault(require("./Modify")); | ||
return this.tohsi(args); | ||
case 'hsp': | ||
case 'hspa': | ||
case 'hspb': | ||
case 'hspba': | ||
return this.tohsp(args); | ||
case 'cmyk': | ||
@@ -97,2 +101,18 @@ return this.tocmyk(args); | ||
args = {}; | ||
var og = this.constructor['name']; | ||
var ogargs = { | ||
bitDepth: this.bitDepth, | ||
normalized: this.normalized, | ||
colorSpace: this.colorSpace, | ||
referenceWhite: this.referenceWhite, | ||
kb: this.kb, | ||
kr: this.kr, | ||
yLower: this.yLower, | ||
yUpper: this.yUpper, | ||
cLower: this.cLower, | ||
cUpper: this.cUpper, | ||
gamma: this.gamma | ||
}; | ||
var ogalpha = (typeof this.a == 'undefined' ? false : this.a); | ||
var modified; | ||
switch (modification) { | ||
@@ -103,8 +123,2 @@ case 'blend': | ||
} | ||
if (typeof args.amount === 'undefined') { | ||
args.amount = 0.5; | ||
} | ||
else { | ||
this.valueRangeCheck(args.amount, 0, 1, 'Blend amount must be between 0 and 1'); | ||
} | ||
if (typeof args.method === 'undefined') { | ||
@@ -118,14 +132,108 @@ args.method = 'rgb'; | ||
case 'hex': | ||
tmpColor1 = this.to('rgb', { round: false }); | ||
tmpColor2 = args.with.to('rgb', { round: false }); | ||
return Modify_1.default.rgbBlend(tmpColor1, tmpColor2, args.amount); | ||
tmpColor1 = this.torgb({ round: false }); | ||
tmpColor2 = args.with.torgb({ round: false }); | ||
modified = Modify_1.default.rgbBlend(tmpColor1, tmpColor2, args.amount); | ||
break; | ||
case 'hsv': | ||
case 'hsva': | ||
tmpColor1 = this.to('hsv', { round: false }); | ||
tmpColor2 = args.with.to('hsv', { round: false }); | ||
return Modify_1.default.hsvBlend(tmpColor1, tmpColor2, args.amount); | ||
tmpColor1 = this.tohsv({ round: false }); | ||
tmpColor2 = args.with.tohsv({ round: false }); | ||
modified = Modify_1.default.hsvBlend(tmpColor1, tmpColor2, args.amount); | ||
break; | ||
default: | ||
throw new Error('Unrecognized blending method'); | ||
} | ||
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 (ogalpha) | ||
ogModified.a = ogalpha; // otherwise this gets lost on some modifications | ||
return ogModified; | ||
}; | ||
@@ -212,2 +320,6 @@ colorType.prototype.scheme = function (type, args) { | ||
}; | ||
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) { | ||
@@ -283,3 +395,20 @@ var rgb = this.torgb(args); | ||
var _this = _super.call(this) || this; | ||
_this.hex = Util_1.default.expandHex(hex); | ||
if (typeof hex === 'string') { | ||
if (hex.charAt(0) == '#') { | ||
hex = hex.substr(1); | ||
} | ||
if (!/[0-9A-Fa-f]/g.test(hex)) { | ||
throw new Error('Invalid hex value'); | ||
} | ||
if (hex.length == 3) { | ||
hex = hex.split('').map(function (hex) { return hex + hex; }).join(''); | ||
} | ||
else if (hex.length != 6) { | ||
throw new Error('Invalid hex value'); | ||
} | ||
_this.hex = hex; | ||
} | ||
else { | ||
_this.hex = hex.toString(16).slice(1); | ||
} | ||
return _this; | ||
@@ -501,2 +630,34 @@ } | ||
exports.hsi = hsi; | ||
var hsp = /** @class */ (function (_super) { | ||
__extends(hsp, _super); | ||
function hsp(h, s, p, a, pb, pr) { | ||
if (a === void 0) { a = 100; } | ||
if (pb === void 0) { pb = 0.114; } | ||
if (pr === void 0) { pr = 0.299; } | ||
var _this = _super.call(this) || this; | ||
_this.valueRangeCheck(h, 0, 360); | ||
_this.valueRangeCheck(s, 0, 100); | ||
_this.valueRangeCheck(p, 0, 100); | ||
_this.valueRangeCheck(a, 0, 100); | ||
if (pr + pb > 1) { | ||
throw new Error('Pr + Pg + Pb must = 1'); | ||
} | ||
_this.h = h; | ||
_this.s = s; | ||
_this.p = p; | ||
_this.a = a; | ||
_this.pr = pr; | ||
_this.pg = 1 - pr - pb; | ||
_this.pb = pb; | ||
return _this; | ||
} | ||
hsp.prototype.torgb = function (args) { | ||
return Convert_1.default.hsp2rgb(this, args.round, args.bitDepth); | ||
}; | ||
hsp.prototype.tohsb = function (args) { | ||
return this; | ||
}; | ||
return hsp; | ||
}(colorType)); | ||
exports.hsp = hsp; | ||
var cmyk = /** @class */ (function (_super) { | ||
@@ -686,3 +847,3 @@ __extends(cmyk, _super); | ||
__extends(ypbpr, _super); | ||
function ypbpr(y, pb, pr) { | ||
function ypbpr(y, pb, pr, kb, kr) { | ||
var _this = _super.call(this) || this; | ||
@@ -695,2 +856,4 @@ _this.valueRangeCheck(y, 0, 1); | ||
_this.pr = pr; | ||
_this.kb = kb; | ||
_this.kr = kr; | ||
return _this; | ||
@@ -718,3 +881,3 @@ } | ||
__extends(ycbcr, _super); | ||
function ycbcr(y, cb, cr) { | ||
function ycbcr(y, cb, cr, yLower, yUpper, cLower, cUpper) { | ||
var _this = _super.call(this) || this; | ||
@@ -724,2 +887,14 @@ _this.y = y; | ||
_this.cr = cr; | ||
if (typeof yLower === 'undefined') | ||
yLower = 16; | ||
if (typeof yUpper === 'undefined') | ||
yUpper = 235; | ||
if (typeof cLower === 'undefined') | ||
cLower = 16; | ||
if (typeof cUpper === 'undefined') | ||
cUpper = 240; | ||
_this.yLower = yLower; | ||
_this.yUpper = yUpper; | ||
_this.cLower = cLower; | ||
_this.cUpper = cUpper; | ||
return _this; | ||
@@ -734,6 +909,6 @@ } | ||
ycbcr.prototype.toypbpr = function (args) { | ||
if (typeof args.yLower === 'undefined' || typeof args.yUpper === 'undefined' || typeof args.cLower === 'undefined' || typeof args.cUpper === 'undefined') { | ||
throw new Error('Missing arguments yLower, yUpper, cLower, cUpper'); | ||
if (typeof args.kb === 'undefined' || typeof args.kr === 'undefined') { | ||
throw new Error('Missing arguments kb and kr'); | ||
} | ||
return Convert_1.default.ycbcr2ypbpr(this, args.yLower, args.yUpper, args.cLower, args.cUpper); | ||
return Convert_1.default.ycbcr2ypbpr(this, args.kb, args.kr); | ||
}; | ||
@@ -740,0 +915,0 @@ ycbcr.prototype.toycbcr = function (args) { |
@@ -136,2 +136,4 @@ import * as Colors from './Colors'; | ||
static hsi2hsl(hsi: Colors.hsi, round?: boolean): Colors.hsl; | ||
static rgb2hsp(rgb: Colors.rgb, round?: boolean, Pb?: number, Pr?: number): Colors.hsp; | ||
static hsp2rgb(hsp: Colors.hsp, round?: boolean, bitDepth?: number): Colors.rgb; | ||
/** | ||
@@ -336,9 +338,7 @@ * Convert RGB to CMYK | ||
* @param {Colors.ycbcr} ycbcr | ||
* @param {number} [yLower=16] Lower bounds of Y | ||
* @param {number} [yUpper=235] Upper bounds of Y | ||
* @param {number} [cLower=16] Lower bounds of Cb and Cr | ||
* @param {number} [cUpper=240] Upper bounds of Cb and Cr | ||
* @param {number} kb | ||
* @param {number} kr | ||
* @return {Colors.ypbpr} | ||
*/ | ||
static ycbcr2ypbpr(ycbcr: Colors.ycbcr, yLower?: number, yUpper?: number, cLower?: number, cUpper?: number): Colors.ypbpr; | ||
static ycbcr2ypbpr(ycbcr: Colors.ycbcr, kb: number, kr: number): Colors.ypbpr; | ||
/** | ||
@@ -366,4 +366,2 @@ * Convert RGB to JPEG YCbCr | ||
* This is hugely perceptual and approximate | ||
* Original algorithm: | ||
* https://academo.org/demos/wavelength-to-colour-relationship/ | ||
* | ||
@@ -370,0 +368,0 @@ * @param {Colors.nm} nm Wavelength of light in nanometers (positive number) |
@@ -559,2 +559,151 @@ "use strict"; | ||
}; | ||
Convert.rgb2hsp = function (rgb, round, Pb, Pr) { | ||
if (round === void 0) { round = true; } | ||
if (Pb === void 0) { Pb = 0.114; } | ||
if (Pr === void 0) { Pr = 0.299; } | ||
if (Pr + Pb > 1) { | ||
throw new Error('Pr + Pg + Pb must = 1'); | ||
} | ||
var Pg = 1 - Pr - Pb; | ||
var maxVal = (Math.pow(2, rgb.bitDepth)) - 1; | ||
var r = rgb.r / maxVal; | ||
var g = rgb.g / maxVal; | ||
var b = rgb.b / maxVal; | ||
var pb = Math.sqrt(Math.pow(r, 2) * Pr + Math.pow(g, 2) * Pg + Math.pow(b, 2) * Pb); | ||
var value = Math.max(r, g, b); | ||
var chroma = value - Math.min(r, g, b); | ||
var s = value ? chroma / value : 0; | ||
var h; | ||
if (!chroma) | ||
h = 0; | ||
else if (value == r) | ||
h = (g - b) / chroma; | ||
else if (value == g) | ||
h = (b - r) / chroma + 2; | ||
else if (value == b) | ||
h = (r - g) / chroma + 4; | ||
else | ||
h = 0; | ||
h *= 60; | ||
while (h >= 360) | ||
h -= 360; | ||
while (h < 0) | ||
h += 360; | ||
s *= 100; | ||
pb *= 100; | ||
var a = rgb.a / maxVal * 100; | ||
if (round) { | ||
h = Math.round(h); | ||
s = Math.round(s); | ||
pb = Math.round(pb); | ||
a = Math.round(a); | ||
} | ||
return new Colors.hsp(h, s, pb, a, Pb, Pr); | ||
}; | ||
Convert.hsp2rgb = function (hsp, round, bitDepth) { | ||
if (round === void 0) { round = true; } | ||
if (bitDepth === void 0) { bitDepth = 8; } | ||
var hp = hsp.h / 60; | ||
var s = hsp.s / 100; | ||
var pb = hsp.p / 100; | ||
var s0 = 1 - s; | ||
var r, g, b; | ||
var hpf = Math.floor(hp); | ||
var hpp; | ||
if (s0 > 0) { | ||
switch (hpf) { | ||
case 0: //R>G>B | ||
hpp = hp; | ||
b = pb / Math.sqrt(hsp.pr / Math.pow(s0, 2) + hsp.pg * Math.pow(1 + hpp + (1 / s0 - 1), 2) + hsp.pb); | ||
r = b / s0; | ||
g = b + hpp * (r - b); | ||
break; | ||
case 1: //G>R>B | ||
hpp = -1 * hp + 2; | ||
b = pb / Math.sqrt(hsp.pg / Math.pow(s0, 2) + hsp.pr * Math.pow(1 + hpp * (1 / s0 - 1), 2) + hsp.pb); | ||
g = b / s0; | ||
r = b + hpp * (g - b); | ||
break; | ||
case 2: //G>B>R | ||
hpp = hp - 2; | ||
r = pb / Math.sqrt(hsp.pg / Math.pow(s0, 2) + hsp.pb * Math.pow(1 + hpp * (1 / s0 - 1), 2) + hsp.pr); | ||
g = r / s0; | ||
b = r + hpp * (g - r); | ||
break; | ||
case 3: //B>G>R | ||
hpp = -1 * hp + 4; | ||
r = pb / Math.sqrt(hsp.pb / Math.pow(s0, 2) + hsp.pr * Math.pow(1 + hpp * (1 / s0 - 1), 2) + hsp.pr); | ||
b = r / s0; | ||
g = r + hpp * (b - r); | ||
break; | ||
case 4: //B>R>G | ||
hpp = hp - 4; | ||
g = pb / Math.sqrt(hsp.pb / Math.pow(s0, 2) + hsp.pr * Math.pow(1 + hpp * (1 / s0 - 1), 2) + hsp.pg); | ||
b = g / s0; | ||
r = g + hpp * (b - g); | ||
break; | ||
case 5: //R>B>G | ||
default: | ||
hpp = -1 * hp + 6; | ||
g = pb / Math.sqrt(hsp.pr / Math.pow(s0, 2) + hsp.pb * Math.pow(1 + hpp * (1 / s0 - 1), 2) + hsp.pg); | ||
r = g / s0; | ||
b = g + hpp * (r - g); | ||
} | ||
} | ||
else { | ||
switch (hpf) { | ||
case 0: //R>G>B | ||
hpp = hp; | ||
r = Math.sqrt(Math.pow(pb, 2) / (hsp.pr + hsp.pg * Math.pow(hpp, 2))); | ||
g = r * hpp; | ||
b = 0; | ||
break; | ||
case 1: //G>R>B | ||
hpp = -1 * hp + 2; | ||
g = Math.sqrt(Math.pow(pb, 2) / (hsp.pg + hsp.pr * Math.pow(hpp, 2))); | ||
r = g * hpp; | ||
b = 0; | ||
break; | ||
case 2: //G>B>R | ||
hpp = hp - 2; | ||
g = Math.sqrt(Math.pow(pb, 2) / (hsp.pr + hsp.pg * Math.pow(hpp, 2))); | ||
b = g * hpp; | ||
r = 0; | ||
break; | ||
case 3: //B>G>R | ||
hpp = -1 * hp + 4; | ||
b = Math.sqrt(Math.pow(pb, 2) / (hsp.pb + hsp.pg * Math.pow(hpp, 2))); | ||
g = b * hpp; | ||
r = 0; | ||
break; | ||
case 4: //B>R>G | ||
hpp = hp - 4; | ||
b = Math.sqrt(Math.pow(pb, 2) / (hsp.pb + hsp.pr * Math.pow(hpp, 2))); | ||
r = b * hpp; | ||
g = 0; | ||
break; | ||
case 5: //R>B>G | ||
default: | ||
hpp = -1 * hp + 6; | ||
r = Math.sqrt(Math.pow(pb, 2) / (hsp.pr + hsp.pb * Math.pow(hpp, 2))); | ||
b = r * hpp; | ||
g = 0; | ||
} | ||
} | ||
r = Math.min(Math.max(r, 0), 1); | ||
g = Math.min(Math.max(g, 0), 1); | ||
b = Math.min(Math.max(b, 0), 1); | ||
var max = (Math.pow(2, bitDepth)) - 1; | ||
r *= max; | ||
g *= max; | ||
b *= max; | ||
var a = hsp.a / 100 * max; | ||
if (round) { | ||
r = Math.round(r); | ||
g = Math.round(g); | ||
b = Math.round(b); | ||
a = Math.round(a); | ||
} | ||
return new Colors.rgb(r, g, b, a, bitDepth); | ||
}; | ||
/////////// CMYK /////////// | ||
@@ -999,3 +1148,3 @@ /** | ||
minFrom = 64; | ||
maxFrom = 876; | ||
maxFrom = 940; | ||
} | ||
@@ -1122,3 +1271,3 @@ else { | ||
// let pr = 0.5 * r + (-0.5 * (kg / (1 - kr))) * g + (-0.5 * (kb / (1 - kr))) * b; | ||
return new Colors.ypbpr(y, pb, pr); | ||
return new Colors.ypbpr(y, pb, pr, kb, kr); | ||
}; | ||
@@ -1187,17 +1336,11 @@ /** | ||
* @param {Colors.ycbcr} ycbcr | ||
* @param {number} [yLower=16] Lower bounds of Y | ||
* @param {number} [yUpper=235] Upper bounds of Y | ||
* @param {number} [cLower=16] Lower bounds of Cb and Cr | ||
* @param {number} [cUpper=240] Upper bounds of Cb and Cr | ||
* @param {number} kb | ||
* @param {number} kr | ||
* @return {Colors.ypbpr} | ||
*/ | ||
Convert.ycbcr2ypbpr = function (ycbcr, yLower, yUpper, cLower, cUpper) { | ||
if (yLower === void 0) { yLower = 16; } | ||
if (yUpper === void 0) { yUpper = 235; } | ||
if (cLower === void 0) { cLower = 16; } | ||
if (cUpper === void 0) { cUpper = 240; } | ||
var y2 = Util_1.default.scaleValueRange(ycbcr.y, yLower, yUpper, 0, 1, false); | ||
var pb = Util_1.default.scaleValueRange(ycbcr.cb, cLower, cUpper, 0, 1, false) - 0.5; | ||
var pr = Util_1.default.scaleValueRange(ycbcr.cr, cLower, cUpper, 0, 1, false) - 0.5; | ||
return new Colors.ypbpr(y2, pb, pr); | ||
Convert.ycbcr2ypbpr = function (ycbcr, kb, kr) { | ||
var y2 = Util_1.default.scaleValueRange(ycbcr.y, ycbcr.yLower, ycbcr.yUpper, 0, 1, false); | ||
var pb = Util_1.default.scaleValueRange(ycbcr.cb, ycbcr.cLower, ycbcr.cUpper, 0, 1, false) - 0.5; | ||
var pr = Util_1.default.scaleValueRange(ycbcr.cr, ycbcr.cLower, ycbcr.cUpper, 0, 1, false) - 0.5; | ||
return new Colors.ypbpr(y2, pb, pr, kb, kr); | ||
}; | ||
@@ -1264,4 +1407,2 @@ /** | ||
* This is hugely perceptual and approximate | ||
* Original algorithm: | ||
* https://academo.org/demos/wavelength-to-colour-relationship/ | ||
* | ||
@@ -1268,0 +1409,0 @@ * @param {Colors.nm} nm Wavelength of light in nanometers (positive number) |
@@ -8,2 +8,10 @@ import * as Colors from './Colors'; | ||
referenceWhite?: string; | ||
yLower?: number; | ||
yUpper?: number; | ||
cLower?: number; | ||
cUpper?: number; | ||
kb?: number; | ||
kr?: number; | ||
pb?: number; | ||
pr?: number; | ||
} | ||
@@ -10,0 +18,0 @@ interface colorDef { |
@@ -111,2 +111,7 @@ "use strict"; | ||
return new Colors.hsi(value[0], value[1], value[2], value[3]); | ||
case 'hsp': | ||
case 'hspa': | ||
if (typeof value[3] === 'undefined') | ||
value[3] = 100; | ||
return new Colors.hsp(value[0], value[1], value[2], value[3], args.pb, args.pr); | ||
case 'cmyk': | ||
@@ -125,5 +130,8 @@ return new Colors.cmyk(value[0], value[1], value[2], value[3]); | ||
case 'ypbpr': | ||
return new Colors.ypbpr(value[0], value[1], value[2]); | ||
if (typeof args.kb == 'undefined' || typeof args.kr == 'undefined') { | ||
throw new Error('Must supply Kb and Kr constants'); | ||
} | ||
return new Colors.ypbpr(value[0], value[1], value[2], args.kb, args.kr); | ||
case 'ycbcr': | ||
return new Colors.ycbcr(value[0], value[1], value[2]); | ||
return new Colors.ycbcr(value[0], value[1], value[2], args.yLower, args.yUpper, args.cLower, args.cUpper); | ||
default: | ||
@@ -130,0 +138,0 @@ throw new Error('Unable to determine color type'); |
@@ -21,3 +21,3 @@ import * as Colors from './Colors'; | ||
*/ | ||
static rgbBlend(rgb1: Colors.rgb, rgb2: Colors.rgb, amount: number, round?: boolean): Colors.rgb; | ||
static rgbBlend(rgb1: Colors.rgb, rgb2: Colors.rgb, amount?: number, round?: boolean): Colors.rgb; | ||
/** | ||
@@ -32,8 +32,12 @@ * Blend one HSV color with another | ||
*/ | ||
static hsvBlend(hsv1: Colors.hsv, hsv2: Colors.hsv, amount: number, round?: boolean): Colors.hsv; | ||
static darken(): void; | ||
static lighten(): void; | ||
static desaturate(): void; | ||
static saturate(): void; | ||
static hsvBlend(hsv1: Colors.hsv, hsv2: Colors.hsv, amount?: number, round?: boolean): Colors.hsv; | ||
static hslDarken(hsl: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; | ||
static hslLighten(hsl: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; | ||
static hspDarken(hsp: Colors.hsp, amount?: number, round?: boolean): Colors.hsp; | ||
static hspLighten(hsp: Colors.hsp, amount?: number, round?: boolean): Colors.hsp; | ||
static hslDesaturate(hsl: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; | ||
static hslSaturate(hsl: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; | ||
static hsvDesaturate(hsv: Colors.hsv, amount?: number, round?: boolean): Colors.hsv; | ||
static hsvSaturate(hsv: Colors.hsv, amount?: number, round?: boolean): Colors.hsv; | ||
} | ||
export = Modify; |
@@ -66,3 +66,5 @@ "use strict"; | ||
Modify.rgbBlend = function (rgb1, rgb2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var r3 = rgb1.r + ((rgb2.r - rgb1.r) * amount); | ||
@@ -90,3 +92,5 @@ var g3 = rgb1.g + ((rgb2.g - rgb1.g) * amount); | ||
Modify.hsvBlend = function (hsv1, hsv2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var hueDiff; | ||
@@ -113,12 +117,76 @@ if (Math.abs(hsv2.h - hsv1.h) > 180) { | ||
}; | ||
Modify.darken = function () { | ||
Modify.hslDarken = function (hsl, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var vDarker = hsl.l * realAmount; | ||
if (round) | ||
vDarker = Math.round(vDarker); | ||
return new Colors.hsl(hsl.h, hsl.s, vDarker, hsl.a); | ||
}; | ||
Modify.lighten = function () { | ||
Modify.hslLighten = function (hsl, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var vLighter = hsl.l + ((100 - hsl.l) * realAmount); | ||
if (round) | ||
vLighter = Math.round(vLighter); | ||
return new Colors.hsl(hsl.h, hsl.s, vLighter, hsl.a); | ||
}; | ||
Modify.desaturate = function () { | ||
Modify.hspDarken = function (hsp, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var pDarker = hsp.p * realAmount; | ||
if (round) | ||
pDarker = Math.round(pDarker); | ||
return new Colors.hsp(hsp.h, hsp.s, pDarker, hsp.a, hsp.pb, hsp.pr); | ||
}; | ||
Modify.saturate = function () { | ||
Modify.hspLighten = function (hsp, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var pLighter = hsp.p + ((100 - hsp.p) * realAmount); | ||
if (round) | ||
pLighter = Math.round(pLighter); | ||
return new Colors.hsp(hsp.h, hsp.s, pLighter, hsp.a, hsp.pb, hsp.pr); | ||
}; | ||
Modify.hslDesaturate = function (hsl, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var sLess = hsl.s * realAmount; | ||
if (round) | ||
sLess = Math.round(sLess); | ||
return new Colors.hsl(hsl.h, sLess, hsl.l, hsl.a); | ||
}; | ||
Modify.hslSaturate = function (hsl, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var sMore = hsl.s + ((100 - hsl.s) * realAmount); | ||
if (round) | ||
sMore = Math.round(sMore); | ||
return new Colors.hsl(hsl.h, sMore, hsl.l, hsl.a); | ||
}; | ||
Modify.hsvDesaturate = function (hsv, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var sLess = hsv.s * realAmount; | ||
if (round) | ||
sLess = Math.round(sLess); | ||
return new Colors.hsv(hsv.h, sLess, hsv.v, hsv.a); | ||
}; | ||
Modify.hsvSaturate = function (hsv, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var sMore = hsv.s + ((100 - hsv.s) * realAmount); | ||
if (round) | ||
sMore = Math.round(sMore); | ||
return new Colors.hsv(hsv.h, sMore, hsv.v, hsv.a); | ||
}; | ||
return Modify; | ||
}()); | ||
module.exports = Modify; |
@@ -16,9 +16,2 @@ declare class Util { | ||
/** | ||
* Expands shorthand hex color values to full 6-digit values | ||
* | ||
* @param {string} hex RGB or RRGGBB | ||
* @return {string} RRGGBB | ||
*/ | ||
static expandHex(hex: string): string; | ||
/** | ||
* Generates the inverse of a 3x3 matrix | ||
@@ -25,0 +18,0 @@ * Utilized for XYZ matrix generation |
@@ -42,24 +42,2 @@ "use strict"; | ||
/** | ||
* Expands shorthand hex color values to full 6-digit values | ||
* | ||
* @param {string} hex RGB or RRGGBB | ||
* @return {string} RRGGBB | ||
*/ | ||
Util.expandHex = function (hex) { | ||
if (hex.charAt(0) == '#') { | ||
hex = hex.substr(1); | ||
} | ||
if (!/[0-9A-Fa-f]/g.test(hex)) { | ||
throw new Error('Invalid hex value'); | ||
} | ||
if (hex.length == 6) { | ||
return hex; | ||
} | ||
if (hex.length != 3) { | ||
throw new Error('Invalid hex value'); | ||
} | ||
hex = hex.split('').map(function (hex) { return hex + hex; }).join(''); | ||
return hex; | ||
}; | ||
/** | ||
* Generates the inverse of a 3x3 matrix | ||
@@ -66,0 +44,0 @@ * Utilized for XYZ matrix generation |
{ | ||
"name": "chromaticity-color-utilities", | ||
"version": "0.1.5-alpha", | ||
"version": "0.1.7-alpha", | ||
"description": "Color utilities for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "dist/main.js", |
335
README.md
# chromaticity-color-utilities | ||
Color utilities for Node.js. | ||
Conversion, modification, and color schemes of: RGB (at any bit depth), HSV, HSL, HSI, CYMK, YIQ, XYZ, xyY, L\*a\*b\*, L\*u\*v\*, Y'PbPr, Y'CbCr, and more. | ||
Conversion, modification, and color schemes of: RGB (at any bit depth), HSV, HSL, HSI, HSP, CYMK, YIQ, XYZ, xyY, L\*a\*b\*, L\*u\*v\*, Y'PbPr, Y'CbCr, and more. | ||
@@ -18,2 +18,3 @@ ## Table of Contents | ||
* [HSI: Hue, Saturation, Intensity](#hsi--hue-saturation-intensity) | ||
* [HSP: Hue, Saturation, Perceived Brightness](#hsp--hue-saturation-perceived-brightness) | ||
* [CMYK: Cyan, Magenta, Yellow, Black](#cmyk--cyan-magenta-yellow-black) | ||
@@ -32,6 +33,6 @@ * [YIQ: NTSC Color](#yiq--ntsc-color) | ||
* [Blending Two Colors](#blending-two-colors) | ||
* Darken | ||
* Lighten | ||
* Saturate | ||
* Desaturate | ||
* [Darken](#darken) | ||
* [Lighten](#lighten) | ||
* [Saturate](#saturate) | ||
* [Desaturate](#desaturate) | ||
* [Color Scheme Generation](#color-scheme-generation) | ||
@@ -52,2 +53,4 @@ * [Complementary Schemes](#complementary-schemes) | ||
* [HSI to RGB](#hsi-to-rgb) | ||
* [RGB to HSP](#rgb-to-hsp) | ||
* [HSP to RGB](#hsp-to-rgb) | ||
* [HSV to HSL](#hsv-to-hsl) | ||
@@ -179,3 +182,3 @@ * [HSL to HSV](#hsl-to-hsv) | ||
May use string or numberical value. Strings are case-insensitive. Short form or long form may be used. # ignored if present. | ||
May use string or numerical value. Strings are case-insensitive. Short form or long form may be used. # ignored if present. | ||
@@ -301,2 +304,37 @@ ```ts | ||
### HSP : Hue, Saturation, Perceived Brightness | ||
The formula used to generate HSP is similar to the one Photoshop uses when converting images to greyscale. | ||
Hue value is between 0 and 360. Saturation, perceived brightness, and alpha are between 0 and 100 (as in, percent). | ||
When passing P<sub>R</sub> and P<sub>B</sub> values, P<sub>R</sub> + P<sub>G</sub> + P<sub>B</sub> must = 1. | ||
By default, | ||
* P<sub>R</sub> = 0.299 | ||
* P<sub>G</sub> = 0.587 | ||
* P<sub>B</sub> = 0.114 | ||
** This formula is not as accurate as most others, but does offer another way of adjusting brightness in an image. | ||
```ts | ||
Color.from('hsp',[h, s, p, a?],{ | ||
pb: number // optional, default = 0.114 | ||
pr: number // optional, default = 0.299 | ||
}) | ||
.to('hsp',{ | ||
round: boolean // optional, default = true | ||
pb: number // optional, default = 0.114 | ||
pr: number // optional, default = 0.299 | ||
}) | ||
// e.g. | ||
let color1 = Color.from('hsp',[300, 100, 65]).to('rgb') | ||
// rgb { r: 255, g: 0, b: 255, a: 255, bitDepth: 8, max: 255 } | ||
let color3 = Color.from('rgb',[255, 0, 255]).to('hsp') | ||
// hsp { h: 300, s: 100, p: 64, a: 100, pr: 0.299, pg: 0.587, pb: 0.114 } | ||
``` | ||
### CMYK : Cyan, Magenta, Yellow, Black | ||
@@ -648,6 +686,9 @@ | ||
Blending methods include: `rgb`, `hsv` | ||
```ts | ||
let color3 = color1.modify('blend', { | ||
with: color2, // REQUIRED, can be any color of any type | ||
amount: number // optional, 0 - 1, defaults to 0.5 | ||
with: color2, // REQUIRED, can be any color of any type | ||
amount: number, // optional, 0 - 1, defaults to 0.5 | ||
method: string // optional, defaults to 'rgb' | ||
}) | ||
@@ -670,16 +711,81 @@ | ||
todo | ||
Methods available are: `hsl`/`lightness`, `hsp`/`perceived` | ||
These methods are intended to provide alternative ways of modifying a color versus changing the values directly, which can make more sense. | ||
```ts | ||
let color2 = color1.modify('darken', { | ||
amount: number, // optional, 0 - 1, defaults to 0.5 | ||
method: string // optional, defaults to 'lightness' | ||
round: boolean // optional, defaults to true | ||
}) | ||
// e.g. | ||
let color2 = Color.from('rgb',[255,0,255,200]).modify('darken',{method:'lightness'}) | ||
// rgb { r: 128, g: 0, b: 128, a: 200, bitDepth: 8, max: 255 } | ||
let color2 = Color.from('rgb',[100,0,100]).modify('darken',{method:'hsp'}) | ||
// rgb { r: 52, g: 0, b: 52, a: 255, bitDepth: 8, max: 255 } | ||
``` | ||
### Lighten | ||
todo | ||
Methods available are: `hsl`/`lightness`, `hsp`/`perceived` | ||
These methods are intended to provide alternative ways of modifying a color versus changing the values directly, which can make more sense. | ||
```ts | ||
let color2 = color1.modify('lighten', { | ||
amount: number, // optional, 0 - 1, defaults to 0.5 | ||
method: string // optional, defaults to 'lightness' | ||
round: boolean // optional, defaults to true | ||
}) | ||
// e.g. | ||
let color2 = Color.from('rgb',[255,0,255,200]).modify('lighten',{method:'lightness'}) | ||
// rgb { r: 255, g: 128, b: 255, a: 200, bitDepth: 8, max: 255 } | ||
let color2 = Color.from('rgb',[100,0,100]).modify('lighten',{method:'hsp'}) | ||
// rgb { r: 250, g: 0, b: 250, a: 255, bitDepth: 8, max: 255 } | ||
``` | ||
### Saturate | ||
todo | ||
Methods available are: `hsv`, `hsl`. The input color type does not matter. | ||
These methods are intended to provide alternative ways of modifying a color versus changing the values directly, which can make more sense. | ||
```ts | ||
let color2 = color1.modify('saturate', { | ||
amount: number, // optional, 0 - 1, defaults to 0.5 | ||
method: string // optional, defaults to 'hsl' | ||
round: boolean // optional, defaults to true | ||
}) | ||
// e.g. | ||
let color2 = Color.from('rgb',[128,64,128,200]).modify('saturate','hsl') | ||
// rgb { r: 160, g: 32, b: 160, a: 200, bitDepth: 8, max: 255 } | ||
let color2 = Color.from('rgb',[128,64,128,200]).modify('saturate','hsv') | ||
// rgb { r: 128, g: 32, b: 128, a: 200, bitDepth: 8, max: 255 } | ||
``` | ||
### Desaturate | ||
todo | ||
Methods available are: `hsv`, `hsl`. The input color type does not matter. | ||
These methods are intended to provide alternative ways of modifying a color versus changing the values directly, which can make more sense. | ||
```ts | ||
let color2 = color1.modify('saturate', { | ||
amount: number, // optional, 0 - 1, defaults to 0.5 | ||
method: string // optional, defaults to 'hsl' | ||
round: boolean // optional, defaults to true | ||
}) | ||
// e.g. | ||
let color2 = Color.from('rgb',[255,0,255,200]).modify('desaturate','hsl') | ||
// rgb { r: 191, g: 64, b: 191, a: 200, bitDepth: 8, max: 255 } | ||
let color2 = Color.from('rgb',[255,0,255,200]).modify('desaturate','hsl') | ||
// rgb { r: 255, g: 128, b: 255, a: 200, bitDepth: 8, max: 255 } | ||
``` | ||
## Color Scheme Generation | ||
@@ -822,6 +928,6 @@ | ||
C references chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsv-v.png) | ||
C = chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsv-c.png) | ||
@@ -858,6 +964,6 @@ | ||
C references chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsv-v.png) | ||
C = chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsv-c.png) | ||
@@ -871,3 +977,3 @@ | ||
C = chroma | ||
C references chroma | ||
@@ -899,6 +1005,6 @@ ![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsl-rgb-c.png) | ||
C references chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsv-v.png) | ||
C = chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsv-c.png) | ||
@@ -926,6 +1032,6 @@ | ||
C references chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsi-rgb-z.png) | ||
C = chroma | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsi-rgb-c.png) | ||
@@ -941,2 +1047,164 @@ | ||
### RGB to HSP | ||
Where P is perceived brightness. This algorithm is similar to the one Photoshop uses when converting images to greyscale. | ||
If no values are passed, the default weight for P is as follows: | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-p.png) | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/rgb-hsp.png) | ||
<!-- | ||
\begin{align*} | ||
P_{R} &= 0.299 \\ | ||
P_{G} &= 0.587 \\ | ||
P_{B} &= 0.114 | ||
\end{align*} | ||
\begin{align*} | ||
V &= max(R,G,B) \\ | ||
C &= V - min(R,G,B) \\ | ||
\:\\ | ||
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} \\ | ||
\:\\ | ||
S &= \begin{cases} | ||
0 & \text{ if } V=0 \\ | ||
\frac{V}{C} & \text{ otherwise } | ||
\end{cases} \\ | ||
\:\\ | ||
P &= \sqrt{R^2 \cdot P_{R} + G^2 \cdot P_{G} + B^2 \cdot P_{B}} \\ | ||
\end{align*} | ||
--> | ||
### HSP to RGB | ||
Where P is perceived brightness. This algorithm is similar to the one Photoshop uses when converting images to greyscale. | ||
If no values are passed, the default weight for P is as follows: | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-p.png) | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-rgb-v.png) | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-rgb-f.png) | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-rgb-r.png) | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-rgb-g.png) | ||
![](https://raw.githubusercontent.com/reiniiriarios/chromaticity-color-utilities/master/math/hsp-rgb-b.png) | ||
<!-- | ||
\begin{align*} | ||
H' &= \frac{H}{60} \\ | ||
S_{0} &= 1 - S \\ | ||
H_{0} &= \begin{cases} | ||
H' & \text{ if } H' < 1 \\ | ||
-H'+2 & \text{ if } 1 \leq H' < 2 \\ | ||
H'-2 & \text{ if } 2 \leq H' < 3 \\ | ||
-H'+4 & \text{ if } 3 \leq H' < 4 \\ | ||
H'-4 & \text{ if } 4 \leq H' < 5 \\ | ||
-H'+6 & \text{ if } 5 \leq H' < 6 \\ | ||
\end{cases} | ||
\end{align*} | ||
\begin{align*} | ||
f_{a}(x) &= \frac{x}{S_{0}} \\ | ||
f_{b}(x) &= x \cdot S_{0} \\ | ||
f_{c}(x,y) &= y + H_{0} \cdot (x - y) \\ | ||
f_{d}(x,y,z) &= \frac | ||
{P} | ||
{\sqrt{\frac{P_{x}}{S_{0}^2}}} | ||
+ P_{y} \cdot | ||
(1 + H_{0} + \frac{1}{S_{0}-1})^2 | ||
+ P_{z}\\ | ||
f_{e}(x,y) &= \sqrt{ | ||
\frac{P^2} | ||
{P_{x} + P_{y} \cdot H_{0}^2} | ||
} | ||
\end{align*} | ||
R = \begin{cases} | ||
f_{a}(B) & | ||
\text{ if } S_{0} > 0 \text{ and } H' < 1 \\ | ||
f_{c}(G,B) & | ||
\text{ if } S_{0} > 0 \text{ and } 1 \leq H' < 2 \\ | ||
f_{d}(R,B,G) & | ||
\text{ if } S_{0} > 0 \text{ and } 2 \leq H' < 3 \\ | ||
f_{a}(B,R,G) & | ||
\text{ if } S_{0} > 0 \text{ and } 3 \leq H' < 4 \\ | ||
f_{c}(B,G) & | ||
\text{ if } S_{0} > 0 \text{ and } 4 \leq H' < 5 \\ | ||
f_{a}(G) & | ||
\text{ if } S_{0} > 0 \text{ and } 5 \leq H' < 6 \\ | ||
f_{e}(R,G) & | ||
\text{ if } S_{0} = 0 \text{ and } H' < 1 \\ | ||
f_{b}(G) & | ||
\text{ if } S_{0} = 0 \text{ and } 1 \leq H' < 2 \\ | ||
0 & | ||
\text{ if } S_{0} = 0 \text{ and } 2 \leq H' < 4 \\ | ||
f_{b}(B) & | ||
\text{ if } S_{0} = 0 \text{ and } 4 \leq H' < 5 \\ | ||
f_{e}(R,B) & | ||
\text{ if } S_{0} = 0 \text{ and } 5 \leq H' < 6 \\ | ||
\end{cases} | ||
G = \begin{cases} | ||
f_{c}(R,B) & | ||
\text{ if } S_{0} > 0 \text{ and } H' < 1 \\ | ||
f_{a}(B) & | ||
\text{ if } S_{0} > 0 \text{ and } 1 \leq H' < 2 \\ | ||
f_{a}(R) & | ||
\text{ if } S_{0} > 0 \text{ and } 2 \leq H' < 3 \\ | ||
f_{c}(B,R) & | ||
\text{ if } S_{0} > 0 \text{ and } 3 \leq H' < 4 \\ | ||
f_{d}(B,R,G) & | ||
\text{ if } S_{0} > 0 \text{ and } 4 \leq H' < 5 \\ | ||
f_{d}(R,B,G) & | ||
\text{ if } S_{0} > 0 \text{ and } 5 \leq H' < 6 \\ | ||
f_{b}(R) & | ||
\text{ if } S_{0} = 0 \text{ and } H' < 1 \\ | ||
f_{e}(G,R) & | ||
\text{ if } S_{0} = 0 \text{ and } 1 \leq H' < 2 \\ | ||
f_{e}(R,G) & | ||
\text{ if } S_{0} = 0 \text{ and } 2 \leq H' < 3 \\ | ||
f_{b}(B) & | ||
\text{ if } S_{0} = 0 \text{ and } 3 \leq H' < 4 \\ | ||
0 & | ||
\text{ if } S_{0} = 0 \text{ and } 4 \leq H' < 6 \\ | ||
\end{cases} | ||
B = \begin{cases} | ||
f_{a}(B) & | ||
\text{ if } S_{0} > 0 \text{ and } H' < 1 \\ | ||
f_{d}(G,R,B) & | ||
\text{ if } S_{0} > 0 \text{ and } 1 \leq H' < 2 \\ | ||
f_{c}(G,R) & | ||
\text{ if } S_{0} > 0 \text{ and } 2 \leq H' < 3 \\ | ||
f_{a}(R) & | ||
\text{ if } S_{0} > 0 \text{ and } 3 \leq H' < 4 \\ | ||
f_{a}(G) & | ||
\text{ if } S_{0} > 0 \text{ and } 4 \leq H' < 5 \\ | ||
f_{b}(R,G) & | ||
\text{ if } S_{0} > 0 \text{ and } 5 \leq H' < 6 \\ | ||
0 & | ||
\text{ if } S_{0} = 0 \text{ and } H' < 2 \\ | ||
f_{b}(G) & | ||
\text{ if } S_{0} = 0 \text{ and } 2 \leq H' < 3 \\ | ||
f_{e}(B,G) & | ||
\text{ if } S_{0} = 0 \text{ and } 3 \leq H' < 4 \\ | ||
f_{e}(B,R) & | ||
\text{ if } S_{0} = 0 \text{ and } 4 \leq H' < 5 \\ | ||
f_{b}(R) & | ||
\text{ if } S_{0} = 0 \text{ and } 5 \leq H' < 6 \\ | ||
\end{cases} | ||
--> | ||
### HSV to HSL | ||
@@ -1347,7 +1615,6 @@ | ||
* HSB (perceived brightness) | ||
* Gamma adjustment modification | ||
* Auto-gamma adjustment and conversion for rec709, rec2020, and jpeg to/from ypbpr | ||
* note to self: rec709 does gamma conversion before while rec2020 does gamma conversion after when converting to ypbpr (I think) | ||
* Lighten and darken colors | ||
* Saturate and desaturate colors | ||
* Create color schemes / gradient schemes based on tints and shades | ||
@@ -1357,1 +1624,23 @@ * Generate gradients given two colors | ||
* Modification methods that retain luma | ||
Review: | ||
http://www.physics.sfasu.edu/astro/color/blackbodyc.txt | ||
## References | ||
todo: clean this up | ||
**Recommendation ITU-R BT.709-6**, *Parameter values for the HDTV standards for production and international programme exchange*, | ||
https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-6-201506-I!!PDF-E.pdf | ||
**Recommendation ITU-R BT.601-7**, *Studio encoding parameters of digital television for standard 4:3and wide-screen 16:9 aspect ratios*, | ||
https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf | ||
*Computing RGB-to-XYZ and XYZ-to-RGB matrices*, | ||
http://www.brucelindbloom.com | ||
*Approximate RGB values for Visible Wavelengths*, | ||
http://www.physics.sfasu.edu/astro/color/spectra.html | ||
*Converting temperature (Kelvin) to RGB*, | ||
https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
278178
21
5471
1631