Node.js

Как изменить цвет PNG на Node.js через sharp

Короткий ответ: для обработки PNG в Node.js чаще всего используют библиотеку sharp. Если PNG — это простая иконка с прозрачным фоном, ее можно перекрасить через tint. Если нужно заменить конкретный цвет внутри сложной картинки, задача становится не “поменять цвет”, а обработать пиксели по условию

Этот материал полезен, когда нужно автоматически готовить аватарки, иконки, бейджи, цветовые версии логотипа или изображения для карточек. Но важно сразу разделить два сценария: перекрасить одноцветную иконку легко, а аккуратно заменить один цвет на фотографии намного сложнее

Установите sharp

Создайте папку проекта

mkdir png-color-node
cd png-color-node
npm init -y
npm install sharp

Положите рядом файл icon.png. Лучше начать с простой PNG-иконки: темный силуэт на прозрачном фоне

Самый простой вариант: tint

Создайте index.js

const sharp = require("sharp");

async function recolorPng() {
  await sharp("icon.png")
    .tint("#1d4ed8")
    .png()
    .toFile("icon-blue.png");

  console.log("Готово: icon-blue.png");
}

recolorPng().catch(console.error);

Запустите

node index.js

Метод tint хорошо подходит для одноцветных иконок. Он сохраняет прозрачность и меняет общий оттенок изображения

Если нужно сделать белую иконку

Для белого варианта

const sharp = require("sharp");

async function makeWhiteIcon() {
  await sharp("icon.png")
    .tint("#ffffff")
    .png()
    .toFile("icon-white.png");
}

makeWhiteIcon().catch(console.error);

Если исходная иконка уже цветная, результат может быть не таким чистым, как ожидалось. Для идеальной перекраски лучше иметь черную или однотонную маску с прозрачным фоном

Перекраска через наложение цвета и альфа-канал

Более контролируемый вариант — взять альфа-канал исходной PNG и наложить новый цвет как фон

const sharp = require("sharp");

async function recolorByAlpha() {
  const image = sharp("icon.png");
  const metadata = await image.metadata();

  await sharp({
    create: {
      width: metadata.width,
      height: metadata.height,
      channels: 4,
      background: "#ef4444"
    }
  })
    .composite([
      {
        input: await sharp("icon.png").extractChannel("alpha").toBuffer(),
        blend: "dest-in"
      }
    ])
    .png()
    .toFile("icon-red.png");

  console.log("Готово: icon-red.png");
}

recolorByAlpha().catch(console.error);

Этот подход полезен, если нужно получить ровно один цвет и сохранить форму и прозрачность исходной иконки

Как заменить конкретный цвет

Если задача звучит “все красное сделать синим”, придется работать с пикселями. Для простых изображений можно использовать raw

const sharp = require("sharp");

async function replaceRedWithBlue() {
  const image = sharp("image.png").ensureAlpha();
  const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });

  for (let i = 0; i < data.length; i += 4) {
    const red = data[i];
    const green = data[i + 1];
    const blue = data[i + 2];

    const isRed = red > 180 && green < 80 && blue < 80;

    if (isRed) {
      data[i] = 29;
      data[i + 1] = 78;
      data[i + 2] = 216;
    }
  }

  await sharp(data, {
    raw: {
      width: info.width,
      height: info.height,
      channels: 4
    }
  })
    .png()
    .toFile("image-recolored.png");
}

replaceRedWithBlue().catch(console.error);

Этот код заменяет ярко-красные пиксели на синие. Для реальных фотографий границы цвета нужно подбирать аккуратнее, потому что тени, сглаживание и полутона редко имеют один точный RGB

Как сделать функцию для проекта

Вынесите обработку в отдельную функцию

const sharp = require("sharp");

async function recolorIcon(inputPath, outputPath, color) {
  const image = sharp(inputPath);
  const metadata = await image.metadata();

  await sharp({
    create: {
      width: metadata.width,
      height: metadata.height,
      channels: 4,
      background: color
    }
  })
    .composite([
      {
        input: await sharp(inputPath).extractChannel("alpha").toBuffer(),
        blend: "dest-in"
      }
    ])
    .png()
    .toFile(outputPath);
}

module.exports = { recolorIcon };

Теперь функцию можно использовать в Express-роуте, скрипте генерации картинок или сборке ассетов

Мини-практика

Возьмите одну PNG-иконку с прозрачным фоном и сделайте три версии: синюю, красную и белую. После этого проверьте, что прозрачность сохранилась, а размер файла не стал неожиданно огромным

Дополнительное упражнение: добавьте массив цветов и сгенерируйте несколько файлов в цикле

const colors = ["#1d4ed8", "#ef4444", "#22c55e"];

Частые ошибки

Пытаются перекрасить сложную фотографию как иконку tint подходит не для всех изображений. Для фотографии нужна другая логика обработки цвета

Теряют прозрачность Следите за альфа-каналом. Для иконок с прозрачным фоном это ключевая часть результата

Не ждут завершения асинхронной операции sharp(...).toFile(...) возвращает promise. Используйте await или .then

Сохраняют результат поверх исходника На этапе экспериментов лучше писать в новый файл, чтобы не потерять оригинал

Что почитать дальше по Node.js

Если нужен общий маршрут по теме, откройте рубрику Node.js. Для соседних задач пригодятся эти разборы:

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x