2009-06-01 88 views
291

我有一些常规的HTML页面(只有普通的<img /> HTML标签)。我希望获得他们的内容,最好是base64编码,而不需要重新下载图像(即它已经被浏览器加载,所以现在我想要内容)。在JavaScript中获取图像数据?

我很想用Greasemonkey和Firefox来实现这一点。

回答

374

注意:这只适用于如果图像来自与页面相同的域,或者具有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”。

+1

虽然这似乎是工作(除非未转义/在返回),它不会创建相同的base64字符串作为我从PHP获得的一个base64_encode用file_get_contents函数获取的文件。这些图像看起来非常相似/相同,但是它们的尺寸较小,我希望它们完全一样。 还有一件事:输入图像是一个小的(594字节),具有透明背景的28x30 PNG - 如果这改变了任何东西。 – Detariael 2009-06-01 14:22:58

+0

另外http://www.motobit.com/util/base64-decoder-encoder.asp确认Javascript的Base64编码字符串是错误的 - 如果从原始文件创建,结果与PHP相同,不同于一个来自Javascript。 – Detariael 2009-06-01 14:32:46

+7

Firefox可能会使用不同的压缩级别,这会影响编码。此外,我认为PNG支持一些额外的头部信息,如笔记,这些信息会丢失,因为画布只能获取像素数据。如果你需要它完全一样,你可能可以使用AJAX来获取文件,并用base64手动编码。 – 2009-06-01 15:13:37

66

该函数将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")

24

经过长时间的到来,但没有这里的答案是完全正确的。

在画布上绘制时,传递的图像是未压缩的+所有预先倍增的。
导出时,其未压缩或用不同的算法重新压缩,并且不相乘。

所有浏览器和设备在此过程中都会发生不同的舍入错误
(请参阅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">

0

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>
这里是工作小提琴示例: - upload & get Image Data