JS在浏览器中解析Base64编码图像


Posted in Javascript onFebruary 09, 2017

上一篇介绍中,我们将二进制文件(BLOB)保存为Base64编码的文本,这些文本可以内嵌在XML的标签中,因此二进制信息它可以随着XML文件被拷贝、下载而不用担心信息会缺失。这项技术也在email邮件中被广泛使用。

浏览器对Base64的支持

图像是最经常被使用的一种二进制文件。而现代的浏览器的进步日新月异,IE7,FireFox和其他浏览器为包括Base64在内各种编码的图像信息提供了很好的支持。因此图形信息可以以下面的形式呈现在页面中、

Java代码

<img src="data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM///// 
wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4ML 
wWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==" 
alt="Base64 encoded image" width="150" height="150"/>

这种data: URI的格式能把Base64(或其他数据)可以内嵌在image标签的属性当中(或者CSS中)。我们可以看到在大部分浏览器中的显示效果: 

JS在浏览器中解析Base64编码图像

这种做法有利有弊,好处是浏览器可以在一个连接中得到完成的页面内容,不好的地方时图像的大小会增加1/3。因此,这种内嵌的方法适合对小的图形元素比如图标、圆角等等进行处理,从而减少浏览器打开的连接数,但对大的照片、图片(量少而大)等等则不应该使用Base64编码以免影响下载速度。

为了得到刚才的Base64编码,我们将上一篇的Java修改成Struts Action,并借用了JIMI进行图形的读取和格式转换,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; 
 } 
}

对应的View端是个十分简单的Freemarker模板:

Html代码

<html> 
<head> 
<title>Hello,World</title> 
</head> 
<body> 
<img src="data:image/png;base64,${encodeString}" /> 
</body> 
</html>

处理古代浏览器

世界总是不是那么完美,尽管大部分现代浏览器对Base64的处理都十分完善,但是我们不能不考虑到一些“古老”的浏览器,而现在还是普遍使用的“古老”的浏览器,就当属IE6,在IE6里试图浏览上面的图片可能会得到一个红叉叉。我们不得不为IE6做一些特殊处理,利用下面的JavaScript,我们把Base64字串传回服务器端,重新解析成图片

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]); 
 } 
};

服务器端的Struts可以参考上面的例子做反向操作,具体从略。

更完美的方法

将Base64传回服务器解码是不错的IE6补丁,但是违背了我们的初衷,对IE6来说,浏览器连接数并未有任何减少。更直接的想法,是否能用Javascript直接在浏览器中,对Base64文本进行解码呢?我们构思的场景如下:服务器端先将图片转换成PNG格式以方便客户端进行处理,Base64编码之后,利用JSON将文本传递给浏览器客户端进行处理。

我们选择PNG图形格式是因为PNG已经俨然成为新的Web图形标准,它格式非常简单,可以很方便的用javascript进行处理而不需要借助浏览器的支持。我们知道javascript直接不能处理二进制数据,但是现在这不是个问题,服务器端已经准备好了Base64编码的文本数据,现在我们只需要一个javascript的Base64解析器,你可以在这里找到一个notmasteryet的Base64解析器。

现在PNG图形格式采用了DEFLATE作为唯一的压缩算法,该算法也广泛应用在ZIP,GZIP等压缩格式中。PNG图像格式文件(或者称为数据流)由一个8字节的PNG文件署名(PNG file signature)域和按照特定结构组织的3个以上的数据块(chunk)组成。

PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,其中图像数据块IDAT(image data chunk):它存储实际的数据, PNG总的数据流采用DEFLAT进行压缩。此外还擦用三角过滤“delta filters”来过滤每一行的像素的未压缩数据。DEFLAT和delta压缩在其他数据和文本处理中也被广泛应用。PNG格式你可以参考<a href="http://www.libpng.org/pub/png/spec/1.1/PNG-Contents.html">官方文档</a>。

很棒的,notmasteryet也为我们提供了一个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.......数据从略......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编码图像,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
div拖拽插件——JQ.MoveBox.js(自制JQ插件)
May 17 Javascript
基于jquery实现的文字淡入淡出效果
Nov 14 Javascript
键盘KeyCode值列表汇总
Nov 26 Javascript
node.js中RPC(远程过程调用)的实现原理介绍
Dec 05 Javascript
jquery根据一个值来选中select下的option实例代码
Aug 29 Javascript
@ResponseBody 和 @RequestBody 注解的区别
Mar 08 Javascript
vue如何使用 Slot 分发内容实例详解
Sep 05 Javascript
jQuery中的for循环var与let的区别
Apr 21 jQuery
解决vue数组中对象属性变化页面不渲染问题
Aug 09 Javascript
微信小程序实现多选功能
Nov 04 Javascript
微信小程序获取复选框全选反选选中的值(实例代码)
Dec 17 Javascript
vue实现移动端触屏拖拽功能
Aug 21 Javascript
jQuery实现在新增加的元素上添加事件方法案例分析
Feb 09 #Javascript
jquery滚动条插件slimScroll使用方法
Feb 09 #Javascript
JS回调函数简单用法示例
Feb 09 #Javascript
Bootstrap列表组学习使用
Feb 09 #Javascript
jQuery实现获取隐藏div高度的方法示例
Feb 09 #Javascript
Bootstrap进度条学习使用
Feb 09 #Javascript
详解浏览器渲染页面过程
Feb 09 #Javascript
You might like
PHP的范围解析操作符(::)的含义分析说明
2011/07/03 PHP
php实现最简单的MVC框架实例教程
2014/09/08 PHP
PHP获取文件相对路径的方法
2015/02/26 PHP
PHP文件上传问题汇总(文件大小检测、大文件上传处理)
2015/12/24 PHP
php文件包含目录配置open_basedir的使用与性能详解
2017/04/03 PHP
PHP排序算法之归并排序(Merging Sort)实例详解
2018/04/21 PHP
动态表格Table类的实现
2009/08/26 Javascript
简洁实用的BootStrap jQuery手风琴插件
2016/08/31 Javascript
jQuery扩展+xml实现表单验证功能的方法
2016/12/25 Javascript
详解webpack的配置文件entry与output
2017/08/21 Javascript
微信小程序之页面拦截器的示例代码
2017/09/07 Javascript
vue3.0 CLI - 2.2 - 组件 home.vue 的初步改造
2018/09/14 Javascript
详解vuex commit保存数据技巧
2018/12/25 Javascript
详解vue使用$http服务端收不到参数
2019/04/19 Javascript
Node.js文本文件BOM头的去除方法
2020/11/22 Javascript
[13:16]INFAMOUS vs VGJ T BO3
2018/06/07 DOTA
Python实现的简单万年历例子分享
2014/04/25 Python
Python读取sqlite数据库文件的方法分析
2017/08/07 Python
python模块之sys模块和序列化模块(实例讲解)
2017/09/13 Python
Python多进程fork()函数详解
2019/02/22 Python
在python中,使用scatter绘制散点图的实例
2019/07/03 Python
keras读取训练好的模型参数并把参数赋值给其它模型详解
2020/06/15 Python
浅谈Python里面None True False之间的区别
2020/07/09 Python
html5指南-1.html5全局属性(html5 global attributes)深入理解
2013/01/07 HTML / CSS
美国男士和女士奢侈品折扣手表购物网站:Certified Watch Store
2018/06/13 全球购物
奖学金自我鉴定范文
2013/10/03 职场文书
应届本科生推荐信范文
2013/12/25 职场文书
应用化学专业职业生涯规划书
2013/12/31 职场文书
办公室主任主任岗位责任制
2014/02/11 职场文书
学生打架检讨书
2014/02/14 职场文书
《雷雨》教学反思
2014/02/20 职场文书
大学生评语大全
2014/04/18 职场文书
升学宴演讲稿
2014/09/01 职场文书
“四风”查摆问题自我剖析材料
2014/09/27 职场文书
Python进程间的通信之语法学习
2022/04/11 Python
使用python绘制横竖条形图
2022/04/21 Python