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 相关文章推荐
List Information About the Binary Files Used by an Application
Jun 11 Javascript
基于jquery的下拉框改变动态添加和删除表格实现代码
Sep 12 Javascript
Jqyery中同等与js中windows.onload的应用
May 10 Javascript
jWiard 基于JQuery的强大的向导控件介绍
Oct 28 Javascript
导入extjs、jquery 文件时$使用冲突问题解决方法
Jan 14 Javascript
详解javascript中的事件处理
Nov 06 Javascript
JavaScript实现页面定时刷新(定时器,meta)
Oct 12 Javascript
vue中手机号,邮箱正则验证以及60s发送验证码的实例
Mar 16 Javascript
Node.js进阶之核心模块https入门
May 23 Javascript
JavaScript中的一些实用小技巧总结
Apr 07 Javascript
150行代码带你实现微信小程序中的数据侦听
May 17 Javascript
类和原型的设计模式之复制与委托差异
Jul 07 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+swoole+linux实现系统监控和性能优化操作示例
2019/04/15 PHP
java解析json方法总结
2019/05/16 PHP
表单(FORM)的一些实用效果代码
2007/03/25 Javascript
表格 隔行换色升级版
2009/11/07 Javascript
json2.js的初步学习与了解
2011/10/06 Javascript
加载远程图片时,经常因为缓存而得不到更新的解决方法(分享)
2013/06/26 Javascript
使用js完成节点的增删改复制等的操作
2014/01/02 Javascript
javascript比较两个日期相差天数的方法
2015/07/24 Javascript
详解JavaScript ES6中的模板字符串
2015/07/28 Javascript
javascript+canvas实现刮刮卡抽奖效果
2015/07/29 Javascript
javascript实现tab切换的两个实例
2015/11/05 Javascript
Bootstrap每天必学之简单入门
2015/11/19 Javascript
jQuery操作Table技巧大汇总
2016/01/23 Javascript
BootStrap树状图显示功能
2016/11/24 Javascript
在js代码拼接dom对象到页面上去的模板总结(必看)
2017/02/14 Javascript
javascript 秒表计时器实现代码
2017/03/09 Javascript
vue.js学习之UI组件开发教程
2017/07/03 Javascript
荐书|您有一份JavaScript书单待签收
2017/07/21 Javascript
JS监控关闭浏览器操作的实例详解
2017/09/12 Javascript
基于js中style.width与offsetWidth的区别(详解)
2017/11/12 Javascript
Vue 创建组件的两种方法小结(必看)
2018/02/23 Javascript
11行JS代码制作二维码生成功能
2018/03/09 Javascript
微信小程序获取当前位置和城市名
2019/11/13 Javascript
js 执行上下文和作用域的相关总结
2021/02/08 Javascript
python使用wmi模块获取windows下硬盘信息的方法
2015/05/15 Python
对python实时得到鼠标位置的示例讲解
2018/10/14 Python
Python 正则表达式 re.match/re.search/re.sub的使用解析
2019/07/22 Python
使用CSS3编写类似iOS中的复选框及带开关的按钮
2016/04/11 HTML / CSS
html5定位获取当前位置并在百度地图上显示
2014/08/22 HTML / CSS
德国购买健身器材:AsVIVA
2017/08/09 全球购物
辩论赛主持词
2014/03/18 职场文书
校园游戏活动新闻稿
2014/10/15 职场文书
2014年打非治违工作总结
2014/11/13 职场文书
工伤事故赔偿协议书
2015/08/06 职场文书
Python如何加载模型并查看网络
2022/07/15 Python
mysql序号rownum行号实现方式
2022/12/24 MySQL