你有沒有想過:為了壓縮js文件,把js文件轉化成PNG圖像,然後用 canvas 控件中的 getImageData() 函數將圖像再重新讀成js文件。我昨天在這裡發表的JS文件快速加載的文章中提到了這一方法,有網友對這個做法很感興趣,於是今天詳細解讀一下。
這樣可以做到很高的壓縮比,到底有多高,下面會提到。這種方法用到了 canvas 控件,這也意味著只有支持 canvas 控件的浏覽器下才有效。

現在你可以看到,上面的圖像類似一個噪聲圖像,但它實際上是一個由124K的 prototype 框架代碼轉化成的30K的8位PNG圖像(壓縮比還不錯吧)。
其實,要將代碼轉化為圖像的格式存儲,可以轉化成GIF和PNG格式。PNG格式的圖像有24位和8位,用24位的RGB圖像,每個像素可以存儲3字節的數據,如果是用8位的RGB圖像,每個像素可以存儲1字節的數據。
在PHOTOSHOP中做測試發現:一個300x100的純色雜點8位圖像可以壓縮到5K,而同樣的純色雜點圖像,如果是100x100的24位圖像只能壓縮到20K。如果是同樣圖案的8位GIF圖像,壓縮效果比PNG要差一些。所以,我們選擇用8位的PNG圖像作為壓縮和解壓縮的存儲格式。
現在,我們就需要開始壓縮圖像了,下面是用PHP寫的壓縮文件的方法:
<?php
$filename="http://www.phpernote.com/js/jquery.min.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文件並創建一個PNG圖像,圖像中的每個像素中是一個0-255之間的值,而這個值對應的是JS字符的ascII的值。
當然,除了壓縮,還要有解壓縮,也就是將圖像讀取為JS文件的過程。這個函數是用JS寫的,具體代碼如下:
function loadPNGData(strFilename,fncCallback){
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;
}
}
最後給出在線測試地址,在這個網頁上,您可以在列表中選擇一個PNG圖像文件,點擊 load file 按鈕可以在網頁上看到這個圖像,在圖像的下面是由這個圖像所讀出來的代碼文件。
http://www.nihilogic.dk/labs/canvascompress/