いくつかの画像を含む通常のHTMLページがあります(通常の<img />
HTMLタグのみ)。画像を再ダウンロードせずに、できればbase64でエンコードされたコンテンツを取得したい(つまり、ブラウザによって既に読み込まれているので、コンテンツが必要になります)。
私はGreasemonkeyとFirefoxでそれを達成したいと思っています。
いくつかの画像を含む通常のHTMLページがあります(通常の<img />
HTMLタグのみ)。画像を再ダウンロードせずに、できればbase64でエンコードされたコンテンツを取得したい(つまり、ブラウザによって既に読み込まれているので、コンテンツが必要になります)。
私はGreasemonkeyとFirefoxでそれを達成したいと思っています。
注:これは、画像がページと同じドメインからのものであるか、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」になります。
この関数は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")
ずっと後になりますが、ここでの答えはどれも完全に正しいものではありません。
キャンバスに描画すると、渡された画像は非圧縮+すべて事前に乗算されます。
エクスポートされると、圧縮されていないか、別のアルゴリズムで再圧縮され、乗算されません。
すべてのブラウザとデバイスで、このプロセスで発生するさまざまな丸め誤差が発生します
(キャンバスフィンガープリンティングを参照)。
したがって、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">
フェッチを使用した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
画像がすでに読み込まれている(または読み込まれていない)場合は、次の「ツール」が便利です。
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-type
、MDN仕様でquality
説明されているように、これらの引数/パラメーターを省略できます。
このJSを(必要になる前に)ロードしている場合、への変換dataURL
は次のように簡単です。
HTML
<img src="/yo.jpg" onload="console.log(this.toDataURL('image/jpeg'))">
JS
console.log(document.getElementById("someImgID").toDataURL());
ビットの「正確さ」が気になる場合は、@ Kaiidoの回答で提供されているように、ニーズに合わせてこのツールを変更できます。
読み込み後にイベントを使用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>
これはあなたが読む必要があるすべてです。
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);
});
HTML5では、これをより適切に使用します。
{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}