sharp-vibrant
Version:
Extract prominent colors from an image in a node environment using sharp.
143 lines • 7.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-param-reassign */
const color_1 = require("../color");
const util_1 = require("../util");
const DefaultOpts = {
targetDarkLuma: 0.26,
maxDarkLuma: 0.45,
minLightLuma: 0.55,
targetLightLuma: 0.74,
minNormalLuma: 0.3,
targetNormalLuma: 0.5,
maxNormalLuma: 0.7,
targetMutesSaturation: 0.3,
maxMutesSaturation: 0.4,
targetVibrantSaturation: 1.0,
minVibrantSaturation: 0.35,
weightSaturation: 3,
weightLuma: 6.5,
weightPopulation: 0.5,
};
function findMaxPopulation(swatches) {
let p = 0;
swatches.forEach((s) => { p = Math.max(p, s.population); });
return p;
}
function isAlreadySelected(palette, s) {
return palette.Vibrant === s
|| palette.DarkVibrant === s
|| palette.LightVibrant === s
|| palette.Muted === s
|| palette.DarkMuted === s
|| palette.LightMuted === s;
}
function createComparisonValue(saturation, targetSaturation, luma, targetLuma, population, maxPopulation, opts) {
function weightedMean(...values) {
let sum = 0;
let weightSum = 0;
for (let i = 0; i < values.length; i += 2) {
const value = values[i];
const weight = values[i + 1];
sum += value * weight;
weightSum += weight;
}
return sum / weightSum;
}
function invertDiff(value, targetValue) {
return 1 - Math.abs(value - targetValue);
}
return weightedMean(invertDiff(saturation, targetSaturation), opts.weightSaturation, invertDiff(luma, targetLuma), opts.weightLuma, population / maxPopulation, opts.weightPopulation);
}
function findColorVariation(palette, swatches, maxPopulation, targetLuma, minLuma, maxLuma, targetSaturation, minSaturation, maxSaturation, opts) {
let max = null;
let maxValue = 0;
swatches.forEach((swatch) => {
const [, s, l] = swatch.hsl;
if (s >= minSaturation && s <= maxSaturation
&& l >= minLuma && l <= maxLuma
&& !isAlreadySelected(palette, swatch)) {
const value = createComparisonValue(s, targetSaturation, l, targetLuma, swatch.population, maxPopulation, opts);
if (max === null || value > maxValue) {
max = swatch;
maxValue = value;
}
}
});
return max;
}
function generateVariationColors(swatches, maxPopulation, opts) {
const palette = {};
// mVibrantSwatch = findColor(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA,
// TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
palette.Vibrant = findColorVariation(palette, swatches, maxPopulation, opts.targetNormalLuma, opts.minNormalLuma, opts.maxNormalLuma, opts.targetVibrantSaturation, opts.minVibrantSaturation, 1, opts);
// mLightVibrantSwatch = findColor(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f,
// TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
palette.LightVibrant = findColorVariation(palette, swatches, maxPopulation, opts.targetLightLuma, opts.minLightLuma, 1, opts.targetVibrantSaturation, opts.minVibrantSaturation, 1, opts);
// mDarkVibrantSwatch = findColor(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA,
// TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
palette.DarkVibrant = findColorVariation(palette, swatches, maxPopulation, opts.targetDarkLuma, 0, opts.maxDarkLuma, opts.targetVibrantSaturation, opts.minVibrantSaturation, 1, opts);
// mMutedSwatch = findColor(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA,
// TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
palette.Muted = findColorVariation(palette, swatches, maxPopulation, opts.targetNormalLuma, opts.minNormalLuma, opts.maxNormalLuma, opts.targetMutesSaturation, 0, opts.maxMutesSaturation, opts);
// mLightMutedColor = findColor(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f,
// TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
palette.LightMuted = findColorVariation(palette, swatches, maxPopulation, opts.targetLightLuma, opts.minLightLuma, 1, opts.targetMutesSaturation, 0, opts.maxMutesSaturation, opts);
// mDarkMutedSwatch = findColor(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA,
// TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
palette.DarkMuted = findColorVariation(palette, swatches, maxPopulation, opts.targetDarkLuma, 0, opts.maxDarkLuma, opts.targetMutesSaturation, 0, opts.maxMutesSaturation, opts);
return palette;
}
function withLuminance(hsl, l) {
const [h, s] = hsl;
return [h, s, l];
}
function generateEmptySwatches(palette, maxPopulation, opts) {
if (palette.Vibrant === null && palette.DarkVibrant === null && palette.LightVibrant === null) {
if (palette.DarkVibrant === null && palette.DarkMuted !== null) {
const [h, s, l] = withLuminance(palette.DarkMuted.hsl, opts.targetDarkLuma);
palette.DarkVibrant = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
if (palette.LightVibrant === null && palette.LightMuted !== null) {
const [h, s, l] = withLuminance(palette.LightMuted.hsl, opts.targetDarkLuma);
palette.DarkVibrant = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
}
if (palette.Vibrant === null && palette.DarkVibrant !== null) {
const [h, s, l] = withLuminance(palette.DarkVibrant.hsl, opts.targetNormalLuma);
palette.Vibrant = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
else if (palette.Vibrant === null && palette.LightVibrant !== null) {
const [h, s, l] = withLuminance(palette.LightVibrant.hsl, opts.targetNormalLuma);
palette.Vibrant = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
if (palette.DarkVibrant === null && palette.Vibrant !== null) {
const [h, s, l] = withLuminance(palette.Vibrant.hsl, opts.targetDarkLuma);
palette.DarkVibrant = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
if (palette.LightVibrant === null && palette.Vibrant !== null) {
const [h, s, l] = withLuminance(palette.Vibrant.hsl, opts.targetLightLuma);
palette.LightVibrant = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
if (palette.Muted === null && palette.Vibrant !== null) {
const [h, s, l] = withLuminance(palette.Vibrant.hsl, opts.targetMutesSaturation);
palette.Muted = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
if (palette.DarkMuted === null && palette.DarkVibrant !== null) {
const [h, s, l] = withLuminance(palette.DarkVibrant.hsl, opts.targetMutesSaturation);
palette.DarkMuted = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
if (palette.LightMuted === null && palette.LightVibrant !== null) {
const [h, s, l] = withLuminance(palette.LightVibrant.hsl, opts.targetMutesSaturation);
palette.LightMuted = new color_1.Swatch(util_1.hslToRgb(h, s, l), 0);
}
}
const DefaultGenerator = (swatches, opts) => {
const optsWithDefaults = Object.assign(Object.assign({}, DefaultOpts), opts);
const maxPopulation = findMaxPopulation(swatches);
const palette = generateVariationColors(swatches, maxPopulation, optsWithDefaults);
generateEmptySwatches(palette, maxPopulation, optsWithDefaults);
return palette;
};
exports.default = DefaultGenerator;
//# sourceMappingURL=default.js.map