JS在瀏覽器中解析Base64編碼圖像
上一篇介紹中,我們將二進(jìn)制文件(BLOB)保存為Base64編碼的文本,這些文本可以內(nèi)嵌在XML的標(biāo)簽中,因此二進(jìn)制信息它可以隨著XML文件被拷貝、下載而不用擔(dān)心信息會(huì)缺失。這項(xiàng)技術(shù)也在email郵件中被廣泛使用。
瀏覽器對(duì)Base64的支持
圖像是最經(jīng)常被使用的一種二進(jìn)制文件。而現(xiàn)代的瀏覽器的進(jìn)步日新月異,IE7,F(xiàn)ireFox和其他瀏覽器為包括Base64在內(nèi)各種編碼的圖像信息提供了很好的支持。因此圖形信息可以以下面的形式呈現(xiàn)在頁面中、
Java代碼
<img src="data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM///// wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4ML wWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==" alt="Base64 encoded image" width="150" height="150"/>
這種data: URI的格式能把Base64(或其他數(shù)據(jù))可以內(nèi)嵌在image標(biāo)簽的屬性當(dāng)中(或者CSS中)。我們可以看到在大部分瀏覽器中的顯示效果:

這種做法有利有弊,好處是瀏覽器可以在一個(gè)連接中得到完成的頁面內(nèi)容,不好的地方時(shí)圖像的大小會(huì)增加1/3。因此,這種內(nèi)嵌的方法適合對(duì)小的圖形元素比如圖標(biāo)、圓角等等進(jìn)行處理,從而減少瀏覽器打開的連接數(shù),但對(duì)大的照片、圖片(量少而大)等等則不應(yīng)該使用Base64編碼以免影響下載速度。
為了得到剛才的Base64編碼,我們將上一篇的Java修改成Struts Action,并借用了JIMI進(jìn)行圖形的讀取和格式轉(zhuǎn)換,Base64編碼器則改為更普遍的Apache Commons組件,代碼如下:
Java代碼
public class Base64ImageAction extends ActionSupport {
private final static String galleryName = "gallery";
private static String parent = null;
private String encodeString = null;
public String getEncodeString() {
return encodeString;
}
public void setEncodeString(String encodeString) {
this.encodeString = encodeString;
}
private String getImageFullPath() {
parent = new File(this.getClass().getClassLoader().getResource(
File.separator).getPath()).getParent()+File.separator+"flag.jpg";
}
public String execute() {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
JimiReader reader = Jimi.createJimiReader(this.getImageFullPath());
Image image = reader.getImage();
Jimi.putImage("image/png", image, output);
output.flush();
output.close();
this.encodeString = Base64.encodeBase64String(output.toByteArray());
} catch (IOException e) {
e.printStackTrace();
} catch (JimiException e) {
e.printStackTrace();
}
return SUCCESS;
}
}
對(duì)應(yīng)的View端是個(gè)十分簡(jiǎn)單的Freemarker模板:
Html代碼
<html>
<head>
<title>Hello,World</title>
</head>
<body>
<img src="data:image/png;base64,${encodeString}" />
</body>
</html>
處理古代瀏覽器
世界總是不是那么完美,盡管大部分現(xiàn)代瀏覽器對(duì)Base64的處理都十分完善,但是我們不能不考慮到一些“古老”的瀏覽器,而現(xiàn)在還是普遍使用的“古老”的瀏覽器,就當(dāng)屬IE6,在IE6里試圖瀏覽上面的圖片可能會(huì)得到一個(gè)紅叉叉。我們不得不為IE6做一些特殊處理,利用下面的JavaScript,我們把Base64字串傳回服務(wù)器端,重新解析成圖片
Javascript代碼
// a regular expression to test for Base64 data
var BASE64_DATA = /^data:.*;base64/i;
// path to the PHP module that will decode the encoded data
var base64Path = "/my/path/base64.php";
function fixBase64(img) {
// check the image source
if (BASE64_DATA.test(img.src)) {
// pass the data to the PHP routine
img.src = base64Path + "?" + img.src.slice(5);
}
};
// fix images on page load
onload = function() {
for (var i = 0; i < document.images.length; i++) {
fixBase64(document.images[i]);
}
};
服務(wù)器端的Struts可以參考上面的例子做反向操作,具體從略。
更完美的方法
將Base64傳回服務(wù)器解碼是不錯(cuò)的IE6補(bǔ)丁,但是違背了我們的初衷,對(duì)IE6來說,瀏覽器連接數(shù)并未有任何減少。更直接的想法,是否能用Javascript直接在瀏覽器中,對(duì)Base64文本進(jìn)行解碼呢?我們構(gòu)思的場(chǎng)景如下:服務(wù)器端先將圖片轉(zhuǎn)換成PNG格式以方便客戶端進(jìn)行處理,Base64編碼之后,利用JSON將文本傳遞給瀏覽器客戶端進(jìn)行處理。
我們選擇PNG圖形格式是因?yàn)镻NG已經(jīng)儼然成為新的Web圖形標(biāo)準(zhǔn),它格式非常簡(jiǎn)單,可以很方便的用javascript進(jìn)行處理而不需要借助瀏覽器的支持。我們知道javascript直接不能處理二進(jìn)制數(shù)據(jù),但是現(xiàn)在這不是個(gè)問題,服務(wù)器端已經(jīng)準(zhǔn)備好了Base64編碼的文本數(shù)據(jù),現(xiàn)在我們只需要一個(gè)javascript的Base64解析器,你可以在這里找到一個(gè)notmasteryet的Base64解析器。
現(xiàn)在PNG圖形格式采用了DEFLATE作為唯一的壓縮算法,該算法也廣泛應(yīng)用在ZIP,GZIP等壓縮格式中。PNG圖像格式文件(或者稱為數(shù)據(jù)流)由一個(gè)8字節(jié)的PNG文件署名(PNG file signature)域和按照特定結(jié)構(gòu)組織的3個(gè)以上的數(shù)據(jù)塊(chunk)組成。
PNG定義了兩種類型的數(shù)據(jù)塊,一種是稱為關(guān)鍵數(shù)據(jù)塊(critical chunk),這是標(biāo)準(zhǔn)的數(shù)據(jù)塊,另一種叫做輔助數(shù)據(jù)塊(ancillary chunks),這是可選的數(shù)據(jù)塊。關(guān)鍵數(shù)據(jù)塊定義了4個(gè)標(biāo)準(zhǔn)數(shù)據(jù)塊,其中圖像數(shù)據(jù)塊IDAT(image data chunk):它存儲(chǔ)實(shí)際的數(shù)據(jù), PNG總的數(shù)據(jù)流采用DEFLAT進(jìn)行壓縮。此外還擦用三角過濾“delta filters”來過濾每一行的像素的未壓縮數(shù)據(jù)。DEFLAT和delta壓縮在其他數(shù)據(jù)和文本處理中也被廣泛應(yīng)用。PNG格式你可以參考<a href="http://www.libpng.org/pub/png/spec/1.1/PNG-Contents.html">官方文檔</a>。
很棒的,notmasteryet也為我們提供了一個(gè)DEFLAT解壓器。
最后,我們把這些組合起來:
Html代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Demo JavaScript PNG Viewer</title>
</head>
<body onload="show(gravatar);">
<script src="../Source/Base64.js" type="text/javascript"></script>
<script src="../Source/Deflate.js" type="text/javascript"></script>
<script src="../Source/PNG.js" type="text/javascript"></script>
<script type="text/javascript">
var gravatar = 'iVBORw0KGgoAAAANSUhEUgAAA.......數(shù)據(jù)從略......55CYII=';
String.prototype.padRight = function(c, n){
var txt = '';
for(var i=0;i<n-this.length;i++) txt += c;
return txt + this;
};
function show(data){
var png = new PNG(data);
var img = document.getElementById('image'), limg = document.getElementById('largeimage');
document.getElementById('nativeimage').src = 'data:image/png;base64,' + data;
img.innerHTML = '';
limg.innerHTML = '';
img.style.width = png.width + 'px';
img.style.height = png.height + 'px';
limg.style.width = (png.width * 3) + 'px';
limg.style.width = (png.height * 3) + 'px';
var line;
while(line = png.readLine())
{
for (var x = 0; x < line.length; x++){
var px = document.createElement('div'), px2 = document.createElement('div');
px.className = px2.className = 'pixel';
px.style.backgroundColor = px2.style.backgroundColor = '#' + line[x].toString(16).padRight('0', 6);
img.appendChild(px);
limg.appendChild(px2);
}
}
}
</script>
<div id="image"></div>
<div id="largeimage"></div>
<img id="nativeimage" />
</body>
</html>
以上所述是小編給大家介紹的JS在瀏覽器中解析Base64編碼圖像,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
three.js中3D視野的縮放實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了three.js中3D視野的縮放實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
淺析對(duì)JS中方法unshift和push方法的理解
JavaScript中的`unshift`和`push`方法用于在數(shù)組的開始和結(jié)尾添加元素,它們會(huì)直接修改原數(shù)組并返回新的數(shù)組長(zhǎng)度,本文介紹JS中方法unshift和push方法的相關(guān)知識(shí),感興趣的朋友一起看看吧2024-12-12
js下為表格內(nèi)部動(dòng)態(tài)添加行的代碼
最近的一個(gè)項(xiàng)目中在保存表單數(shù)據(jù)時(shí),要用到一個(gè)動(dòng)態(tài)添加行的功能。平時(shí)動(dòng)態(tài)添加行只是在表格的最下面添加,現(xiàn)在在表格中間動(dòng)態(tài)添加行,而且表格內(nèi)部是包含并且單元格的,其實(shí)很簡(jiǎn)單,下面貼出代碼。2010-06-06
javascript仿php的print_r函數(shù)輸出json數(shù)據(jù)
輸出json數(shù)據(jù),php的print_r函數(shù)可以輕松實(shí)現(xiàn),下面為大家介紹下javascript也可以模仿print_r函數(shù)輸出json數(shù)據(jù),具體實(shí)現(xiàn)如下,感興趣的朋友可以了解下2013-09-09
js實(shí)現(xiàn)String.Fomat的實(shí)例代碼
下面小編就為大家?guī)硪黄猨s實(shí)現(xiàn)String.Fomat的實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09

