Вор цвета Найдите цвет на картинке


Проблема, которую необходимо решить в данной статье

Я думал, что определение цветов в изображении — это функция, требующая искусственного интеллекта или чего-то за пределами интеллекта Конана, но после некоторых любопытных исследований я обнаружил, что это можно сделать на переднем крае! Принцип заключается в том, что canvas имеет функцию getImageData, которая может получить информацию RGBA каждого пикселя, а затем выполнить математический процесс, который не смог бы выполнить даже первоклассник Конан, чтобы вычислить цветовой код изображения.

И тогда, да, мир инженеров полон богов, которые поддерживают мир во всем мире и будут делать наборы из этих сложных математических операций.

В данном случае Color Thief — это набор, позволяющий извлечь цветовой код изображения, а также расширить его, чтобы показать основной цветовой код и другие цветовые коды файла изображения после его выбора.

Причины рекомендовать Color Thief.

  • Поддержка браузеров, Node.js
  • Четкая документация
  • Простота в использовании, наглядные примеры (kudos)
  • С открытым исходным кодом и бесплатно

Color Thief GitHub:

https://github.com/lokesh/color-thief/

Файлы справки Color Thief, демо-версии:

https://lokeshdhakar.com/projects/color-thief/

Вот еще два связанных ресурса, которые Август нашел полезными при поиске информации.

  • Принцип: Извлечение цветовой палитры из изображения с помощью javascript
  • Связанный пакет: Rgbaster.js

Последняя демонстрация этой статьи:

https://letswritetw.github.io/letswrite-color-thief/

Недавно я захотел начать трогать Vue.js 3, поэтому исходный файл демо, JS написан на Vue 3.


Базовое использование Color Thief

Ссылки на JS

Для игры Color Thief существует четыре JS-файла.

  • color-thief.js: для Node.js.
  • color-thief.mjs: для импорта ES6, используется в Webpack и Rollup.
  • color-thief.umd.js, color-thief.min.js: используются как прямые ссылки на CDN.

Самый простой способ сделать прямую ссылку на CDN — это

<script src="https://cdnjs.cloudflare.com/ajax/libs/color-thief/2.3.0/color-thief.umd.js"></script>
Войдите в полноэкранный режим Выход из полноэкранного режима

В этом демо используется ES6, и после того, как в терминале выполняется yarn add colorthief, ссылка выглядит следующим образом

import ColorThief from './../node_modules/colorthief/dist/color-thief.mjs';
Войдите в полноэкранный режим Выход из полноэкранного режима

Самое приятное в Color Thief то, что это всего две функции, так что вам не придется смотреть на такой длинный файл.

Вот две функции: getColor и getPalette.

getColor получает код основного цвета

getColor получает основной цветовой код изображения, то есть цветовой код наиболее используемого цвета в изображении.

getColor(image [, quality])
// => [R, G, B]
Войдите в полноэкранный режим Выход из полноэкранного режима

image: указывается само изображение, а не путь к файлу изображения.

Допустим, мы цитируем HTML, поступающий с изображения, следующим образом

<img id="i_am_image" src="xxx.jpg">
Войдите в полноэкранный режим Выход из полноэкранного режима

Вместо xxx.jpg, изображение будет представлено как

const img = document.getElementById('i_am_image');
Войдите в полноэкранный режим Выход из полноэкранного режима

quality: необязательный параметр, задается как целое число больше 1, значение по умолчанию 10.

Значение по умолчанию — 10. quality означает «Делаете ли вы захват каждые несколько пикселей? Как уже упоминалось в начале, внешний модуль определяет цветовой код изображения, захватывая каждый пиксель и получая его значение RGBA, а затем выполняя ряд математических операций, чтобы вычислить наиболее часто используемый RGBA.

Если размер изображения составляет всего 10px * 10px, и захватывается каждый пиксель, то всего нужно захватить и рассчитать 100 пикселей.

Что если сегодняшнее изображение имеет размер 1024px * 1024px? Или даже больше? Захват каждого пикселя отнимает много времени.

quality устанавливается на захват каждые несколько пикселей, а значение по умолчанию 10 — на захват каждые 10 пикселей. Поэтому значение 1 является наиболее точным, но если изображение большое, оно будет возвращаться очень медленно.

getPalette Получить палитру

Помимо основного цветового кода, в изображении используются и другие цветовые коды. getPalette — это способ захвата всех этих цветов.

getPalette(image [, colorCount, quality]
// => [[R, G, B], [R, G, B], ... ]
Войдите в полноэкранный режим Выход из полноэкранного режима

image, quality Эти два параметра аналогичны параметру getColor и не будут здесь повторяться.

colorCount: для захвата нескольких цветов, значение по умолчанию 10.

Результатом является массив с заданным количеством (colorCount) массивов, три значения для каждого массива — R, G и B.

Пример использования

Здесь мы захватываем изображение, берем его основной цветовой код и цветовые коды других цветов в палитре.

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

В официальной документации Color Thief приводится следующий пример

const colorThief = new ColorThief();
const img = document.querySelector('img');

if (img.complete) {
  colorThief.getColor(img);
  colorThief.getPalette(img);
} else {
  image.addEventListener('load', function() {
    colorThief.getColor(img);
    colorThief.getPalette(img);
  });
}
Войдите в полноэкранный режим Выход из полноэкранного режима

img.complete: Убедитесь, что изображение загружено.

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

// ...
methods: {
  // 確定圖片載入完成
  waitImageLoad(img) {
    return new Promise((resolve, reject) => {
      let timer;
      timer = () => {
        setTimeout(() => {
          if(img.complete) resolve(true);
          else timer();
        }, 100);
      }
      timer();
    })
  },
  // 基本使用,取得圖片色碼
  async getColors() {
    const colorThief = new ColorThief();
    const img = document.getElementById('i_am_image');
    await this.waitImageLoad(img);
    let color = this.colorThief.getColor(img);
    let palette = this.colorThief.getPalette(img);
  }
},
mounted() {
  this.getColors();
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Демонстрационная страница была исправлена с помощью Tailwind CSS, и базовое использование в итоге выглядело следующим образом.

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

Цветовой код также был изменен с RGB на Hex, как объясняется в следующих нескольких абзацах.


Расширенное использование: сортировка цветовых кодов от светлого к темному

Это предположение самого Августа, и никаких других научных экспериментов для его подтверждения не проводилось XD.

Когда мы пишем цвета в CSS, черно-белые цвета будут выглядеть следующим образом

  • Черный: #000 || rgb(0, 0, 0)
  • Белый: #FFF || rgb(255, 255, 255)

Как видно из rgb, чем меньше сумма трех, тем темнее цвет, а чем больше сумма, тем светлее цвет.

Поэтому нам просто нужно сложить три числа rgb и затем проранжировать их от большого к маленькому, чтобы цветовой код палитры отображался от светлого к темному.

В Javascript, reduce может суммировать числа в массиве. Ну… немного нелепо, что слово reduce не означает «уменьшать», но при использовании в JS оно означает add up, что странно ~» ~. (сократить описание MDN)

sortPalette(array) {
  // 建一個空陣列,把調色盤裡的 RGB 存進去,並存一個三數加總的值
  let tempForCalc = [];
  Array.prototype.forEach.call(array, palette => {
    const sum = palette.reduce((a, b) => a + b, 0);
    const item = {
      color: palette,
      sum: sum
    }
    tempForCalc.push(item);
  });

  // 用三數加總的值做 大 -> 小 排序
  const result = tempForCalc.concat().sort((a, b) => {
    return a.sum > b.sum ? -1 : 1;
  });
  return result;
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Расширенное использование: получение выбранного пользователем файла изображения

Настройте input type="file" См. предыдущее примечание, которое здесь не объясняется.

Файловый API пользовательская кнопка загрузки файла / файл ввода

После того, как пользователь выбрал файл, существует два способа запихнуть выбранный файл изображения в img src: Blob, Base64.

В этом демонстрационном примере используется Blob для захвата файла изображения, поскольку количество записываемых строк относительно невелико.(Я потрачу его впустую)

Метод преобразования в Base64 также написан в исходном коде, вы можете найти getUploadImgBase64 в src/main.js в исходном файле.

async getUploadImgBlob(file) {
  const fileData = file.target.files[0];
  const customImg = window.URL.createObjectURL(fileData);

  // 確定 #i_am_image 的圖片載入完成
  // waitImageLoad:前面幾段「確定圖片載入完成」的 method
  const img = document.getElementById('i_am_image');
  await this.waitImageLoad(img);

  // 執行 colorThief
  const colorThief = new ColorThief();
  const color = colorThief.getColor(img, 5);

  // sortPalette:前面幾段「排序色碼由亮到暗」的 method
  let tempPalette = colorThief.getPalette(img, 10, 5);
  const palette = this.sortPalette(tempPalette);
},
Войдите в полноэкранный режим Выход из полноэкранного режима

Расширенное использование: цветовые коды RGB в Hex

Когда мы пишем CSS, мы редко пишем цвета в RGB, а в основном в шестнадцатеричных кодах, таких как «#000000», ну, по крайней мере, к этому привык Август.

В официальной документации приводится метод преобразования RGB в Hex

const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => {
  const hex = x.toString(16)
  return hex.length === 1 ? '0' + hex : hex
}).join('')

rgbToHex(102, 51, 153); // #663399
Войдите в полноэкранный режим Выход из полноэкранного режима

В данном демонстрационном примере эта функция заменяется на метод Vue, который при рендеринге преобразует полученный RGB в Hex.

toHex(colors) {
  let hex = colors.map(x => {
    return x.toString(16);
  }).join('');
  return '#' + hex
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Исходный код и демонстрация

Исходный код этой статьи доступен на GitHub, а демонстрационная страница была создана с помощью GitHub Pages.

Пожалуйста, поделитесь этой статьей или дайте ей звезду на GitHub, прежде чем использовать ее, так как ваш маленький жест будет большим подспорьем для сайта.

Исходный код:

https://github.com/letswritetw/letswrite-color-thief

Демо:

https://letswritetw.github.io/letswrite-color-thief/

Оцените статью
devanswers.ru
Добавить комментарий