web-dev-qa-db-ja.com

getImageData()エラーを修正する方法キャンバスがクロスオリジンデータによって汚染されていますか?

私のコードはローカルホストでは非常にうまく機能していますが、サイトでは機能していません。

コンソールからこのエラーが発生しました。この行.getImageData(x,y,1,1).data

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

私のコードの一部:

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

注:画像のURL(src)はサブドメインのURLからのものです

104
Erfan Safarpoor

他の人が言ったように、クロスオリジンドメインからロードすることでキャンバスを「汚染」しています。

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

ただし、以下を設定するだけでこれを防止できる場合があります。

img.crossOrigin = "Anonymous";

これは、リモートサーバーが次のヘッダーを適切に設定した場合にのみ機能します。

Access-Control-Allow-Origin "*"

「ダイレクトリンク」オプションを使用する場合の Dropboxファイル選択 は、この良い例です。 oddprints.com で使用して、リモートドロップボックスの画像URLから画像をキャンバスに移動し、画像データをサーバーに送信します。すべてJavaScriptで

85
matt burns

.setAttribute('crossOrigin', '')を使用し、Access-Control-Allow-Originヘッダーのない304応答を回避するために、URLのクエリ文字列にタイムスタンプを追加する必要があることがわかりました。

これは私に与えます

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

別のサーバーからキャンバスに画像を直接描画してからgetImageDataを使用することはできません。これはセキュリティの問題であり、キャンバスは「汚染された」と見なされます。

PHPを使用して画像のコピーをサーバーに保存し、新しい画像をロードするだけで機能しますか?たとえば、URLをPHPスクリプトに送信してサーバーに保存し、次のように新しいファイル名をjavascriptに返すことができます。

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

?>

PHPスクリプトを次のようなajax javascriptで使用します。

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

その後、キャンバスでgetImageDataを使用すると、正常に機能します。

あるいは、画像全体を保存したくない場合は、xおよびy座標をPHPスクリプトに渡し、その側のピクセルのrgba値を計算できます。 PHPでそのような画像処理を行うための優れたライブラリがあると思います。

このアプローチを使用する場合は、実装の支援が必要かどうかをお知らせください。

編集:覗き見は、PHPスクリプトが公開され、インターネットが潜在的に悪用する可能性があることを指摘しました。これを処理するための無数の方法があります。最も単純な方法の1つは、ある種のURLの難読化です...

17
jaya

コードをローカルでテストしているときに、Chromeでこのエラーが発生していました。 Firefoxに切り替えましたが、エラーは表示されなくなりました。別のブラウザに切り替えるのは簡単な修正かもしれません。

最初の回答で与えられたソリューションを使用している場合は、img変数を宣言した直後にimg.crossOrigin = "Anonymous";を追加してください(たとえば、var img = new Image();)。

2
Safwan

クロスオリジンドメインからロードすることにより、キャンバスを「汚染」しています。このMDN記事をご覧ください。

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

2
srquinn

問題は、別のドメインからの外部イメージをロードすることです。これにより、キャンバスコンテキストのデータにアクセスしようとすると、セキュリティエラーが発生します。

2
axelduch

Matt burnsが his answer で述べているように、問題の画像がホストされているサーバーでCORSを有効にする必要がある場合があります。

サーバーがApacheの場合、VirtualHost構成または.htaccessファイルに次のスニペット( here から)を追加することでこれを実行できます。

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

... VirtualHostに追加する場合、おそらくApacheの設定も再読み込みする必要があります(たとえば、ApacheがLinuxサーバーで実行されている場合はSudo service Apache2 reload

0
Nick F

私は同じ問題を抱えていましたが、私にとってはhttps:${image.getAttribute('src')}を連結するだけで機能しました

0
Livia Rett

ローカルで作業する場合、サーバーを追加します

ローカルで作業しているときに、同様の問題がありました。あなたのURLはローカルファイルへのパスになります。 file:///Users/PeterP/Desktop/folder/index.html。

私はMACにいることに注意してください。

Http-serverをグローバルにインストールすることでこれを回避しました。 https://www.npmjs.com/package/http-server

手順:

  1. グローバルインストール:npm install http-server -g
  2. サーバーの実行:http-server ~/Desktop/folder/

PS:ノードがインストールされていると思いますが、そうでなければ、npmコマンドをあまり実行しません。

0
Anas