Как получить данные о пикселях в JS?

Что я хочу:

  • Ввод: файл-картинка, например 32х32
  • Вывод: массив пикселей типа ['RGB1', ..., 'RGB1024']

Вот код, который есть

window.addEventListener('load', function() {
  document.querySelector('input[type="file"]').addEventListener('change', async function() {
      if (this.files && this.files[0]) {
        const bitmap = await createImageBitmap(this.files[0])
        console.log(bitmap)
      }
  });
});
<input type="file">

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


Ответы (1 шт):

Автор решения: Leonid

Не обязательно отрисовывать где-то "на виду", можно воспользоваться OffscreenCanvas.

window.addEventListener('load', function() {
  document.querySelector('input[type="file"]').addEventListener('change', async function() {
    if (this.files && this.files[0]) {
      const bitmap = await createImageBitmap(this.files[0])

      const offscreen = new OffscreenCanvas(bitmap.width, bitmap.height);
      const off_ctx = offscreen.getContext("2d");
      off_ctx.drawImage(bitmap, 0, 0);
      console.log(off_ctx.getImageData(0, 0, bitmap.width, bitmap.height).data);
    }
  });
});
<input type="file">

Если вывод нужен указанного формата (только с альфа-каналом - можно формат вывода изменить), то:

window.addEventListener('load', function() {
  document.querySelector('input[type="file"]').addEventListener('change', async function() {
    if (this.files && this.files[0]) {
      const bitmap = await createImageBitmap(this.files[0])

      const offscreen = new OffscreenCanvas(bitmap.width, bitmap.height);
      const off_ctx = offscreen.getContext("2d");
      off_ctx.drawImage(bitmap, 0, 0);
      console.log(rgba(off_ctx.getImageData(0, 0, bitmap.width, bitmap.height).data));
    }
  });
});

function rgba(data) {
  const result = [];
  for (let i = 0; i < data.length; i += 4) {
    result.push(`RGBA${i/4+1}: ${data[i]},${data[i+1]},${data[i+2]},${data[i+3]}`);
  }
  return result;
}
<input type="file">

→ Ссылка