从HTML Canvas获取像素的颜色没有getImageData()?

时间:2018-02-27 16:56:12

标签: javascript html image canvas firefox-webextensions

任务

我目前正在尝试为Firefox创建一个网络扩展程序。 它应该能够读取图像的像素。 为此,我在一个不可见的画布上渲染图像,然后我想读它。

示例代码

function getImdata(reference) {
    var canvas=document.createElement("canvas");
    canvas.width=reference.naturalWidth;
    canvas.height=reference.naturalHeight;
    var context=canvas.getContext("2d");
    context.drawImage(reference,0,0);
    return context.getImageData(0,0,reference.naturalWidth,reference.naturalHeight); //Here I actually get the error...
}

问题

但是,如果我使用“getImageData()”,我会收到“安全错误”。

问题

所以我需要一个解决方法,但我自己找不到任何东西。 如何在没有getImageData()的情况下读取图像的像素?

修改

显然它与CORS有关:HTML5 Canvas getImageData and Same Origin Policy

提前致谢!

1 个答案:

答案 0 :(得分:1)

有。由于您是从扩展程序运行,因此您的扩展程序将 特权访问 发送到跨源来源,但仅限于loaded via fetch() and XMLHttpRequest() from a content script(或后台脚本) - 摘录自链接:

  

内容脚本获得与其他脚本相同的跨域权限   扩展名:所以如果扩展程序已请求跨域访问   对于使用manifest.json中的权限键的域,然后是它   内容脚本也可以访问该域。

     

这是通过公开更多特权XHR和获取来实现的   内容脚本中的实例[...]

请注意,从内容脚本调用时,这些调用不会设置originreferer标题,如果跨源网站希望设置这些标题,有时会导致问题 - 对于在这些情况下,您需要使用非特权content.XMLHttpRequestcontent.fetch(),这将使您回到原点。

清单文件中的权限(或动态设置权限)还必须允许访问这些跨源站点。

但这意味着您必须通过这些调用单独“重新加载”图像源。您可以通过以下方式执行此操作:首先获取要加载的图片的原始网址,例如,来自内容脚本

// example loading all images in current tab
let images = document.querySelectorAll("img");
for(let image of images) loadAsBitmap(image.src); // some sub-call using the url

然后通过内容脚本fetch()

加载该来源
fetch(src).then(resp => {  // load from original source
  return resp.blob();      // obtain a blob
}).then(blob => {          // convert blob, see below
  // ...
};

当获得blob时,您可以将其转换为Object-URL并将其设置为图像的源,并且能够绕过我们原本面临的跨源限制。在内容脚本中,接下来的步骤是:

let url = URL.createObjectURL(blob);         // attach Object-URL to blob
let img = new Image();                       // create image element *
img.onload = () => {                         // attach handler
  let c = document.createElement("canvas");  // create canvas
  let ctx = c.getContext("2d");              // get context
  c.width = img.width;                       // canvas size = image
  c.height = img.height;
  ctx.drawImage(img, 0, 0);                  // draw in image
  URL.revokeObjectURL(url);                  // remove reference.
  let imageData = 
    ctx.getImageData(0,0,c.width,c.height);  // get image data
  // .. callback to a function that handles the image data
};
img.src = url;                               // start loading blob