js对图片base64编码字符串进行解码并输出图像示例

2014-03-17 20 whsnow

<!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> 

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 

<style> 

body{padding-left:75px;background-color:beige} 

</style> 

<script> 

/////////////////////////// 

//base64编码的GIF图像解码 

//By Mozart0 

//2005/10/29 

//////////////////// 
//建立GIF类的对象 

//类GIF在此函数内部定义 

//str64:gif文件的Base64编码字符串 

//成功返回创建的GIF对象 

//失败返回null 

function getGif(str64){ 

var bytes=decodeBase64(str64); 

if(!bytes){ 

alert("错误:无效的Base64编码"); 

return null; 

} 

var gif=new GIF(); 

for(var i=0;i<6;i++) 

gif.version+=String.fromCharCode(bytes[i]); 

if(gif.version.slice(0,3)!="GIF"){ 

alert("错误:非Gif图像格式"); 

return null; 

} 

gif.width=bytes[i]|(bytes[i+1]<<8); 

gif.height=bytes[i+2]|(bytes[i+3]<<8); 

var f=bytes[i+4]; 

gif.colorResolution=(f>>4&0x7)+1; 

gif.sorted=(f&0x8)?true:false; 

gif.backgroundIndex=bytes[i+5]; 

gif.pixelAspectRadio=bytes[i+6]; 

if(f&0x80){ 

gif.globalPalette=[]; 

i+=getPalette(i+7,bytes,gif.globalPalette,2<<(f&0x7)); 

} 

i+=7; 

for(var j=i;j<bytes.length;j++) 

if(bytes[j]==0x21&&bytes[j+1]==0xf9) 

break; 

if(j==bytes.length){ 

for(;i<bytes.length;i++) 

if(bytes[i]==0x2c) 

break; 

if(i==bytes.length){ 

alert("错误:找不到图像数据"); 

return null; 

} 

var f=new GIF_Frame(); 

if(!getSingleFrame(i,f)) 

return null; 

else 

gif.frames.push(f); 

} 

else{ 

i=j; 

do{ 

var f=new GIF_Frame(); 

var t=getSingleFrame(i,f); 

if(!t) 

return null; 

gif.frames.push(f); 

for(i+=t;i<bytes.length;i++) 

if(bytes[i]==0x21&&bytes[i+1]==0xf9) 

break; 

} 

while(i<bytes.length); 

} 

return gif; 

//内部过程,生成色表 

function getPalette(pos,s,d,len){ 

len*=3; 

for(var i=pos;i<pos+len;i+=3) 

d.push('#'+(s[i]<=0xf?"0":"")+s[i].toString(16) 

+(s[i+1]<=0xf?"0":"")+s[i+1].toString(16) 

+(s[i+2]<=0xf?"0":"")+s[i+2].toString(16)); 

return len; 

} 

//内部过程,整合数据段 

function getBlock(pos,s,d){ 

var p=pos; 

while(len=s[p++]){ 

for(var i=0;i<len;i++) 

d.push(s[p+i]); 

p+=len; 

} 

return p-pos; 

} 

//内部过程,获取一帧数据 

function getSingleFrame(pos,frame){ 

var i=pos; 

if(bytes[i]==0x21){ 

i+=3; 

if(bytes[i]&1) 

frame.transparentIndex=bytes[i+3]; 

frame.delay=bytes[i+1]|(bytes[i+2]<<8); 

for(i+=5;i<bytes.length&&bytes[i]!=0x2c;i++); 

if(i==bytes.length){ 

alert("错误:找不到图像标志符"); 

return 0; 

} 

} 

frame.offsetX=bytes[i+1]|(bytes[i+2]<<8); 

frame.offsetY=bytes[i+3]|(bytes[i+4]<<8); 

frame.width=bytes[i+5]|(bytes[i+6]<<8); 

frame.height=bytes[i+7]|(bytes[i+8]<<8); 

var f=bytes[i+9]; 

i+=10; 

if(f&0x40) 

frame.interlace=true; 

if(f&0x20) 

frame.sorted=true; 

if(f&0x80){ 

frame.colorResolution=(f&0x7)+1; 

frame.localPalette=[]; 

i+=getPalette(i,bytes,frame.localPalette,1<<frame.colorResolution); 

} 

else{ 

frame.colorResolution=gif.colorResolution; 

frame.localPalette=gif.globalPalette; 

} 

var lzwLen=bytes[i++]+1; 

i+=getBlock(i,bytes,frame.data); 

frame.data=decodeLzw(frame.data,lzwLen); 

return frame.data?i-pos:0; 

} 

//定义存储GIF文件的数据结构 

//提供方法showInfo,返回图片信息 

function GIF(){ 

this.version=""; //版本号 

this.width=0; //逻辑屏幕宽度 

this.height=0; //逻辑屏幕高度 

this.colorResolution=0; //颜色深度 

this.sorted=false; //全局色表分类标志 

this.globalPalette=null; //全局色表 

this.backgroundIndex=-1; //背景色索引 

this.pixelAspectRadio=0; //像素宽高比 

this.frames=[]; //图像各帧,见GIF_Frame 

this.showInfo=function(sep){ //显示图片信息,sep为行分隔符 

if(!sep) 

sep="\n"; 

var s="Gif infomation:"+sep+"-------------------"; 

s+=subInfo(this)+sep; 

for(var i=0;i<this.frames.length;i++) 

s+=sep+"frames "+i+"----------"+subInfo(this.frames[i]); 

return s; 

function subInfo(o){ 

var s=""; 

for(var i in o){ 

if(i=="showInfo"||i=="draw") 

continue; 

s+=sep+i+":"; 

if(typeof(o[i])=="object") 

s+=(o[i]?o[i].length:"null"); 

else 

s+=o[i]; 

} 

return s; 

} 

} 

} 

//定义存储一帧图象的数据结构 

//提供方法draw,绘图 

function GIF_Frame(){ 

this.offsetX=0; //X方向偏移量 

this.offsetY=0; //Y方向偏移量 

this.width=0; //图象宽度 

this.height=0; //图象高度 

this.localPalette=null; //局部色表 

this.colorResolution=0; //颜色深度 

this.interlace=false; //交错标志 

this.sorted=false; //局部色表分类标志 

this.data=[]; //图像数据,存储各像素颜色的整数索引 

this.transparentIndex=-1; //透明色索引 

this.delay=0; //帧延时 

this.draw=function(parent,zoom){ 

if(!this.data.length) 

return; 

if(!parent) 

parent=document.body; 

if(!zoom) 

zoom=1; 

if(parent.clientWidth<this.width*zoom) 

parent.style.width=this.width*zoom; 

if(parent.clientHeight<this.height*zoom) 

parent.style.height=this.height*zoom; 

var id="ImgDefaultDraw"; 

var img=document.getElementById(id); 

if(img) 

delete parent.removeChild(img); 

img=document.createElement("DIV"); 

img.id=id; 

parent.appendChild(img); 

img.style.position="absolute"; 

var t=document.createElement("DIV"); 

t.style.overflow="hidden"; 

t.style.position="absolute"; 

defLayout(this.data,this.localPalette,this.width,this.height,img,t,zoom); 

delete t; 

} 

} 

} 

//Base64解码 

//strIn,输入字符串 

//成功返回一个数组,每一个元素包含一字节信息 

//失败返回null 

function decodeBase64(strIn){ 

if(!strIn.length||strIn.length%4) 

return null; 

var str64= 

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 

var index64=[]; 

for(var i=0;i<str64.length;i++) 

index64[str64.charAt(i)]=i; 

var c0,c1,c2,c3,b0,b1,b2; 

var len=strIn.length; 

var len1=len; 

if(strIn.charAt(len-1)=='=') 

len1-=4; 

var result=[]; 

for(var i=0,j=0;i<len1;i+=4){ 

c0=index64[strIn.charAt(i)]; 

c1=index64[strIn.charAt(i+1)]; 

c2=index64[strIn.charAt(i+2)]; 

c3=index64[strIn.charAt(i+3)]; 

b0=(c0<<2)|(c1>>4); 

b1=(c1<<4)|(c2>>2); 

b2=(c2<<6)|c3; 

result.push(b0&0xff); 

result.push(b1&0xff); 

result.push(b2&0xff); 

} 

if(len1!=len){ 

c0=index64[strIn.charAt(i)]; 

c1=index64[strIn.charAt(i+1)]; 

c2=strIn.charAt(i+2); 

b0=(c0<<2)|(c1>>4); 

result.push(b0&0xff); 

if(c2!='='){ 

c2=index64[c2]; 

b1=(c1<<4)|(c2>>2); 

result.push(b1&0xff); 

} 

} 

return result; 

} 

//用于GIF的LZW解码函数 

//arrBytes为源数据,nBits为初始编码位数 

//成功返回数组,每个元素包括一个颜色索引 

//失败返回null 

function decodeLzw(arrBytes,nBits){ 

var cc=1<<(nBits-1); 

var eoi=cc+1; 

var table=[],mask=[],result=[]; 

for(var i=0;i<cc;i++) 

table[i]=(i>>8&0xf).toString(16) 

+(i>>4&0xf).toString(16)+(i&0xf).toString(16); 

for(i=2,mask[1]=1;i<13;i++) 

mask[i]=mask[i-1]<<1|1; 

var bc=nBits; 

var pos=0,temp=0,tleft=0,code=0,old=0; 

while(true){ 

while(tleft<bc){ 

temp=temp|(arrBytes[pos++]<<tleft); 

tleft+=8; 

} 

code=temp&mask[bc]; 

tleft-=bc; 

temp>>=bc; 

if(code==eoi) 

break; 

if(code==cc){ 

table.length=cc+2; 

bc=nBits; 

old=code; 

continue; 

} 

var t=""; 

if(code<table.length){ 

t=table[code]; 

if(old!=cc) 

table.push(table[old]+t.slice(0,3)); 

} 

else if(old<table.length){ 

t=table[old]+table[old].slice(0,3); 

table.push(t); 

} 

else{ 

alert("错误:图像数据无效"); 

return null; 

} 

old=code; 

for(var i=0;i<t.length;i+=3) 

result.push(parseInt(t.substr(i,3),16)) 

if(table.length==1<<bc&&bc<12) 

bc++; 

} 

return result; 

} 

//根据字节数组data布局,以最少的div完成绘图 

function defLayout(data,palette,width,height,image,block,zoom){ 

var map=new Array(height); 

for(var i=0;i<height;i++){ 

map[i]=new Array(width); 

for(var j=0;j<width;j++) 

map[i][j]=data[i*width+j]; 

} 

var i,j,i1,i2,j1,j2,c; 

for(i=0;i<height;i++) 

for(j=0;j<width;){ 

if(map[i][j]==0x100){ 

j++; 

continue; 

} 

c=map[i][j]; 

for(i1=i+1;i1<height&&map[i1][j]==c;i1++); 

for(j1=j+1;j1<width;j1++){ 

for(i2=i;i2<i1&&map[i2][j1]==c;i2++); 

if(i2<i1) 

break; 

} 

for(i2=i;i2<i1;i2++) 

for(j2=j;j2<j1;j2++) 

map[i2][j2]=0x100; 

var x=block.cloneNode(true); 

x.style.left=j*zoom; 

x.style.top=i*zoom; 

x.style.width=(j1-j)*zoom; 

x.style.height=(i1-i)*zoom; 

x.style.backgroundColor=palette[c]; 

image.appendChild(x); 

j=j1; 

} 

} 

</SCRIPT> 

<script> 

function main(){ 

var t=new Date().getTime(); 

var xmldom=document.getElementById("imgData"); 

var gif=getGif("R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="); 

var info=document.getElementById("info"); 

info.innerHTML=gif.showInfo("<br>"); 

t=new Date().getTime(); 

gif.frames[0].draw(document.getElementById("canvas"),1); 

info.innerHTML+="<br>绘图耗时"+(new Date().getTime()-t)+"ms"; 

} 

</SCRIPT> 

<body onload="main()"> 

<div id="canvas"></div> 

<hr> 

<div id="info">页面载入中,请稍候...</div> 

</body> 

</html>
展开阅读全文

更多Javascript文章

JQuery异步获取返回值中文乱码的解决方法
Jan 29 23
jQuery无刷新上传之uploadify3.1简单使用
Jun 18 21
Angular 4依赖注入学习教程之ClassProvider的使用(三)
Jun 04 45
浅谈JavaScript面向对象--继承
Mar 20 20
微信小程序实现多选框全选与反全选及购物车中删除选中的商品功能
Dec 17 26
有关vue 开发钉钉 H5 微应用 dd.ready() 不执行问题及快速解决方案
May 09 21
Vue基于localStorage存储信息代码实例
Nov 16 26
手机访问当前页面