我有一些常规的HTML页面(只有普通的<img />
HTML标签)。我希望获得他们的内容,最好是base64编码,而不需要重新下载图像(即它已经被浏览器加载,所以现在我想要内容)。在JavaScript中获取图像数据?
我很想用Greasemonkey和Firefox来实现这一点。
我有一些常规的HTML页面(只有普通的<img />
HTML标签)。我希望获得他们的内容,最好是base64编码,而不需要重新下载图像(即它已经被浏览器加载,所以现在我想要内容)。在JavaScript中获取图像数据?
我很想用Greasemonkey和Firefox来实现这一点。
注意:这只适用于如果图像来自与页面相同的域,或者具有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格式图像的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")
除了马修的答案,我想说image.width和图像.height返回图片的显示大小(并在绘制到画布时剪裁图片)
改为使用naturalWidth和naturalHeight,它使用实际大小的图片。
见http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#dom-img-naturalwidth
经过长时间的到来,但没有这里的答案是完全正确的。
在画布上绘制时,传递的图像是未压缩的+所有预先倍增的。
导出时,其未压缩或用不同的算法重新压缩,并且不相乘。
所有浏览器和设备在此过程中都会发生不同的舍入错误
(请参阅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">
使用取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
function encodeImageFileAsURL(cb) {
return function() {
var file = this.files[0];
var reader = new FileReader();
reader.onloadend = function() {
cb(reader.result);
}
reader.readAsDataURL(file);
}
}
$('#inputFileToLoad').change(encodeImageFileAsURL(function(base64Img) {
$('.output')
.find('textarea')
.val(base64Img)
.end()
.find('a')
.attr('href', base64Img)
.text(base64Img)
.end()
.find('img')
.attr('src', base64Img);
}));
@import url('//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css'); body{ padding: 20px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Input</h2>
<form class="input-group" id="img2b64">
<input id="inputFileToLoad" type="file" onchange="encodeImageFileAsURL();" />
</form>
<hr>
虽然这似乎是工作(除非未转义/在返回),它不会创建相同的base64字符串作为我从PHP获得的一个base64_encode用file_get_contents函数获取的文件。这些图像看起来非常相似/相同,但是它们的尺寸较小,我希望它们完全一样。 还有一件事:输入图像是一个小的(594字节),具有透明背景的28x30 PNG - 如果这改变了任何东西。 – Detariael 2009-06-01 14:22:58
另外http://www.motobit.com/util/base64-decoder-encoder.asp确认Javascript的Base64编码字符串是错误的 - 如果从原始文件创建,结果与PHP相同,不同于一个来自Javascript。 – Detariael 2009-06-01 14:32:46
Firefox可能会使用不同的压缩级别,这会影响编码。此外,我认为PNG支持一些额外的头部信息,如笔记,这些信息会丢失,因为画布只能获取像素数据。如果你需要它完全一样,你可能可以使用AJAX来获取文件,并用base64手动编码。 – 2009-06-01 15:13:37