JavaScript实现Base64编码转换


Posted in Javascript onApril 23, 2016

简介

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外的两个可打印符号在不同的系统中而不同,一般为+和/。

转换原理

Base64的直接数据源是二进制序列(Binary Sequence)。当然,你也可以将图片、文本和音视频转换成二进制序列,再然后转换为Base64编码。我们这里讨论的是如何将二进制转换为Base64编码,对于如何将图片,文本和音视频转换为二进制序列敬请期待。

在转换前,先定义一张索引表,这张表规定了如何转换:

JavaScript实现Base64编码转换

转换的时候我们先将二进制序列分组,每6个比特为一组。但是如果编码的字节数不能被3整除,那么最后就会多出1个或两个字节,可以使用下面的方法进行处理:先使用0字节值在末尾补足,使其能够被3整除,然后再进行base64的编码。在编码后的base64文本后加上一个或两个'='号,代表补足的字节数。也就是说,当最后剩余一个八位字节(一个byte)时,最后一个6位的base64字节块有四位是0值,最后附加上两个等号;如果最后剩余两个八位字节(2个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。 参考下表:

JavaScript实现Base64编码转换

JavaScript实现Base64

原理明白了以后,实现起来就很容易了。

define(function(require, exports, module) {
 
  var code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""); //索引表
 
  /**
   * @author laixiangran@163.com
   * @description 将二进制序列转换为Base64编码
   * @param {String}
   * @return {String}
   */
  function binToBase64(bitString) {
    var result = "";
    var tail = bitString.length % 6;
    var bitStringTemp1 = bitString.substr(0, bitString.length - tail);
    var bitStringTemp2 = bitString.substr(bitString.length - tail, tail);
    for (var i = 0; i < bitStringTemp1.length; i += 6) {
      var index = parseInt(bitStringTemp1.substr(i, 6), 2);
      result += code[index];
    }
    bitStringTemp2 += new Array(7 - tail).join("0");
    if (tail) {
      result += code[parseInt(bitStringTemp2, 2)];
      result += new Array((6 - tail) / 2 + 1).join("=");
    }
    return result;
  }
 
  /**
   * @author laixiangran@163.com
   * @description 将base64编码转换为二进制序列
   * @param {String}
   * @return {String}
   */
  function base64ToBin(str) {
    var bitString = "";
    var tail = 0;
    for (var i = 0; i < str.length; i++) {
      if (str[i] != "=") {
        var decode = code.indexOf(str[i]).toString(2);
        bitString += (new Array(7 - decode.length)).join("0") + decode;
      } else {
        tail++;
      }
    }
    return bitString.substr(0, bitString.length - tail * 2);
  }
 
  /**
   * @author laixiangran@163.com
   * @description 将字符转换为二进制序列
   * @param {String} str
   * @return {String}  
   */
  function stringToBin(str) {
    var result = "";
    for (var i = 0; i < str.length; i++) {
      var charCode = str.charCodeAt(i).toString(2);
      result += (new Array(9 - charCode.length).join("0") + charCode);
    }
    return result;
  }

  /**
   * @author laixiangran@163.com
   * @description 将二进制序列转换为字符串
   * @param {String} Bin
   */
  function BinToStr(Bin) {
    var result = "";
    for (var i = 0; i < Bin.length; i += 8) {
      result += String.fromCharCode(parseInt(Bin.substr(i, 8), 2));
    }
    return result;
  }
  exports.base64 = function(str) {
    return binToBase64(stringToBin(str));
  }
  exports.decodeBase64 = function(str) {
    return BinToStr(base64ToBin(str));
  }
})

将图片数据进行Base64编码

将图片数据转换为Base64,首先要获取到图片的二进制数据。图片的二进制数据可以通过canvas接口得到。具体实现为:

function getCanvas(w, h) {
  var c = document.createElement('canvas');
  c.width = w;
  c.height = h;
  return c;
}
 
function getPixels(img) {
  var c = getCanvas(img.width, img.height);
  var ctx = c.getContext('2d');
  ctx.drawImage(img, 0, 0);
  return ctx.getImageData(0, 0, c.width, c.height);
}

取到图片的二进制数据后,接下来就要进行编码了。因为图片不仅包含像素信息,还包含长度,宽度信息。所以在编码像素信息的同时也应将宽度和高度信息按某一约定进行编码,我是这样处理的:

将图片的像素数值数据转换为二进制序列;将宽度和高度信息组合成字符串 $$width,height$$,转换为二进制序列;将图片像素信息的二进制序列和图片宽高度的二进制序列组合起来,然后再进行Base64的编码

具体实现为:

function img2Base64(img) {
  var imgData = getPixels(img).data;
  var imgWidth = getPixels(img).width;
  var imgHeight = getPixels(img).height;
  var bin = "";
  for (var i = 0; i < imgData.length; i++) {
    bin += base.numToString(imgData[i]);
  }
  bin = bin + base.stringToBin("$$" + imgWidth + "," + imgHeight + "$$");
  return base.binToBase64(bin);
}

将图片Base64数据进行解码

解码是编码的逆过程。过程大致为:

将图片的Base64信息进行解码,得到包含图片像素信息和宽高度信息的二进制序列;然后将这个二进制序列解码成字符串,获取高度和宽度信息;去除二进制序列中的高度和宽度信息,得到像素信息;根据像素信息生成像素矩阵;根据像素矩阵、宽度和高度创建图片对象ImageData;利用putImageData将图像绘制出来。

具体的代码实现为:

function paint(imgData) {
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    ctx.fillRect(0, 0, imgData.width, imgData.height);
    ctx.putImageData(imgData, 0, 0);
  }
 
function base642img(data) {
  var str = base.BinToStr(base.base64ToBin(data));
  var imgWidth = str.match(/\$\$(\d+),(\d+)\$\$$/, "")[1];
  var imgHeight = str.match(/\$\$(\d+),(\d+)\$\$$/, "")[2]
  var imgData = base.base64ToBin(data).replace(base.stringToBin("$$" + imgWidth + "," + imgHeight + "$$"), "");
 
  var ImageDataArray = new Uint8ClampedArray(imgWidth * imgHeight * 4);
  for (var i = 0; i < ImageDataArray.length; i++) {
    ImageDataArray[i] = parseInt(imgData.substr(i * 8, 8), 2);
  }
  return new ImageData(ImageDataArray, imgWidth, imgHeight);
 
}
Javascript 相关文章推荐
javascript 图片上一张下一张链接效果代码
Mar 12 Javascript
基于SVG的web页面图形绘制API介绍及编程演示
Jun 28 Javascript
JS父页面与子页面相互传值方法
Mar 05 Javascript
javascript中的nextSibling使用陷(da)阱(keng)
May 05 Javascript
JavaScript事件学习小结(三)js事件对象
Jun 09 Javascript
AngularJs页面筛选标签小功能
Aug 01 Javascript
AngularJs  unit-testing(单元测试)详解
Sep 02 Javascript
最全面的JS倒计时代码
Sep 17 Javascript
jquery select2的使用心得(推荐)
Dec 04 Javascript
提高Web性能的前端优化技巧总结
Feb 27 Javascript
详解vue-cli 脚手架 安装
Apr 16 Javascript
详解如何在Javascript中使用Object.freeze()
Oct 18 Javascript
jQuery UI库中dialog对话框功能使用全解析
Apr 23 #Javascript
详解jQuery UI库中文本输入自动补全功能的用法
Apr 23 #Javascript
AngularJS中的过滤器filter用法完全解析
Apr 22 #Javascript
举例讲解如何判断JavaScript中对象的类型
Apr 22 #Javascript
使用jQuery制作基础的Web图片轮播效果
Apr 22 #Javascript
使用jQuery UI库开发Web界面的简单入门指引
Apr 22 #Javascript
jQuery 监控键盘一段时间没输入
Apr 22 #Javascript
You might like
php打开文件fopen函数的使用说明
2013/07/05 PHP
PHP实现格式化文件数据大小显示的方法
2015/01/03 PHP
微信公众平台实现获取用户OpenID的方法
2015/04/15 PHP
Yii2实现ajax上传图片插件用法
2016/04/28 PHP
php中的登陆login实例代码
2016/06/20 PHP
php查询内存信息操作示例
2019/05/09 PHP
PHP中遍历数组的三种常用方法实例分析
2019/06/24 PHP
javascript Onunload与Onbeforeunload使用小结
2009/12/31 Javascript
JavaScript中的类(Class)详细介绍
2014/12/30 Javascript
node.js中的forEach()是同步还是异步呢
2015/01/29 Javascript
Js控制滑轮左右滑动实例
2015/02/13 Javascript
jquery实现仿新浪微博带动画效果弹出层代码(可关闭、可拖动)
2015/10/12 Javascript
JavaScript获取中英文混合字符串长度的方法示例
2017/02/04 Javascript
angular十大常见问题
2017/03/07 Javascript
Vue.js 表单控件操作小结
2018/03/29 Javascript
ES6 Iterator接口和for...of循环用法分析
2019/07/31 Javascript
node.js中module模块的功能理解与用法实例分析
2020/02/14 Javascript
解决vue打包 npm run build-test突然不动了的问题
2020/11/13 Javascript
JS获取一个字符串中指定字符串第n次出现的位置
2021/02/10 Javascript
videocapture库制作python视频高速传输程序
2013/12/23 Python
python实现超简单端口转发的方法
2015/03/13 Python
python 移除字符串尾部的数字方法
2018/07/17 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
pandas删除指定行详解
2019/04/04 Python
python实现发送form-data数据的方法详解
2019/09/27 Python
python3获取文件中url内容并下载代码实例
2019/12/27 Python
python如何实现复制目录到指定目录
2020/02/13 Python
tensorflow中tf.reduce_mean函数的使用
2020/04/19 Python
python相对企业语言优势在哪
2020/06/12 Python
枚举与#define宏的区别
2014/04/30 面试题
国家励志奖学金获奖感言
2014/01/09 职场文书
运动会通讯稿50字
2014/01/30 职场文书
小学作文指导之如何写人?
2019/07/08 职场文书
HTML5+CSS+JavaScript实现捉虫小游戏设计和实现
2021/10/16 HTML / CSS
SQL SERVER触发器详解
2022/02/24 SQL Server
一起来学习Python的元组和列表
2022/03/13 Python