【发布时间】:2010-10-30 08:37:49
【问题描述】:
我有一个带有一些图像的常规 HTML 页面(只是常规的<img /> HTML 标签)。我想获取他们的内容,最好是 base64 编码,而不需要重新下载图像(即它已经被浏览器加载,所以现在我想要内容)。
我很想用 Greasemonkey 和 Firefox 来实现。
【问题讨论】:
标签: javascript image firefox greasemonkey base64
我有一个带有一些图像的常规 HTML 页面(只是常规的<img /> HTML 标签)。我想获取他们的内容,最好是 base64 编码,而不需要重新下载图像(即它已经被浏览器加载,所以现在我想要内容)。
我很想用 Greasemonkey 和 Firefox 来实现。
【问题讨论】:
标签: javascript image firefox greasemonkey base64
这就是你需要阅读的全部内容。
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);
});
【讨论】:
使用 fetch 的 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
编辑:正如 cmets 中所指出的,这将返回一个指向本地系统中文件的对象 url,而不是实际的 DataURL,因此根据您的用例,这可能不是您所需要的。
您可以查看以下答案以使用 fetch 和实际的 dataURL:https://stackoverflow.com/a/50463054/599602
【讨论】:
URL.revokeObjectURL(),否则您的内存会变得混乱。
如果您的图片已经加载(或未加载),这个“工具”可能会派上用场:
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 和 quality -或者-您可以省略这些参数/参数,如 中所述MDN 规范here.
如果您已经加载了这个 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>
【讨论】:
在 HTML5 中最好使用这个:
{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
【讨论】:
很久以后,但这里没有一个答案是完全正确的。
在画布上绘制时,传递的图像是未压缩的 + 全部是预乘的。
导出时,其未压缩或使用不同的算法重新压缩,并且未相乘。
所有浏览器和设备在此过程中都会发生不同的舍入错误
(见Canvas fingerprinting)。
因此,如果想要一个图像文件的 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">
【讨论】:
XMLHttpRequest cannot load data:image/jpeg;base64,/9j/4AA ... /2Q==. Invalid response. Origin 'https://example.com' is therefore not allowed access.
注意:这仅适用于图片来自与页面相同的域,或者具有crossOrigin="anonymous" 属性并且服务器支持 CORS。它也不会给你原始文件,而是一个重新编码的版本。如果您需要结果与原始结果相同,请参阅Kaiido's answer。
您将需要创建具有正确尺寸的画布元素并使用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 格式的图像不适用于旧版本(大约 3.5)的 Firefox,因此如果您想支持它,您需要检查兼容性。如果不支持编码,则默认为“image/png”。
【讨论】:
drawImage 什么都不做,你最终会得到一个空白画布和生成的图像。
此函数获取 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")
【讨论】:
img.src =放在img.onload =之后,因为在某些浏览器中,比如Opera,这个事件不会发生。
getBase64FromImageUrl(url) 和img.onload = function () 的函数范围,img 将无法访问并被垃圾收集。除了 IE 6/7,这没关系。