看過FlashK寫的《關于Flash AS2 中的拍照圖片傳輸量太大的解決思路》,也想加一個算法。
我們都說無損壓縮吧,保留點陣數(shù)據(jù)。 此法壓縮的數(shù)據(jù)已經(jīng)接近BMP格式的圖片大小,我的機器花費大約1秒處理200*200的圖片,比未壓縮的字符的壓縮比率為50%。具體圖片比較黑暗則壓縮更好。
引用: 未壓縮文本:295k 壓縮文本:143k 高階壓縮:127k BMP圖片(200*200一樣的圖片):117k
壓縮結果類似:
引用: 200,200='c,'c,'c,'c,'c,Eg,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,' c,'c,Eg,Eg,Eg,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,R9,R9, R9,R9,0i,0i,0i,0i,0i,0i,0i,0i,0i,0i,0i,0i,Eg,Q9,){,)c,0i,Eg,Eg,0i,0i,0i,R9,R9,R9,R9,)c,/E,'c,0i,R9,0i,R9,R9,R9,R9,R9,R9,0i,)c,)c,R9,R9,R9,R9,R9,R9,R9,R9,R9,R9,EE
我這里的思維是用自定義的進制來處理數(shù)字壓縮的問題。
原理:按字符來算,一個數(shù)字用2進制是最長的,用十進制則更短,用16進制更短,那用盡量大的進制則字符越少。
進階壓縮算法:選擇起始點算法,分段壓縮,鄰近同樣字符用范圍數(shù)表示。
先說一下本次的算法:
//program by hqlulu //www.aslibra.com
import flash.display.BitmapData; //自定義寬和高 var max_w:Number = 200; var max_h:Number = 200; var myBitmap:BitmapData = new BitmapData(max_w, max_h, true, 0x000000); myBitmap.draw(_root); view_mc.attachBitmap(myBitmap, 10); //是否壓縮 //我的測試數(shù)據(jù): //true:1382 ms //false:364 ms var is_compress:Boolean = true; // //定義進制字符,在這里差不多把所有的字符用上了,用的越多壓縮越好,不過選擇ffffff所達到的字符數(shù)最好 //這里對于圖片加密也有很大的幫助! var code:String = "0123456789qwertyuiop[]asdfghjkl;zxcvbnm./QWERTYUIOP{}|ASDFGHJKL:ZXCVBNM<>?~!@#$%^&*()_+'"; var code_array:Array = code.split(""); //多少個字符就是多少進制了 var byte:Number = code.length; function getcode(i:Number):String { //取整求余法 var return_code:String = ""; while ((i=Math.ceil(i/byte))>byte) { return_code += code_array[i%byte]; } return_code += code_array[i]; return return_code; } // //記錄的數(shù)組 var p_array:Array = new Array(); var timer:Number = getTimer(); function save2array():Void { for (var i:Number = 0; i<max_w; i++) { p_array[i] = new Array(); for (var j:Number = 0; j<max_h; j++) { //這里不加判斷的話,速度可以提高些 if (is_compress) { p_array[i].push(getcode(myBitmap.getPixel(i+1, j+1))); } else { p_array[i].push(myBitmap.getPixel(i+1, j+1)); } } } } save2array(); trace("轉換時間: "+(getTimer()-timer)+" ms"); //分隔符要用那些沒有做在進制字符的 var my_data:String = max_w+","+max_h+"="; //trace(my_data); my_data += p_array.join(","); trace("字符長度:"+my_data.length); //字符長度 //我的測試數(shù)據(jù): //false:302419 //true:147174 //trace(my_data);
執(zhí)行時間不多,對于程序的有效行比較好。 大家可以看一下代碼的執(zhí)行效果
進階壓縮的原理:
引用: 'c,'c,'c,'c,'c,Eg,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,Eg, Eg,Eg,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,'c,
看到上面的數(shù)據(jù)了,對于重復的點,可以考慮這樣處理:
引用: 'c(5),Eg,'c(10),Eg,Eg,Eg,'c(15),
這個算法需要再對數(shù)組處理,本人未寫出,提高的壓縮比率是客觀的。 當然"()"需要在后期先處理,把"()"的多個字符先行恢復。
引用: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
對于上面字符,可以看出來,如果相片偏暗,以黑色為基點運算就好,相片偏亮,則適宜以白色為基點運算。
分段壓縮的算法效率不大,畢竟現(xiàn)在已經(jīng)是三個字符表示了,如果分區(qū)間,可以用兩個字符表示顏色,但是還要用一個字符表示區(qū)間。
圖片壓縮方法
相鄰的點的顏色一樣,采用"(個數(shù))"表示 如果顏色相差不大,差值為n,則在二維數(shù)組中進行比較,把某些點近似為該點,這樣就有更多的個數(shù)了,字符數(shù)量就更加少。
經(jīng)典論壇討論: http://bbs.blueidea.com/thread-2700451-1-1.html
出處:藍色理想
責任編輯:blue
◎進入論壇Flash專欄版塊參加討論
|