将js/css脚本放到png图片中的实践。

http://blog.csdn.net/zswang/article/details/7061560

将js/css脚本放到png图片中的实践。

标签: 脚本functionxmlhttprequesturl浏览器加密

2011-12-11 21:50 13788人阅读 评论(26) 收藏 举报

 分类:

前端技术 png canvas 压缩

版权声明:本文为博主原创文章,未经博主允许不得转载。

起因

高级浏览器支持data协议,如:

参考:http://en.wikipedia.org/wiki/Data:_URL

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC"/>

<script src="data:text/javascript;base64,YWxlcnQoJ2h0dHA6Ly93ZWliby5jb20venN3YW5nJyk7"></script>

不光是<img>标签,<script>、<style>、<iframe>也都支持data协议;

data协议可以表示图片、文本、音视频等各种二进制数据

另html5的canvas除了绘制图像,还能读写每一个像素值

一种把脚本存到图像中的思路就有了。

经过

最初的尝试就是把每个字符挨个放到像素的r、g、b、a里

需要处理的问题:

1、计算图片的尺寸;

本来想用高度为1,宽度为字符串长度的尺寸,但考虑到压缩比和美观,所以决定生成正方形。

var pixel = Math.ceil((text.length + 3) / 4);

var size = Math.ceil(Math.sqrt(pixel));

2、每个字符unicode编码,可能会超出255;

那就得将字符串转成ascii码

function encodeUTF8(str) {

return String(str).replace(

/[\u0080-\u07ff]/g,

function(c) {

var cc = c.charCodeAt(0);

return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f);

}

).replace(

/[\u0800-\uffff]/g,

function(c) {

var cc = c.charCodeAt(0);

return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3f, 0x80 | cc & 0x3f);

}

);

}

3、还得考虑异步的问题

var img = document.createElement(‘img‘);

img.onload = function(){

//...;

}

 

第一轮demo做完,结果测试不符合预期。跟踪发现:还原的数据和编码的数据相差较大。

开始在怀疑是不是img标签绘制到canvas变成了有损压缩,如果真是这样,那整个方案就是不可行;

坚持“不抛弃,不放弃”+定位问题最简化的原则,逐步缩小范围,最终锁定是由于alpha值影响还原。
解决方案就是:一个像素存放三个字符并将alpha固定为255。


第二轮demo测试符合预期。

总结

build流程:

1、字符串转换成ascii码;

2、创建足够存储空间的canvas;

3、将字符填入到像素中(忽略alpha值);

4、获取data url;

canvas.toDataURL("image/png");

5、存为png图片。
代码示例

[html] view plain copy

  1. <textarea id="base64"></textarea>
  2. <script>
  3. function encodeUTF8(str) {
  4. return String(str).replace(
  5. /[\u0080-\u07ff]/g,
  6. function(c) {
  7. var cc = c.charCodeAt(0);
  8. return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f);
  9. }
  10. ).replace(
  11. /[\u0800-\uffff]/g,
  12. function(c) {
  13. var cc = c.charCodeAt(0);
  14. return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3f, 0x80 | cc & 0x3f);
  15. }
  16. );
  17. }
  18. function request(url, loaded) {
  19. var xmlhttp = new XMLHttpRequest();
  20. xmlhttp.onreadystatechange = function() {
  21. if (xmlhttp.readyState == 4)
  22. if (xmlhttp.status == 200)
  23. loaded(xmlhttp);
  24. }
  25. xmlhttp.open("GET", url, true);
  26. xmlhttp.send();
  27. }
  28. void function(){
  29. var source = ‘tangram-1.5.0.js‘;
  30. request(source, function(xmlhttp){
  31. var text = encodeUTF8(xmlhttp.responseText);
  32. var pixel = Math.ceil((text.length + 2) / 3); // 1一个像素存3个字节,
  33. var size = Math.ceil(Math.sqrt(pixel));
  34. //console.log([text.length, pixel, size, size * size * 3]);
  35. var canvas = document.createElement(‘canvas‘);
  36. canvas.width = canvas.height = size;
  37. var context = canvas.getContext("2d"),
  38. imageData = context.getImageData(0, 0, canvas.width, canvas.height),
  39. pixels = imageData.data;
  40. for(var i = 0, j = 0, l = pixels.length; i < l; i++){
  41. if (i % 4 == 3) { // alpha会影响png还原
  42. pixels[i] = 255;
  43. continue;
  44. }
  45. var code = text.charCodeAt(j++);
  46. if (isNaN(code)) break;
  47. pixels[i] = code;
  48. }
  49. context.putImageData(imageData, 0, 0);
  50. document.getElementById(‘base64‘).value = canvas.toDataURL("image/png");
  51. });
  52. }();
  53. </script>

编译结果

调用流程:

1、加载png;

2、将png原尺寸绘制到canvas中;

3、读取像素中的字符串;

4、生成相应协议的data url使用。
代码示例

[html] view plain copy

  1. <script>
  2. void function(){
  3. var source = ‘tangram-1.5.0.png‘;
  4. var img = document.createElement(‘img‘);
  5. img.onload = function(){
  6. var canvas = document.createElement(‘canvas‘);
  7. canvas.width = img.width;
  8. canvas.height = img.height;
  9. var context = canvas.getContext("2d");
  10. context.drawImage(img, 0, 0);
  11. var imageData = context.getImageData(0, 0, canvas.width, canvas.height),
  12. pixels = imageData.data;
  13. var script = document.createElement(‘script‘);
  14. var buffer = [];
  15. for (var i = 0, l = pixels.length; i < l; i++) {
  16. if (i % 4 == 3) continue; // alpha会影响png还原
  17. if (!pixels[i]) break;
  18. buffer.push(String.fromCharCode(pixels[i]));
  19. }
  20. script.src = ‘data:text/javascript;charset=utf-8,‘ + encodeURIComponent(buffer.join(‘‘));
  21. document.body.appendChild(script);
  22. script.onload = function(){
  23. alert(T.date.format(new Date, ‘yyyy年M月d日‘));
  24. }
  25. img = null;
  26. }
  27. img.src = source;
  28. }();
  29. </script>

优势

1、压缩率大(50%);

2、隐蔽性相对高;

可以设计加密的脚本,用公钥解锁;

3、减少网络请求;

可以将多个图片、脚本放到一个png里,囧;

4、一种二进制处理文本的思路。

劣势

1、解码会使用更多的cpu,导致加载缓慢;

2、不支持低端浏览器;

3、开发维护成本更高。

总结

1、不具实战性;

2、在数据加密传输方面可以近一步研究。

相关demo

http://jssdk.com/imgscript/index.html

时间: 2024-12-28 23:38:56

将js/css脚本放到png图片中的实践。的相关文章

Google Pagespeed,自动压缩优化JS/CSS/Image

Google Pagespeed,自动压缩优化JS/CSS/Image 浏览:257 发布日期:2015/07/05 分类:技术分享 关键字: Nginx Appache Pagespeed 自动压缩优化JS/CSS/Image 这个周末,把服务器的Nginx升级了下,并加入了Google Pagespeed模块 效果很明显: 页面加载的多个JS.CSS会自动合并压缩处理 发现新版本的Pagespeed能很好的发现处理用户加载的第三方JS库,如jQuery 发现新版本的lazyload_imag

实用js+css多级树形展开效果导航菜单

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

js+css实现带缓冲效果右键弹出菜单

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

ASP.NET MVC 4使用Bundle的打包压缩JS/CSS

打包(Bundling)及压缩(Minification)指的是将多个js文件或css文件打包成单一文件并压缩的做法,如此可减少浏览器需下载多个文件案才能完成网页显示的延迟感,同时通过移除JS/CSS文件案中空白.批注及修改JavaScript内部函数.变量名称的压缩手法,能有效缩小文件案体积,提高传输效率,提供使用者更流畅的浏览体验. 在ASP.NET MVC 4中可以使用BundleTable捆绑多个css文件和js文件,以提高网络加载速度和页面解析速度.更为重要的是通过捆绑可以解决IE浏览

iOS项目中如何正确引入Html5文件(html/js/css)

iOS项目中使用项目中的html js css 文件时,有时会遇到引用路径出错的问题,导致html js css image文件无法加载的情况. 那么,引入H5相关文件的正确操作方式如下,这样就不会出现资源文件无法引入并正常使用的情况: 1 在项目目录下创建存放Html5文件文件夹:H5 2 将文件夹H5拖放至项目中对应的位置,此处注意要选择:Create groups 3 将各种Html5文件(html js css image等)拖放到H5文件夹中,此处注意选择:Create folder

压缩 js/css 的工具

最近检测服务器,发现js/css文件都没有压缩过,动手解决此问题先. 本次压缩采用 yui compress (2.4.8) 压缩脚本: #!/bin/sh echo "###########################" echo "---------------------------" echo "begin to compress JS file." for file in `find . -name "*.js"

动态加载js,css(项目中需要的)

最近做的一个项目需要加入百度统计,大家都知道百度统计在页面引用就是一坨js,实现方法很简单引用到页面就ok了. 那么问题来了,虽然我不知道百度统计的原理是啥,我的测试服引用了百度统计,百度统计账号里面配置的域名是正式服的域名,但是却检测到了我测试服的访问量,这就尴尬了,然后就想到了动态加载js 1.动态加载js文件 我们要把这块链接加入页面 <script src="js/count.js"></script> 具体代码实现如下 function loadJs(

iOS之在webView中引入本地html,image,js,css文件的方法 - sky//////////////////////////////////////ZZZZZZZZZZZZZZZ

iOS之在webView中引入本地html,image,js,css文件的方法 2014-12-08 20:00:16CSDN-sky_2016-点击数:10292 项目需求 最近开发的项目,需要一个webView,同时这个webView会需要引入一些项目中的资源: 一个本地的html文件,作为webView的模板 两张loading图片,在图片未加载的时候进行占位 jquery.js,scrollLoading.js 也是本地的,实现滚动加载图片功能 然后就开始了漫长的Google历程. 在w

PHP JS CSS session实现验证码功能

PHP JS CSS session实现验证码功能 页面<?php//校验验证码if (isset($_POST["authcode"])) {session_start(); if (strtolower($_POST["authcode"]) == $_SESSION["authcode"]) { echo "<font color='#0000cc'>输入正确</font>"; } else