web-dev-qa-db-ja.com

JavaScriptで画像データのURLを取得しますか?

私はいくつかの画像を含む通常のHTMLページを持っています(通常の<img /> HTMLタグだけ)。私は彼らのコンテンツを、base64でエンコードして、画像を再ダウンロードする必要なしに取得したいのです(つまり、すでにブラウザによってロードされているので、今度はコンテンツが欲しいです)。

GreasemonkeyとFirefoxでそれを実現したいです。

319
Detariael

注:これは、画像がページと同じドメインのものであるか、crossOrigin="anonymous"属性を持ち、サーバーがCORSをサポートしている場合にのみ機能します。元のファイルではなく、再エンコードされたものもあります。元の結果と同じ結果が必要な場合は、 Kaiidoの答え を参照してください。


正しいサイズのキャンバス要素を作成し、drawImage関数を使用して画像データをコピーする必要があります。その後、toDataURL関数を使用して、base-64でエンコードされたイメージを持つdata:urlを取得できます。画像は完全にロードされている必要があります。そうしないと、空の(黒の、透明な)画像が返されるだけです。

それはこのようなものでしょう。私はGreasemonkeyスクリプトを書いたことがないので、その環境で実行するようにコードを調整する必要があるかもしれません。

function getBase64Image(img) {
    // Create an empty canvas element
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    // Copy the image contents to the canvas
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    // Get the data-URL formatted image
    // Firefox supports PNG and JPEG. You could check img.src to
    // guess the original format, but be aware the using "image/jpg"
    // will re-encode the image.
    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

JPEG形式の画像を取得するのは、Firefoxの古いバージョン(3.5前後)では機能しません。そのため、それをサポートしたい場合は、互換性を確認する必要があります。エンコーディングがサポートされていない場合は、デフォルトの "image/png"になります。

389
Matthew Crumley

この関数はURLを取得してから画像BASE64を返します。

function getBase64FromImageUrl(url) {
    var img = new Image();

    img.setAttribute('crossOrigin', 'anonymous');

    img.onload = function () {
        var canvas = document.createElement("canvas");
        canvas.width =this.width;
        canvas.height =this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");

        alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
    };

    img.src = url;
}

これを次のように呼び出します。getBase64FromImageUrl("images/slbltxt.png")

71
MuniR

ずっと後になるが、ここでの答えのどれも完全に正しいというわけではない。

キャンバスに描画されると、渡された画像は圧縮されていない+すべての事前乗算されています。
エクスポートされると、圧縮解除されるか、異なるアルゴリズムで再圧縮され、乗算されません。

このプロセスでは、すべてのブラウザとデバイスで丸め誤差が異なります。
キャンバス指紋採取 を参照)。

そのため、base64バージョンのイメージファイルが必要な場合は、もう一度リクエストする必要があります(ほとんどの場合、キャッシュから取得されます)が、今回はBlobとして処理されます。

それから、 FileReader を使用して、ArrayBufferまたはdataURLとして読み取ることができます。

function toDataURL(url, callback){
    var xhr = new XMLHttpRequest();
    xhr.open('get', url);
    xhr.responseType = 'blob';
    xhr.onload = function(){
      var fr = new FileReader();
    
      fr.onload = function(){
        callback(this.result);
      };
    
      fr.readAsDataURL(xhr.response); // async call
    };
    
    xhr.send();
}

toDataURL(myImage.src, function(dataURL){
  result.src = dataURL;

  // now just to show that passing to a canvas doesn't hold the same results
  var canvas = document.createElement('canvas');
  canvas.width = myImage.naturalWidth;
  canvas.height = myImage.naturalHeight;
  canvas.getContext('2d').drawImage(myImage, 0,0);

  console.log(canvas.toDataURL() === dataURL); // false - not same data
  });
<img id="myImage" src="https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png" crossOrigin="anonymous">
<img id="result">
42
Kaiido

マシューの答えに加えて、私はimage.widthとimage.heightが絵の表示サイズを返す(そしてそれをキャンバスに描画するときに画像をトリミングする)と言いたいです。

実際のサイズの画像を使用する代わりに、naturalWidthとnaturalHeightを使用してください。

http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#dom-img-naturalwidth を参照してください。

23
cube45

Fetchを使ったkaiidoの答えをもっと現代的なものにすると:

function toDataURL(url) {
  return fetch(url)
      .then((response)=> {
        return response.blob();
      })
      .then(blob=> {
        return URL.createObjectURL(blob);
      });
}

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

15
Zaptree

ロード後にonloadイベントを使用して画像を変換する

function loaded(img) {
  let c = document.createElement('canvas')
  c.getContext('2d').drawImage(img, 0, 0)
  msg.innerText= c.toDataURL();
}
pre { Word-wrap: break-Word; width: 500px; white-space: pre-wrap; }
<img onload="loaded(this)" src="https://cors-anywhere.herokuapp.com/http://lorempixel.com/200/140" crossorigin="anonymous"/>

<pre id="msg"></pre>
1

HTML 5ではこれを使用してください。

{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
0
KepHec