- 我有一个彩色(或黑白)图像作为 Base64 字符串
- 我有一个目标 RGB
- 我想为该图像着色,以便在将其调整为更小的尺寸时,它的平均RGB 非常接近我的目标 RGB
你可以在这里看到下面的代码
const MIX_OPACITY = 93;
const SMALL_WIDTH = 6;
const targetRGB = {
r: 77,
g: 19,
b: 80
};
const targetHEX = rgbToHex(targetRGB.r, targetRGB.g, targetRGB.b);
(async () => {
let originalBase64 = fs.readFileSync(`./src/bob.jpeg`, {
encoding: "base64"
});
let jimpOriginal = await Jimp.read(new Buffer(originalBase64, "base64"));
let jimpGrey = jimpOriginal.greyscale();
let jimpTint = await new Promise((resolve) => {
jimpGrey.color(
[
// { apply: 'brighten', params: [50] }, // made things worse
{ apply: "mix", params: [targetHEX, MIX_OPACITY] } // 50 stands for opacity
],
(err, res) => {
resolve(res);
}
);
});
let tintedBase64 = await new Promise((resolve) => {
jimpTint.getBase64(Jimp.AUTO, (err, res) => {
resolve(res.replace(/^data:image\/(png|jpeg);base64,/, ""));
});
});
fs.writeFileSync(`${__dirname}/bob-tint.jpeg`, tintedBase64, "base64");
let resized = await resize(tintedBase64, SMALL_WIDTH, true);
fs.writeFileSync(
`${__dirname}/bob-tint-small.jpeg`,
resized.base64,
"base64"
);
let avgRGB = await avgRgb(resized.base64, { isBase64: true });
let deltaResult = delta(
[avgRGB.r, avgRGB.g, avgRGB.b],
[targetRGB.r, targetRGB.g, targetRGB.b]
);
console.log("deltaResult = ", deltaResult);
if (deltaResult <= 2) {
console.log("all is good");
}
})();
我正在使用的 Jimp 库提供了各种颜色处理方法,但现在我只是在尝试mix
。它还提供brighten
, lighten
,desaturate
等。
我正在尝试找到方法和值的正确组合以达到所需的deltaResult <= 2
.
有可能吗?怎么做?现在我被困住了,因为我对颜色处理并不熟悉。
我意识到增加色调的不透明度显然会降低deltaResult
到所需的值。但是,增加不透明度也会降低内容的清晰度,因为它基本上会将图像“变暗”为所需的颜色,直到您主要看到所需颜色而不是照片的实际内容(在我的情况下是一张脸) . 我认为不可能同时保持内容的清晰度,同时拥有接近所需颜色的平均 RGB。
增加MIX_OPACITY
链接中使用的代码会降低deltaResult
但会损害清晰度,反之亦然。