Canvas 污染帆布

Canvas 污染帆布,canvas,http-headers,cors,webgl,Canvas,Http Headers,Cors,Webgl,我正在运行一个mjpeg拖缆,并试图在three.js中将流设置为纹理 我把它写在画布上,然后把画布作为纹理。 但是,我得到一个受污染的画布错误 DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': Tainted canvases may not be loaded. 我已经在服务器上添加了crossOrigin标头,它的接收方式如下: Access-Control-Allow-Origin:*

我正在运行一个mjpeg拖缆,并试图在three.js中将流设置为纹理

我把它写在画布上,然后把画布作为纹理。 但是,我得到一个受污染的画布错误

DOMException: Failed to execute 'texImage2D' on 'WebGLRenderingContext': 
Tainted canvases may not be loaded.
我已经在服务器上添加了crossOrigin标头,它的接收方式如下:

  Access-Control-Allow-Origin:*
  Content-type:multipart/x-mixed-replace; boundary=--jpgboundary
  Date:Tue, 04 Apr 2017 22:27:35 GMT
  Server:BaseHTTP/0.3 Python/2.7.9**strong text**
在客户端,我添加了相应的crossOrigin属性

<p>Image to use:</p>
<img id="stream" crossorigin="anonymous" 
src="http://192.168.1.224:8080/cam.mjpg">


<p>Canvas:</p>
<canvas id="myCanvas" width="200" height="200" style="border:1px solid 
#d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>

function updateCanvas() {
    var c = document.getElementById("myCanvas");
    var ctx2 = c.getContext("2d");
    var img = document.getElementById("stream");
    img.crossOrigin = "anonymous";
    ctx2.drawImage(img, 0, 0);
}

我看不出你的代码不起作用的任何原因。设置
img.crossOrigin
没有意义,因为您的示例中已经下载了图像

用imgur提供的图像进行尝试,效果很好。这表明问题出在您的服务器上

函数updateCanvas(){
var c=document.getElementById(“myCanvas”);
var ctx2=c.getContext(“2d”);
var img=document.getElementById(“流”);
ctx2.drawImage(img,0,0);
试一试{
const d=c.toDataURL();
日志(“画布不脏,收到CORS权限,可以在WebGL中使用”);
}捕获(e){
日志(“画布脏了,没有CORS权限,它*不能*在WebGL中使用”);
}
}
函数日志(…args){
const elem=document.createElement(“pre”);
elem.textContent=[…args].join(“\n”);
文件.正文.附件(elem);
}
document.getElementById(“流”).addEventListener('click',updateCanvas)
img,canvas{width:32px;}
p{margin:0;}
单击图像:

画布:

这是一个chrome错误:

我必须在本地主机上设置一个ffserver+mjpeg代理来确认这一点,但是, chrome不会在您的运动jpeg流请求中保留crossOrigin头…

Firefox没有这个bug,我也没有找到可靠的前端解决方案

实际上,我发现的唯一解决方法是使用代理,这对于mjpeg streams来说并不容易,但基于express js的代理确实可以很好地工作

但是,还要注意,浏览器应该只在画布上绘制mjpeg流的第一帧[],chrome在这里也有一个bug,不要依赖它,因为它可能很快就会失败,当他们修复它时


编辑 webgl的
texImage2d
在动画图像方面似乎与
drawImage
不一样

因此,对于您的情况,甚至不要穿过2D画布。您可以直接在
标记中使用mjpeg流,并将其用作更新纹理。

(尽管您仍然需要使用chrome的代理)

我不是在src之前设置crossOrigin属性吗?后来我还在代码中反复调用updateCanvas来更新下一帧。@gman,你知道
gl.texImage2D
中的动画媒体上是否与
context2d.drawImage()
一样?
texImage2D
drawImage
更严格
drawImage
可以在没有CORS许可的情况下拍摄跨域图像。这样做会将画布标记为脏的
texImage2D
未经许可,不会拍摄跨域图像。WebGL画布永远不会变脏,因为在没有CORS权限的情况下,您不能使用跨域图像。@gman,很抱歉,我在您的答案上添加了一条评论,从而分割了讨论。如果用于纹理的2d画布之前已被污染,则TexaImage2D将无法正常工作?那么这可能是OP的问题了。但我的问题是他甚至需要穿过2d画布吗?与drawImage不同,texImage2d能否处理动画图像?正确,通过画布传递跨域非CORS权限的视频将不起作用。穿过画布除了可以让你在上传到纹理之前缩放视频外,什么都不做。你可以用。虽然最近有
function init() {
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
    camera.position.z = 500;
    scene.add(camera);
    window.setTimeout("updateCanvas()", 1000); //start with a delay
    texture = new THREE.Texture(canvas);
    var material = new THREE.MeshBasicMaterial({ map: texture });
    geometry = new THREE.BoxGeometry( 200, 200, 200 );
    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );
    canvas.width = canvas.height = size;
    renderer.setClearColor(0xeeeeee, 1);
}


function animate() {
   requestAnimationFrame(animate);
   updateCanvas();
   texture.needsUpdate = true;
   mesh.rotation.y += 0.01;
   renderer.render(scene, camera);
}