如何从 img 获取 RGB 数组?

How can I get RGB array from img?

我正在尝试使用 canvas 获取 img 的 RGB 数组,如下所示:

Teplate

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="display"></div>
    <img id="face" src="./220px-Leonhard_Euler.jpg" />
    <canvas
      id="face2"
      width="112"
      height="112"
      style="border: 1px solid #d3d3d3;"
    ></canvas>

    <script src="src/index.js"></script>
  </body>
</html>

脚本

const img = document.getElementById("face");
img.crossOrigin = "anonymous";

const canvas = document.getElementById("face2");
const context = canvas.getContext("2d");
context.drawImage(img, 0, 0);

let pix = context.getImageData(0, 0, 112, 112).data;
pix = Array.from(pix);

const pix2 = [];

for (let i = 0; i < pix.length; i += 4) {
  pix2.push(pix[i + 0]);
  pix2.push(pix[i + 1]);
  pix2.push(pix[i + 2]);
}

const imgData = context.createImageData(112, 112);

for (let i = 0; i < imgData.data.length; i += 4) {
  imgData.data[i + 0] = pix2[i + 0];
  imgData.data[i + 1] = pix2[i + 1];
  imgData.data[i + 2] = pix2[i + 2];
  imgData.data[i + 3] = 255;
}

context.putImageData(imgData, 10, 10);

正如您在代码的第一部分中看到的那样,我尝试提取图像 RGBA 的 4d 数组,并尝试删除 alpha 通道。

在那之后,我尝试使用默认的 alpha 通道(如 255)再次设置图像,只是为了检查我是否只获得了 RGB 数据。

但是我得到了下面的图像:

输入图像是 112x112 而 canvas 是 112x112,知道为什么我只能得到 img 的 RGB 吗?

EDIT2

@tracktor 的响应有效,但我仍然在使用另一张这样的图片时出错:

相同的代码,唯一的区别是我使用 http://localhost:8080/face.jpg 而不是 crossorigin 加载此图像。

谢谢

HTMLImageElement crossorigin 属性

在 HTML 中的 img 标记上放置一个 crossorigin 属性,以确保浏览器 请求 具有 header 的图像s 用于 CORS 操作,例如

   Origin: http://localhost
   Sec-Fetch-Mode: cors
   Sec-Fetch-Site: cross-site

在 return 中,用图像数据响应的站点 必须 包括从“来源”请求中设置的“Access-Control-Allow-Origin” header header,比如

Access-Control-Allow-Origin: http://localhost

或通配符版本:

Access-Control-Allow-Origin: *

启用 javascript 访问数据 returned。

注意 https://i.stack.imgur.com 没有 return 访问控制 headers,因此从该域 return 编辑的图像会受到污染canvas objects。如果您正在编写或修改 node/express 服务器以支持 CORS,我强烈建议您阅读 http://expressjs.com/resources/middleware/cors.html

window load 事件

等到 window load 事件触发后处理图像数据。如果处理较早,图像加载可能不可用。


图像结果损坏

更新post中显示的不正确图像数据是由于pix2中的rgb数据三元组与[=22=中所需的rgba数据四元组没有对齐造成的].要成功转置像素数据,请尝试等效于:

for (let i = 0, j = 0; i < imgData.data.length; i += 4) {
  imgData.data[i + 0] = pix2[j++];
  imgData.data[i + 1] = pix2[j++];
  imgData.data[i + 2] = pix2[j++];
  imgData.data[i + 3] = 128;  // test value
}

以下代码片段创建了两个 canvas 元素:一个显示加载的图像,另一个显示 canvas 数据操作的结果。该代码在不同端口上使用本地主机服务器,没有它们将无法 运行 成功:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>cross origin</title></head>

<body>
<h2>Image</h2>
<img id="face" crossorigin src="http://localhost:8080/share/imperial.jpg" />
<h2>Canvas</h2>
<canvas
    id="face2"
    width="112"
    height="112"
    style="border: 1px solid blue"
></canvas>

<canvas
    id="modified"
    width="112"
    height="112"
    style="border: 1px solid red"
></canvas>

<script type="text/javascript">"use strict";
window.addEventListener("load", ()=> {
  const img = document.getElementById("face");
  const canvas = document.getElementById("face2");
  const context = canvas.getContext("2d");
  context.drawImage(img, 0, 0);

  let imgData1 = context.getImageData(0, 0, 112, 112)
  let pix;
  try {
    pix = imgData1.data;
  }
  catch( err) {
    console.warn( err.message);
  }

  pix = Array.from(pix);

  const pix2 = [];

  for (let i = 0; i < pix.length; i += 4) {
    pix2.push(pix[i + 0]);
    pix2.push(pix[i + 1]);
    pix2.push(pix[i + 2]);
  }

  const imgData = context.createImageData(112, 112);
  for (let i = 0, j = 0; i < imgData.data.length; i += 4) {
    imgData.data[i + 0] = pix2[j++];
    imgData.data[i + 1] = pix2[j++];
    imgData.data[i + 2] = pix2[j++];
    imgData.data[i + 3] = 128; // test value
  }
 
  const canvas2 = document.getElementById("modified");
  const context2 = canvas2.getContext("2d");
  context2.putImageData(imgData, 10, 10);

});
</script></body>
</html>