mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-12-18 07:21:56 +03:00
Embrace chroma.js and okLCH
This commit is contained in:
parent
c6e562c62e
commit
cc591237f5
4 changed files with 24 additions and 100 deletions
|
@ -26,6 +26,7 @@
|
||||||
"@lingui/macro": "~4.13.0",
|
"@lingui/macro": "~4.13.0",
|
||||||
"@lingui/react": "~4.13.0",
|
"@lingui/react": "~4.13.0",
|
||||||
"@szhsin/react-menu": "~4.2.2",
|
"@szhsin/react-menu": "~4.2.2",
|
||||||
|
"chroma-js": "~3.1.2",
|
||||||
"compare-versions": "~6.1.1",
|
"compare-versions": "~6.1.1",
|
||||||
"fast-blurhash": "~1.1.4",
|
"fast-blurhash": "~1.1.4",
|
||||||
"fast-equals": "~5.0.1",
|
"fast-equals": "~5.0.1",
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from 'preact/hooks';
|
} from 'preact/hooks';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
|
||||||
import { oklab2rgb, rgb2oklab } from '../utils/color-utils';
|
import { oklch2rgb, rgb2oklch } from '../utils/color-utils';
|
||||||
import isRTL from '../utils/is-rtl';
|
import isRTL from '../utils/is-rtl';
|
||||||
import showToast from '../utils/show-toast';
|
import showToast from '../utils/show-toast';
|
||||||
import states from '../utils/states';
|
import states from '../utils/states';
|
||||||
|
@ -116,59 +116,28 @@ function MediaModal({
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const mediaOklabColors = useMemo(() => {
|
const mediaOkColors = useMemo(() => {
|
||||||
return mediaAttachments?.map((media) => {
|
return mediaAttachments?.map((media) => {
|
||||||
const { blurhash } = media;
|
const { blurhash } = media;
|
||||||
if (blurhash) {
|
if (blurhash) {
|
||||||
const averageColor = getBlurHashAverageColor(blurhash);
|
const averageColor = getBlurHashAverageColor(blurhash);
|
||||||
return rgb2oklab(averageColor);
|
return rgb2oklch(averageColor);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}, [mediaAttachments]);
|
}, [mediaAttachments]);
|
||||||
// const mediaAccentColors = useMemo(() => {
|
|
||||||
// return mediaOklabColors?.map((labAverageColor) => {
|
|
||||||
// if (labAverageColor) {
|
|
||||||
// return oklab2rgb([0.6, labAverageColor[1], labAverageColor[2]]);
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
// });
|
|
||||||
// }, [mediaOklabColors]);
|
|
||||||
const mediaAccentColors = useMemo(() => {
|
const mediaAccentColors = useMemo(() => {
|
||||||
return mediaOklabColors?.map((labAverageColor) => {
|
return mediaOkColors?.map((okColor) => {
|
||||||
if (labAverageColor) {
|
if (okColor) {
|
||||||
return {
|
return {
|
||||||
light: oklab2rgb([0.95, labAverageColor[1], labAverageColor[2]]),
|
light: oklch2rgb([0.95, 0.01, okColor[2]]),
|
||||||
dark: oklab2rgb([0.25, labAverageColor[1], labAverageColor[2]]),
|
dark: oklch2rgb([0.35, 0.01, okColor[2]]),
|
||||||
default: oklab2rgb([0.6, labAverageColor[1], labAverageColor[2]]),
|
default: oklch2rgb([0.6, okColor[1], okColor[2]]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// const mediaAccentGradient = useMemo(() => {
|
|
||||||
// const gap = 5;
|
|
||||||
// const range = 100 / mediaAccentColors.length;
|
|
||||||
// return (
|
|
||||||
// mediaAccentColors
|
|
||||||
// ?.map((color, i) => {
|
|
||||||
// const start = i * range + gap;
|
|
||||||
// const end = (i + 1) * range - gap;
|
|
||||||
// if (color) {
|
|
||||||
// return `
|
|
||||||
// rgba(${color?.join(',')}, 0.4) ${start}%,
|
|
||||||
// rgba(${color?.join(',')}, 0.4) ${end}%
|
|
||||||
// `;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return `
|
|
||||||
// transparent ${start}%,
|
|
||||||
// transparent ${end}%
|
|
||||||
// `;
|
|
||||||
// })
|
|
||||||
// ?.join(', ') || 'transparent'
|
|
||||||
// );
|
|
||||||
// }, [mediaAccentColors]);
|
|
||||||
const mediaAccentGradients = useMemo(() => {
|
const mediaAccentGradients = useMemo(() => {
|
||||||
const gap = 5;
|
const gap = 5;
|
||||||
const range = 100 / mediaAccentColors.length;
|
const range = 100 / mediaAccentColors.length;
|
||||||
|
|
20
src/locales/en.po
generated
20
src/locales/en.po
generated
|
@ -106,7 +106,7 @@ msgstr ""
|
||||||
#: src/components/account-info.jsx:1118
|
#: src/components/account-info.jsx:1118
|
||||||
#: src/components/compose.jsx:2488
|
#: src/components/compose.jsx:2488
|
||||||
#: src/components/media-alt-modal.jsx:45
|
#: src/components/media-alt-modal.jsx:45
|
||||||
#: src/components/media-modal.jsx:388
|
#: src/components/media-modal.jsx:357
|
||||||
#: src/components/status.jsx:1721
|
#: src/components/status.jsx:1721
|
||||||
#: src/components/status.jsx:1738
|
#: src/components/status.jsx:1738
|
||||||
#: src/components/status.jsx:1862
|
#: src/components/status.jsx:1862
|
||||||
|
@ -410,7 +410,7 @@ msgstr ""
|
||||||
#: src/components/keyboard-shortcuts-help.jsx:39
|
#: src/components/keyboard-shortcuts-help.jsx:39
|
||||||
#: src/components/list-add-edit.jsx:35
|
#: src/components/list-add-edit.jsx:35
|
||||||
#: src/components/media-alt-modal.jsx:33
|
#: src/components/media-alt-modal.jsx:33
|
||||||
#: src/components/media-modal.jsx:352
|
#: src/components/media-modal.jsx:321
|
||||||
#: src/components/notification-service.jsx:156
|
#: src/components/notification-service.jsx:156
|
||||||
#: src/components/report-modal.jsx:75
|
#: src/components/report-modal.jsx:75
|
||||||
#: src/components/shortcuts-settings.jsx:230
|
#: src/components/shortcuts-settings.jsx:230
|
||||||
|
@ -858,13 +858,13 @@ msgid "Type to search GIFs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/compose.jsx:3491
|
#: src/components/compose.jsx:3491
|
||||||
#: src/components/media-modal.jsx:492
|
#: src/components/media-modal.jsx:461
|
||||||
#: src/components/timeline.jsx:889
|
#: src/components/timeline.jsx:889
|
||||||
msgid "Previous"
|
msgid "Previous"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/compose.jsx:3509
|
#: src/components/compose.jsx:3509
|
||||||
#: src/components/media-modal.jsx:511
|
#: src/components/media-modal.jsx:480
|
||||||
#: src/components/timeline.jsx:906
|
#: src/components/timeline.jsx:906
|
||||||
msgid "Next"
|
msgid "Next"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1185,27 +1185,27 @@ msgstr ""
|
||||||
msgid "Speak"
|
msgid "Speak"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/media-modal.jsx:399
|
#: src/components/media-modal.jsx:368
|
||||||
msgid "Open original media in new window"
|
msgid "Open original media in new window"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/media-modal.jsx:403
|
#: src/components/media-modal.jsx:372
|
||||||
msgid "Open original media"
|
msgid "Open original media"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/media-modal.jsx:419
|
#: src/components/media-modal.jsx:388
|
||||||
msgid "Attempting to describe image. Please wait…"
|
msgid "Attempting to describe image. Please wait…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/media-modal.jsx:434
|
#: src/components/media-modal.jsx:403
|
||||||
msgid "Failed to describe image"
|
msgid "Failed to describe image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/media-modal.jsx:444
|
#: src/components/media-modal.jsx:413
|
||||||
msgid "Describe image…"
|
msgid "Describe image…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/components/media-modal.jsx:467
|
#: src/components/media-modal.jsx:436
|
||||||
msgid "View post"
|
msgid "View post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,6 @@
|
||||||
// https://gist.github.com/earthbound19/e7fe15fdf8ca3ef814750a61bc75b5ce
|
import oklab2rgb from 'chroma-js/src/io/oklab/oklab2rgb.js';
|
||||||
function clamp(value, min, max) {
|
import rgb2oklab from 'chroma-js/src/io/oklab/rgb2oklab.js';
|
||||||
return Math.max(Math.min(value, max), min);
|
import oklch2rgb from 'chroma-js/src/io/oklch/oklch2rgb.js';
|
||||||
}
|
import rgb2oklch from 'chroma-js/src/io/oklch/rgb2oklch.js';
|
||||||
|
|
||||||
const gammaToLinear = (c) =>
|
export { oklab2rgb, rgb2oklab, oklch2rgb, rgb2oklch };
|
||||||
c >= 0.04045 ? Math.pow((c + 0.055) / 1.055, 2.4) : c / 12.92;
|
|
||||||
const linearToGamma = (c) =>
|
|
||||||
c >= 0.0031308 ? 1.055 * Math.pow(c, 1 / 2.4) - 0.055 : 12.92 * c;
|
|
||||||
|
|
||||||
export function rgb2oklab([r, g, b]) {
|
|
||||||
r = gammaToLinear(r / 255);
|
|
||||||
g = gammaToLinear(g / 255);
|
|
||||||
b = gammaToLinear(b / 255);
|
|
||||||
var l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
||||||
var m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
||||||
var s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
||||||
l = Math.cbrt(l);
|
|
||||||
m = Math.cbrt(m);
|
|
||||||
s = Math.cbrt(s);
|
|
||||||
return [
|
|
||||||
l * +0.2104542553 + m * +0.793617785 + s * -0.0040720468,
|
|
||||||
l * +1.9779984951 + m * -2.428592205 + s * +0.4505937099,
|
|
||||||
l * +0.0259040371 + m * +0.7827717662 + s * -0.808675766,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function oklab2rgb([L, a, b]) {
|
|
||||||
var l = L + a * +0.3963377774 + b * +0.2158037573;
|
|
||||||
var m = L + a * -0.1055613458 + b * -0.0638541728;
|
|
||||||
var s = L + a * -0.0894841775 + b * -1.291485548;
|
|
||||||
// The ** operator here cubes; same as l_*l_*l_ in the C++ example:
|
|
||||||
l = l ** 3;
|
|
||||||
m = m ** 3;
|
|
||||||
s = s ** 3;
|
|
||||||
var r = l * +4.0767416621 + m * -3.3077115913 + s * +0.2309699292;
|
|
||||||
var g = l * -1.2684380046 + m * +2.6097574011 + s * -0.3413193965;
|
|
||||||
var b = l * -0.0041960863 + m * -0.7034186147 + s * +1.707614701;
|
|
||||||
// Convert linear RGB values returned from oklab math to sRGB for our use before returning them:
|
|
||||||
r = 255 * linearToGamma(r);
|
|
||||||
g = 255 * linearToGamma(g);
|
|
||||||
b = 255 * linearToGamma(b);
|
|
||||||
// OPTION: clamp r g and b values to the range 0-255; but if you use the values immediately to draw, JavaScript clamps them on use:
|
|
||||||
r = clamp(r, 0, 255);
|
|
||||||
g = clamp(g, 0, 255);
|
|
||||||
b = clamp(b, 0, 255);
|
|
||||||
// OPTION: round the values. May not be necessary if you use them immediately for rendering in JavaScript, as JavaScript (also) discards decimals on render:
|
|
||||||
r = Math.round(r);
|
|
||||||
g = Math.round(g);
|
|
||||||
b = Math.round(b);
|
|
||||||
return [r, g, b];
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue