想不到的將JS文件壓縮成PNG圖像存儲(chǔ)方法
你有沒(méi)有想過(guò):為了壓縮js文件,把js文件轉(zhuǎn)化成PNG圖像,然后用 canvas 控件中的 getImageData() 函數(shù)將圖像再重新讀成js文件。我昨天在這里發(fā)表的JS文件快速加載的文章中提到了這一方法,有網(wǎng)友對(duì)這個(gè)做法很感興趣,于是今天詳細(xì)解讀一下。
這樣可以做到很高的壓縮比,到底有多高,下面會(huì)提到。這種方法用到了 canvas 控件,這也意味著只有支持 canvas 控件的瀏覽器下才有效。
現(xiàn)在你可以看到,上面的圖像類(lèi)似一個(gè)噪聲圖像,但它實(shí)際上是一個(gè)由124K的 prototype 框架代碼轉(zhuǎn)化成的30K的8位PNG圖像(壓縮比還不錯(cuò)吧)。
其實(shí),要將代碼轉(zhuǎn)化為圖像的格式存儲(chǔ),可以轉(zhuǎn)化成GIF和PNG格式。PNG格式的圖像有24位和8位,用24位的RGB圖像,每個(gè)像素可以存儲(chǔ)3字節(jié)的數(shù)據(jù),如果是用8位的RGB圖像,每個(gè)像素可以存儲(chǔ)1字節(jié)的數(shù)據(jù)。
在PHOTOSHOP中做測(cè)試發(fā)現(xiàn):一個(gè)300x100的純色雜點(diǎn)8位圖像可以壓縮到5K,而同樣的純色雜點(diǎn)圖像,如果是100x100的24位圖像只能壓縮到20K。如果是同樣圖案的8位GIF圖像,壓縮效果比PNG要差一些。所以,我們選擇用8位的PNG圖像作為壓縮和解壓縮的存儲(chǔ)格式。
現(xiàn)在,我們就需要開(kāi)始?jí)嚎s圖像了,下面是用PHP寫(xiě)的壓縮文件地址。
- <?
- $filename = "prototype-1.6.0.2.js";
- if (file_exists($filename)) {
- $iFileSize = filesize($filename);
- $iWidth = ceil(sqrt($iFileSize / 1));
- $iHeight = $iWidth;
- $im = imagecreatetruecolor($iWidth, $iHeight);
- $fs = fopen($filename, "r");
- $data = fread($fs, $iFileSize);
- fclose($fs);
- $i = 0;
- for ($y=0;$y<$iHeight;$y++) {
- for ($x=0;$x<$iWidth;$x++) {
- $ord = ord($data[$i]);
- imagesetpixel($im,
- $x, $y,
- imagecolorallocate($im,
- $ord,
- $ord,
- $ord
- )
- );
- $i++;
- }
- }
- header("Content-Type: image/png");
- imagepng($im);
- imagedestroy($im);
- }
- ?>
它讀取JS文件并創(chuàng)建一個(gè)PNG圖像,圖像中的每個(gè)像素中是一個(gè)0-255之間的值,而這個(gè)值對(duì)應(yīng)的是JS字符的ascII的值。
當(dāng)然,除了壓縮,還要有解壓縮,也就是將圖像讀取為JS文件的過(guò)程。這個(gè)函數(shù)是用JS寫(xiě)的,可以從下面的位置下載這個(gè)文件。
- function loadPNGData(strFilename, fncCallback) {
- // test for canvas and getImageData
- var bCanvas = false;
- var oCanvas = document.createElement("canvas");
- if (oCanvas.getContext) {
- var oCtx = oCanvas.getContext("2d");
- if (oCtx.getImageData) {
- bCanvas = true;
- }
- }
- if (bCanvas) {
- var oImg = new Image();
- oImg.style.position = "absolute";
- oImg.style.left = "-10000px";
- document.body.appendChild(oImg);
- oImg.onload = function() {
- var iWidth = this.offsetWidth;
- var iHeight = this.offsetHeight;
- oCanvas.width = iWidth;
- oCanvas.height = iHeight;
- oCanvas.style.width = iWidth+"px";
- oCanvas.style.height = iHeight+"px";
- var oText = document.getElementById("output");
- oCtx.drawImage(this,0,0);
- var oData = oCtx.getImageData(0,0,iWidth,iHeight).data;
- var a = [];
- var len = oData.length;
- var p = -1;
- for (var i=0;i<len;i+=4) {
- if (oData[i] > 0)
- a[++p] = String.fromCharCode(oData[i]);
- };
- var strData = a.join("");
- if (fncCallback) {
- fncCallback(strData);
- }
- document.body.removeChild(oImg);
- }
- oImg.src = strFilename;
- return true;
- } else {
- return false;
- }
- }
***給出在線測(cè)試地址,在這個(gè)網(wǎng)頁(yè)上,您可以在列表中選擇一個(gè)PNG圖像文件,點(diǎn)擊 load file 按鈕可以在網(wǎng)頁(yè)上看到這個(gè)圖像,在圖像的下面是由這個(gè)圖像所讀出來(lái)的代碼文件。http://www.nihilogic.dk/labs/canvascompress/
原文鏈接:http://www.cnblogs.com/ilian/archive/2012/06/21/js-to-png.html
【編輯推薦】