Como corrigir o erro getImageData () A canvas foi corrompida por dados de origem cruzada?

Meu código está funcionando muito bem no meu localhost, mas não está funcionando no site.

Eu recebi este erro do console, para esta linha .getImageData(x,y,1,1).data :

 Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 

parte do meu código:

 jQuery.Event.prototype.rgb=function(){ var x = this.offsetX || (this.pageX - $(this.target).offset().left),y = this.offsetY || (this.pageY - $(this.target).offset().top); if (this.target.nodeName!=="CANVAS")return null; return this.target.getContext('2d').getImageData(x,y,1,1).data; } 

Observação: meu URL de imagem (src) é de um URL de subdomínio

   

Como outros já disseram, você está “manchando” a canvas carregando de um domínio de origens cruzadas.

https://developer.mozilla.org/pt-BR/docs/HTML/CORS_Enabled_Image

No entanto, você pode evitar isso simplesmente configurando:

 img.crossOrigin = "Anonymous"; 

Isso só funciona se o servidor remoto definir o seguinte header de forma adequada:

 Access-Control-Allow-Origin "*" 

O seletor de arquivos do Dropbox ao usar a opção “link direto” é um ótimo exemplo disso. Eu uso-o em oddprints.com para aspirar as imagens da url da imagem da checkbox de depósito remota, para a minha canvas e, em seguida, enviar os dados da imagem de volta para o meu servidor. Tudo em javascript 🙂

Eu achei que tinha que usar .setAttribute('crossOrigin', '') e tinha que acrescentar um timestamp à string de consulta da URL para evitar uma resposta 304 sem o header Access-Control-Allow-Origin .

Isso me dá

 var url = 'http://lorempixel.com/g/400/200/'; var imgObj = new Image(); imgObj.src = url + '?' + new Date().getTime(); imgObj.setAttribute('crossOrigin', ''); 

Você não poderá desenhar imagens diretamente de outro servidor em uma canvas e, em seguida, usar getImageData . É um problema de segurança e a canvas será considerada “contaminada”.

Funcionaria para você salvar uma cópia da imagem em seu servidor usando PHP e depois carregar a nova imagem? Por exemplo, você poderia enviar o URL para o script PHP e salvá-lo no seu servidor e, em seguida, retornar o novo nome de arquivo para o seu javascript da seguinte forma:

 < ?php //The name of this file in this example is imgdata.php $url=$_GET['url']; $img = file_get_contents($url); $fn = substr(strrchr($url, "/"), 1); file_put_contents($fn,$img); echo $fn; ?> 

Você usaria o script PHP com algum javascript ajax como este:

 xi=new XMLHttpRequest(); xi.open("GET","imgdata.php?url="+yourImageURL,true); xi.send(); xi.onreadystatechange=function() { if(xi.readyState==4 && xi.status==200) { img=new Image; img.onload=function(){ ctx.drawImage(img, 0, 0, canvas.width, canvas.height); } img.src=xi.responseText; } } 

Se você usar getImageData na canvas depois disso, funcionará bem.

Alternativamente, se você não quiser salvar a imagem inteira, você poderia passar coordenadas x e y para seu script PHP e calcular o valor rgba do pixel naquele lado. Eu acho que existem boas bibliotecas para fazer esse tipo de image processing no PHP.

Se você quiser usar essa abordagem, me avise se precisar de ajuda para implementá-la.

Seu problema é que você carrega uma imagem externa, ou seja, de outro domínio. Isso causa um erro de segurança quando você tenta acessar os dados do contexto da canvas.

Você está “manchando” a canvas carregando de um domínio de origens cruzadas. Confira este artigo do MDN:

https://developer.mozilla.org/pt-BR/docs/HTML/CORS_Enabled_Image

Como Matt Burns diz em sua resposta , você pode precisar ativar o CORS no servidor onde as imagens do problema estão hospedadas.

Se o servidor for Apache, isso pode ser feito adicionando o seguinte snippet ( daqui ) a sua configuração do VirtualHost ou a um arquivo .htaccess :

    SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=IS_CORS    

… se for adicioná-lo a um VirtualHost, provavelmente será necessário recarregar a configuração do Apache também (por exemplo, sudo service apache2 reload se o Apache estiver sendo executado em um servidor Linux)

Eu encontro o mesmo problema hoje e resolvo isto pelo código segue.

Código HTML:

 
broswer don't support canvas

código js:

 var canvas = document.getElementById('iak') var iakImg = document.getElementById('img') var ctx = canvas.getContext('2d') var image = new Image() image.src=iakImg.src image.onload = function () { ctx.drawImage(image,0,0) var data = ctx.getImageData(0,0,600,400) } 

código como acima, e não há problema de domínio cruzado.