在没有 getImageData() 的情况下从 HTML Canvas 获取像素的颜色?
Get pixels' colors from HTML Canvas WITHOUT getImageData()?
任务
我目前正在尝试为 Firefox 创建一个网络扩展。
它应该能够读取图像的像素。
为此,我在不可见的 canvas 上渲染图像,然后我想阅读它。
示例代码
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()",我会得到一个 "Security Error"。
问题
所以我需要一个解决方法,但我自己找不到任何东西。
如何在没有 getImageData() 的情况下读取图像的像素?
编辑
显然它与 CORS 有关:HTML5 Canvas getImageData and Same Origin Policy
提前致谢!
有。由于您 运行 来自一个扩展程序,您的扩展程序将具有 对 cross-origin 来源的 特权访问权 但前提是 loaded via fetch()
and XMLHttpRequest()
from a content script(或背景脚本)- 摘自 link:
Content scripts get the same cross-domain privileges as the rest of
the extension: so if the extension has requested cross-domain access
for a domain using the permissions key in manifest.json, then its
content scripts get access that domain as well.
This is accomplished by exposing more privileged XHR and fetch
instances in the content script [...]
请注意,从内容脚本调用时这些调用不会设置 origin
和 referer
headers 如果 cross-origin 站点希望设置这些 - 对于这些情况,您将需要使用 non-privileged content.XMLHttpRequest
或 content.fetch()
,这将使您回到第一个问题。
清单文件中的权限(或者如果动态设置权限)还必须允许访问这些 cross-origin 站点。
然而,这意味着您必须通过这些调用单独 "reload" 图像源。您可以通过以下方式执行此操作,首先从内容脚本 :
中获取要加载的图像的原始 URL,例如
// 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 并将其设置为图像的来源,并能够绕过我们否则会面临的 cross-origin 限制。在内容脚本中,接下来的步骤是:
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
任务
我目前正在尝试为 Firefox 创建一个网络扩展。 它应该能够读取图像的像素。 为此,我在不可见的 canvas 上渲染图像,然后我想阅读它。
示例代码
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()",我会得到一个 "Security Error"。
问题
所以我需要一个解决方法,但我自己找不到任何东西。 如何在没有 getImageData() 的情况下读取图像的像素?
编辑
显然它与 CORS 有关:HTML5 Canvas getImageData and Same Origin Policy
提前致谢!
有。由于您 运行 来自一个扩展程序,您的扩展程序将具有 对 cross-origin 来源的 特权访问权 但前提是 loaded via fetch()
and XMLHttpRequest()
from a content script(或背景脚本)- 摘自 link:
Content scripts get the same cross-domain privileges as the rest of the extension: so if the extension has requested cross-domain access for a domain using the permissions key in manifest.json, then its content scripts get access that domain as well.
This is accomplished by exposing more privileged XHR and fetch instances in the content script [...]
请注意,从内容脚本调用时这些调用不会设置 origin
和 referer
headers 如果 cross-origin 站点希望设置这些 - 对于这些情况,您将需要使用 non-privileged content.XMLHttpRequest
或 content.fetch()
,这将使您回到第一个问题。
清单文件中的权限(或者如果动态设置权限)还必须允许访问这些 cross-origin 站点。
然而,这意味着您必须通过这些调用单独 "reload" 图像源。您可以通过以下方式执行此操作,首先从内容脚本 :
中获取要加载的图像的原始 URL,例如// 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 并将其设置为图像的来源,并能够绕过我们否则会面临的 cross-origin 限制。在内容脚本中,接下来的步骤是:
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