358

いくつかの画像を含む通常のHTMLページがあります(通常の<img />HTMLタグのみ)。画像を再ダウンロードせずに、できればbase64でエンコードされたコンテンツを取得したい(つまり、ブラウザによって既に読み込まれているので、コンテンツが必要になります)。

私はGreasemonkeyとFirefoxでそれを達成したいと思っています。

4

8 に答える 8

418

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


正しいサイズのキャンバス要素を作成し、drawImage関数を使用して画像データをコピーする必要があります。次に、この関数を使用toDataURLして、base-64でエンコードされた画像を含むデータ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」になります。

于 2009-06-01T13:55:36.980 に答える
83

この関数は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")

于 2013-05-15T13:21:47.453 に答える
73

ずっと後になりますが、ここでの答えはどれも完全に正しいものではありません。

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

すべてのブラウザとデバイスで、このプロセスで発生するさまざまな丸め誤差が発生します
キャンバスフィンガープリンティングを参照)。

したがって、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">

于 2017-03-21T01:16:09.560 に答える
25

フェッチを使用したkaiidoの答えのより現代的なバージョンは次のようになります。

function toObjectUrl(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

編集:コメントで指摘されているように、これは実際のDataURLではなくローカルシステム内のファイルを指すオブジェクトURLを返すため、ユースケースによってはこれが必要でない場合があります。

フェッチと実際のdataURLを使用するには、次の回答をご覧ください:https ://stackoverflow.com/a/50463054/599602

于 2017-07-21T21:36:06.540 に答える
5

シブ/シム/シャム

画像がすでに読み込まれている(または読み込まれていない)場合は、次の「ツール」が便利です。

Object.defineProperty
(
    HTMLImageElement.prototype,'toDataURL',
    {enumerable:false,configurable:false,writable:false,value:function(m,q)
    {
        let c=document.createElement('canvas');
        c.width=this.naturalWidth; c.height=this.naturalHeight;
        c.getContext('2d').drawImage(this,0,0); return c.toDataURL(m,q);
    }}
);

.. しかし、なぜ?

これには、「ロード済み」の画像データを使用できるという利点があるため、追加のリクエストは必要ありません。さらに、エンドユーザー(あなたのようなプログラマー)がCORSを決定できるようにします。またmime-typeMDN仕様でquality説明されているように、これらの引数/パラメーターを省略できます

このJSを(必要になる前に)ロードしている場合、への変換dataURLは次のように簡単です。

HTML
<img src="/yo.jpg" onload="console.log(this.toDataURL('image/jpeg'))">
JS
console.log(document.getElementById("someImgID").toDataURL());

GPUフィンガープリント

ビットの「正確さ」が気になる場合は、@ Kaiidoの回答で提供されているように、ニーズに合わせてこのツールを変更できます。

于 2019-11-01T01:23:58.913 に答える
1

読み込み後にイベントを使用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>

于 2019-04-24T08:03:38.567 に答える
0

これはあなたが読む必要があるすべてです。

https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString

var height = 200;
var width  = 200;

canvas.width  = width;
canvas.height = height;

var ctx = canvas.getContext('2d');

ctx.strokeStyle = '#090';
ctx.beginPath();
ctx.arc(width/2, height/2, width/2 - width/10, 0, Math.PI*2);
ctx.stroke();

canvas.toBlob(function (blob) {
  //consider blob is your file object

  var reader = new FileReader();

  reader.onload = function () {
    console.log(reader.result);
  }

  reader.readAsBinaryString(blob);
});
于 2020-07-16T18:01:34.443 に答える
-1

HTML5では、これをより適切に使用します。

{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
于 2019-01-12T10:18:20.610 に答える