web-dev-qa-db-fra.com

Comment corriger l'erreur getImageData () Le canevas a été corrompu par des données cross-Origin?

Mon code fonctionne très bien sur mon hôte local, mais il ne fonctionne pas sur le site.

J'ai eu cette erreur de la console, pour cette ligne .getImageData(x,y,1,1).data:

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

une partie de mon code:

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;
    }

Remarque: mon adresse URL d'image (src) provient d'une adresse URL de sous-domaine.

98
Erfan Safarpoor

Comme d'autres l'ont déjà dit, vous "souillez" la toile en la chargeant depuis un domaine d'origine croisée.

https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image

Cependant, vous pourrez peut-être éviter cela en définissant simplement:

img.crossOrigin = "Anonymous";

Cela ne fonctionne que si le serveur distant définit l'en-tête suivant de manière appropriée:

Access-Control-Allow-Origin "*"

Le sélecteur de fichier Dropbox lors de l’utilisation de l’option "lien direct" en est un excellent exemple. Je l’utilise sur oddprints.com pour passer les images de l’URL de l’image dropbox distante dans mon canevas, puis je les renvoie sur mon serveur. Tout en javascript :)

81
matt burns

J'ai constaté que je devais utiliser .setAttribute('crossOrigin', '') et que je devais ajouter un horodatage à la chaîne de requête de l'URL pour éviter qu'une réponse 304 ne contienne l'en-tête Access-Control-Allow-Origin

Cela me donne

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

Vous ne pourrez pas dessiner des images directement à partir d'un autre serveur dans un canevas, puis utiliser getImageData. C'est un problème de sécurité et la toile sera considérée comme "corrompue".

Pourriez-vous enregistrer une copie de l’image sur votre serveur à l’aide de PHP, puis charger simplement la nouvelle image? Par exemple, vous pouvez envoyer l'URL au script PHP et l'enregistrer sur votre serveur, puis renvoyer le nouveau nom de fichier en javascript comme suit:

<?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;

?>

Vous utiliseriez le script PHP avec du javascript ajax comme ceci:

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;
  }
}

Si vous utilisez getImageData sur la toile après cela, cela fonctionnera correctement. 

Sinon, si vous ne souhaitez pas enregistrer l'image entière, vous pouvez transmettre les coordonnées x & y à votre script PHP et calculer la valeur rgba du pixel de ce côté. Je pense qu'il existe de bonnes bibliothèques pour ce type de traitement d'images en PHP.

Si vous souhaitez utiliser cette approche, faites-moi savoir si vous avez besoin d'aide pour la mettre en œuvre.

17
jaya

Je voyais cette erreur sur Chrome pendant que je testais mon code localement. Je suis passé à Firefox et je ne vois plus l'erreur. Peut-être que le passage à un autre navigateur est une solution rapide.

Si vous utilisez la solution donnée en première réponse, assurez-vous d’ajouter img.crossOrigin = "Anonymous"; juste après avoir déclaré la variable img (par exemple, var img = new Image();).

2
Safwan

Vous "souillez" la toile en chargeant à partir d'un domaine d'origines croisées. Découvrez cet article MDN:

https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image

2
srquinn

Votre problème est que vous chargez une image externe, c'est-à-dire d'un autre domaine. Cela provoque une erreur de sécurité lorsque vous essayez d'accéder à des données de votre contexte de zone de dessin.

2
axelduch

Comme Matt Burns le dit dans sa réponse , vous devrez peut-être activer CORS sur le serveur où les images à problèmes sont hébergées.

Si le serveur est Apache, vous pouvez le faire en ajoutant l'extrait suivant (de ici ) à votre configuration VirtualHost ou à un fichier .htaccess:

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

... si vous l'ajoutez à un hôte virtuel, vous devrez probablement également recharger la configuration d'Apache (par exemple, Sudo service Apache2 reload si Apache s'exécute sur un serveur Linux)

0
Nick F

J'avais le même problème, et pour moi cela a fonctionné en concaténant simplement https:${image.getAttribute('src')}

0
Livia Rett

Lorsque vous travaillez sur local, ajoutez un serveur

J'ai eu un problème similaire lorsque je travaillais sur local. Votre URL sera le chemin du fichier local, par exemple. file: ///Users/PeterP/Desktop/folder/index.html.

Veuillez noter que je suis sur un MAC.

J'ai résolu ce problème en installant http-server globalement. https://www.npmjs.com/package/http-server

Pas:

  1. Installation globale: npm install http-server -g
  2. Exécuter le serveur: http-server ~/Desktop/folder/

PS: Je suppose que vous avez un noeud installé, sinon vous n’allez pas aller très loin avec les commandes npm.

0
Anas