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


Posted in Javascript onMarch 17, 2014
<!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 相关文章推荐
解密效果
Jun 23 Javascript
MooTools 1.2介绍
Sep 14 Javascript
JavaScript Cookie的读取和写入函数
Dec 08 Javascript
JavaScript操作XML 使用百度RSS作为新闻源示例
Feb 17 Javascript
js 判断浏览器使用的语言示例代码
Mar 22 Javascript
javascript中的循环语句for语句深入理解
Apr 04 Javascript
js加入收藏夹代码(兼容ie/ff/op)
May 16 Javascript
基于JavaScript代码实现pc与手机之间的跳转
Dec 23 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
Mar 04 Javascript
angularjs+bootstrap实现自定义分页的实例代码
Jun 19 Javascript
js实现拖动缓动效果
Jan 13 Javascript
使用JavaScript通过前端发送电子邮件
May 22 Javascript
javascript文件中引用依赖的js文件的方法
Mar 17 #Javascript
jquery解析JSON数据示例代码
Mar 17 #Javascript
javascript事件函数中获得事件源的两种不错方法
Mar 17 #Javascript
javascript内置对象arguments详解
Mar 16 #Javascript
javascript跨浏览器的属性判断方法
Mar 16 #Javascript
JS高级调试技巧:捕获和分析 JavaScript Error详解
Mar 16 #Javascript
Jquery 在页面加载后执行的几种方式
Mar 14 #Javascript
You might like
php中实现记住密码下次自动登录的例子
2014/11/06 PHP
php三种实现多线程类似的方法
2015/10/30 PHP
总结PHP删除字符串最后一个字符的三种方法
2016/08/30 PHP
总结PHP内存释放以及垃圾回收
2018/03/29 PHP
各种常用浏览器getBoundingClientRect的解析
2009/05/21 Javascript
用js模拟JQuery的show与hide动画函数代码
2010/09/20 Javascript
为radio类型的INPUT添加客户端脚本(附加实现JS来禁用onClick事件思路代码)
2010/11/11 Javascript
js循环改变div颜色具体方法
2013/06/25 Javascript
js字母大小写转换实现方法总结
2013/11/13 Javascript
jQuery内部原理和实现方式浅析
2015/02/03 Javascript
jquery简单实现外部链接用新窗口打开的方法
2015/05/30 Javascript
jQuery实现带水平滑杆的焦点图动画插件
2016/03/08 Javascript
jquery操作ID带有变量的节点实例
2016/12/07 Javascript
使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)
2017/01/21 Javascript
js截取字符串功能的实现方法
2017/09/27 Javascript
vue中v-cloak解决刷新或者加载出现闪烁问题(显示变量)
2018/04/20 Javascript
小程序转发探索示例
2019/02/19 Javascript
python登录pop3邮件服务器接收邮件的方法
2015/04/30 Python
Python使用logging结合decorator模式实现优化日志输出的方法
2016/04/16 Python
Python中表达式x += y和x = x+y 的区别详解
2017/06/20 Python
Django使用详解:ORM 的反向查找(related_name)
2018/05/30 Python
Python实现常见的回文字符串算法
2018/11/14 Python
Python爬取数据保存为Json格式的代码示例
2019/04/09 Python
详细分析Python collections工具库
2020/07/16 Python
欧洲高端品牌直销店:Fashionesta
2016/08/31 全球购物
澳大利亚冒险体验:Adrenaline(跳伞、V8赛车、热气球等)
2017/09/18 全球购物
德国香水、化妆品和护理产品网上商店:Parfumdreams
2018/09/26 全球购物
美国专业汽车音响和移动电子产品零售商:Car Toys
2019/05/13 全球购物
董事长职责范文
2013/11/08 职场文书
供应链金融服务方案
2014/05/25 职场文书
统计员岗位职责
2015/02/11 职场文书
幼儿园老师个人总结
2015/02/28 职场文书
开展警示教育活动总结
2015/05/09 职场文书
2016年寒假政治学习心得体会
2015/10/09 职场文书
Python入门学习之类的相关知识总结
2021/05/25 Python
pytorch model.cuda()花费时间很长的解决
2021/06/01 Python