1
  1. 我有一个彩色(或黑白)图像作为 Base64 字符串
  2. 我有一个目标 RGB
  3. 我想为该图像着色,以便在将其调整为更小的尺寸时,它的平均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但会损害清晰度,反之亦然。

4

0 回答 0