2005年9月30日 星期五

ActionScript LZW 壓縮相關資源   [+/-]

Ticore's Blog

一些ActionScript LZW壓縮解壓縮的資源:

LZW Algorithms:

其實 Flash 8 ActionScript LZW 幾百 kb 的資料,速度還算 OK
不過千萬不要貿貿然地,就把程式 copy 去用
建議多K一下 HTTP 規格以及 Flash Doc 再來用
免得資料傳輸量沒減少,反而暴增~~

以下是直接從AS版的LZW改成Java版的LZW:

 package idv.ticore.compress;
 import java.util.*;
 
 public class LZW {
     private static boolean xmlsafe = false;
     private LZW() {
     }
     public static String compress(String str) {
         
         Map dico = new HashMap();
         int skipnum = xmlsafe ? 5 : 0;
         for (char i = 0 ; i < 256 ; ++i) {
             dico.put(Character.toString(i), new Character(i));
         }
         if (xmlsafe) {
             dico.put("<", new Character((char)256));
             dico.put(">", new Character((char)257));
             dico.put("&", new Character((char)258));
             dico.put(""", new Character((char)259));
             dico.put(""", new Character((char)260));
         }
         String res = "";
         String txt2encode = str;
         String[] splitStr = txt2encode.split("");
         int len = splitStr.length;
         int nbChar = 256 + skipnum;
         String buffer = "";
         
         for (int i = 1; i <= len; i++) {
             String current;
             if(i <= len - 1) {
                 current = splitStr[i];
             } else {
                 current = null;
             }
             if(dico.get(buffer + current) != null) {
                 buffer += current;
             } else {
                 res += ((Character)dico.get(buffer)).toString();
                 
                 dico.put(buffer + current, new Character((char)nbChar));
                 nbChar++;
                 buffer = current;
             }
         }
         return res;
     }
     
     public static String decompress(String str) {
         Map dico = new HashMap();
         int skipnum = xmlsafe ? 5 : 0;
         for (int i = 0 ; i < 256 ; ++i) {
             dico.put(Integer.toString(i), Character.toString((char)i));
         }
         if (xmlsafe) {
             dico.put("256", "<");
             dico.put("257", ">");
             dico.put("258", "&");
             dico.put("259", """);
             dico.put("260", """);
         }
         String txt2encode = str;
         String[] splitStr = txt2encode.split("");
         int len = splitStr.length;
         int nbChar = 256 + skipnum;
         String buffer = "";
         String chaine = "";
         String res = "";
         
         for (int i = 1; i < len; i++) {
             int code = txt2encode.charAt(i - 1);
             String current = (String)dico.get(Integer.toString(code));
             if (buffer == "") {
                 buffer = current;
                 res += current;
             } else {
                 if (code <= 255 + skipnum) {
                     res += current;
                     chaine = buffer + current;
                     dico.put("" + nbChar, chaine);
                     nbChar++;
                     buffer = current;
                 } else {
                     chaine = (String)dico.get("" + code);
                     if (chaine == null) {
                         chaine = buffer + buffer.substring(0, 1);
                     }
                     res += chaine;
                     dico.put("" + nbChar, buffer + chaine.substring(0, 1));
                     nbChar++;
                     buffer = chaine;
                 }
             }
         }
         return res;
     }
 }

相關連結:
ActionScript Huffman、LZ77壓縮相關資源

Read more...

2005年9月27日 星期二

覆寫 AS2 Number.toString() 函式   [+/-]

Ticore's Blog

上次 Po 過 Flash ActionScript 的 Number.toString() 有 Bug (Flash 數字進位轉換Bug)
所以寫了一個函式覆寫原始的 toString
要考慮到能夠適用於 2 ~ 32 所有的進位

不只是用於 16、32 進位~~
最後想到以下的方式來做
居然只有四行就可以完成,比一開始的寫法少很多,真是出乎意料


/*
  Ticore's Blog
  http://ticore.blogspot.com/
*/
Number.prototype.__toString = Number.prototype.toString;
Number.prototype.toString = function(radix) {
 return (Number(this) > radix ? (this / radix)["__toString"](radix) : "") +
    (this % radix)["__toString"](radix);
};
//
trace(0xFFFF0090.toString(5));
trace(0x90000090.toString(5));
trace(0x00090.toString(5));
trace(0xFFFF.toString(5));
trace(0x0.toString(5));
//
trace(0xFFFF0090.toString(8));
trace(0x90000090.toString(8));
trace(0x00090.toString(8));
trace(0xFFFF.toString(8));
trace(0x0.toString(8));
//
trace(0xFFFF0090.toString(16));
trace(0x90000090.toString(16));
trace(0x00090.toString(16));
trace(0xFFFF.toString(16));
trace(0x0.toString(16));
//
Read more...

2005年9月26日 星期一

Flash 8 AS2 數字進位轉換 Bug   [+/-]

Ticore's Blog

由於新功能 BitmapData 出現
最近嘗試使用它來做一些資料轉換
常常用到 getPixel32
為了減少資料長度
把它轉成 16 或是 32 進位
一旦來源數字大小超過 0x80000000
轉換就會出現奇怪的字元

居然會出現以下的結果:

/*
  Ticore's Blog
  http://ticore.blogspot.com/
*/
trace(0x80000000.toString(16));
trace(0x80000000.toString(32));
trace(0x80000001.toString(16));
trace(0x80000001.toString(32));
// output:
// -(0000000
// -.000000
// -7fffffff
// -1vvvvvv

以前的版本好像也有一樣的狀況
只不過以前很少需要用到 32bit 整數轉換吧
javascript 與 actionscript 是很類似的東西
為什麼 javascript 就可以出現正確的結果~

相關連結:覆寫 AS2 Number.toString() 函式

Read more...

2005年9月21日 星期三

Flash 8 AS2 點陣圖雙線性取樣函式   [+/-]

Ticore's Blog

既然 Flash 8 可以直接操作點陣資料
那就可以用來實作一些影像處理的功能了
以下便是用 AS 作點陣圖雙線性重新取樣函式

不過這只是個人研究用的
畢竟AS跑大量迴圈還是比不上 Native 程式
所以並不具有實用的價值

真正欲做點陣圖縮放,可以使用 Matrix + draw
至少比 AS Implement 的快上100倍

/*
  Ticore's Blog
  http://ticore.blogspot.com/
*/
import flash.display.*;
import flash.geom.*;

//=======================================================================

function resizeTo(width:Number, height:Number, img:BitmapData):BitmapData {
var temp:BitmapData = new BitmapData(width, height, true, 0xFF000000);

var p0:Point = new Point();
var p1:Point = new Point();
var p2:Point = new Point();
var p3:Point = new Point();
var p4:Point = new Point();

var c1:Number;
var c2:Number;
var c3:Number;
var c4:Number;

var a:Number;
var r:Number;
var g:Number;
var b:Number;

var dx:Number;
var dy:Number;
var cdx:Number;
var cdy:Number;

var dtl:Number;
var dtr:Number;
var dbl:Number;
var dbr:Number;

for(var i:Number = 0 ; i < width ; ++i){
for(var j:Number = 0 ; j < height ; ++j){
p0.x = i / width * (img.width -1);
p0.y = j / height * (img.height - 1);
p1.x = Math.floor(p0.x);
p1.y = Math.floor(p0.y);
p2.x = p1.x + 1;
p2.y = p1.y;
p3.x = p1.x + 1;
p3.y = p1.y + 1;
p4.x = p1.x;
p4.y = p1.y + 1;

c1 = img.getPixel32(p1.x, p1.y);
c2 = img.getPixel32(p2.x, p2.y);
c3 = img.getPixel32(p3.x, p3.y);
c4 = img.getPixel32(p4.x, p4.y);

dx = p0.x - p1.x;
dy = p0.y - p1.y;
cdx = 1 - dx;
cdy = 1 - dy;

dtl = dx * dy;
dtr = cdx * dy;
dbr = dx * cdy;
dbl = cdx * cdy;

a = ((c1 & 0xFF000000) * dbl
+ (c2 & 0xFF000000) * dbr
+ (c3 & 0xFF000000) * dtl
+ (c4 & 0xFF000000) * dtr) & 0xFF000000;

r = ((c1 & 0x00FF0000) * dbl
+ (c2 & 0x00FF0000) * dbr
+ (c3 & 0x00FF0000) * dtl
+ (c4 & 0x00FF0000) * dtr) & 0x00FF0000;

g = ((c1 & 0x0000FF00) * dbl
+ (c2 & 0x0000FF00) * dbr
+ (c3 & 0x0000FF00) * dtl
+ (c4 & 0x0000FF00) * dtr) & 0x0000FF00;

b = ((c1 & 0x000000FF) * dbl
+ (c2 & 0x000000FF) * dbr
+ (c3 & 0x000000FF) * dtl
+ (c4 & 0x000000FF) * dtr) & 0x000000FF;

temp.setPixel32(i , j , a | r | g | b);
}
}
return temp;
}

//=======================================================================
Read more...

2005年9月10日 星期六

AS字串取代函式   [+/-]

Ticore's Blog

AS字串取代函式
//=====================================================================================
// 字串取代函式
// replace(來源字串:String, 原始字串:String, 目標字串:String[, 取代數目:Number[, 是否逆向:Boolean]])
// 回傳值:取代結果字串
//=====================================================================================
var replace:Function = function (str:String, a:String, b:String, n:Number, reverse:Boolean) {
 var counter:Number = 0;
 var index:Number = !reverse ? -1 : str.length;
 if (!isNaN(n)) {
  while (counter<=n) {
   index = !reverse ? str.indexOf(a, index+1) : str.lastIndexOf(a, index-1);
   if (index>-1) {
    counter++;
   } else {
    return str.split(a).join(b);
   }
  }
  return !reverse ? str.slice(0, index).split(a).join(b) +
    str.slice(index, str.length) : str.slice(0, index+1) +
    str.slice(index+1, str.length).split(a).join(b);
 } else {
  return str.split(a).join(b);
 }
};
trace(replace("xx", "xx", "-----") == "-----");
var str:String = "12312312";
trace(replace(str, "123123", "-----", 4) == "-----12");
trace(replace(str, "12", "-----", 4) == "-----3-----3-----");
trace(replace(str, "2", "-----", 4, true) == "1-----31-----31-----");
trace(replace(str, "1", "-----", 3) == "-----23-----23-----2");
trace(replace(str, "12", "-----", 3, true) == "-----3-----3-----");
trace(replace(str, "1", "-----", 2) == "-----23-----2312");
trace(replace(str, "12", "-----", 2, true) == "123-----3-----");
trace(replace(str, "1", "-----", 1) == "-----2312312");
trace(replace(str, "12", "-----", 1, true) == "123123-----");
trace(replace(str, "1", "-----", 0) == "12312312");
trace(replace(str, "2", "-----", 0, true) == "12312312");
Read more...

2005年9月8日 星期四

Array.prototype function 與 V2 Component 的問題   [+/-]

Ticore's Blog

狀況描述:
自行定義 Array.prototype.xxx 原型函式之後
在使用 V2 UI Component 時
會不時自動呼叫該原型函式

原因:
V2 UI Component使用 mx.events.EventDispatcher
而 EventDispatcher 使用 Array 儲存 quene
EventDispatcher 在依序執行quene的時候是使用 for...each 方式跑迴圈
這會連 Array 的原型函式一起被執行

解決方式:
找到 EventDispatcher.as 中的 function dispatchQueue
將 for (i in queue)
改為 for (var i = 0 ; i < queue.length ; ++i)

還有另外一種方式,就是使用密技
把要新增的 prototype function 設為不可列舉的屬性

Read more...

2005年9月7日 星期三

Hotspot Demo Video 2   [+/-]

Ticore's Blog

這是利用Flash 8新功能BitmapData處理功能加上WebCam作出來的

利用雷射筆光源的開啟、關閉、移動
觸發事件
達到互動的效果

畫面上的三個MovieClip先對Hotspot註冊事件
才能接受Hotspot的事件呼叫
進行互動

Hotspot分析點陣資料之後
計算出雷射筆的位置
換算座標
最後發布事件

Read more...

OpenAMF - 自訂類別轉換對照   [+/-]

Ticore's Blog

OpenAMF - Custom Class Mapping

要看這篇文章,先要對Remoting有些概念
Remoting是可以讓Flash AS程式與異質(heterogeneric)程式語言直接溝通的介面
也就是讓AS可以直接與其他程式語言進行溝通、呼叫、傳遞物件
可以省去大量的資料解析的動作

由於不同程式語言的基礎型別都不太一樣
所以會有一個物件對照表
方便資料在不同程式中傳遞時進行轉換的動作
預設的物件對照僅包含基礎型別的物件與常用的容器型別

傳遞其他類別物件的時候
仍然必須自行作少量的資料解析動作
自訂類別轉換可以補足此一缺憾

因為OpanAMF是開放原始碼的計畫
而且又是連結Java平台介面
功能遠比其他版本的Remoting來得強大

以下就用OpenAMF介紹自訂類別轉換的功能

1.設定類別對照

找出OpenAMF設定檔

[WebApp]/WEB-INF/openamf-config.xml 在config結點內加入以下XML設定:
<custom-class-mapping>
 <java-class>idv.swl.remoting.myClass</java-class>
 <custom-class>idv.swl.remoting.myClass</custom-class>
</custom-class-mapping>

這樣就可以將Server端的Java Class: idv.swl.remoting.myClass
與Flash端的AS Class:idv.swl.remoting.myClass完成對照

2.撰寫Flash AS Class

myClass.as:

class idv.swl.remoting.myClass {
 var count:Number;
 var log:String;
 function myClass() {
 }
 function doTrace() {
  trace("count : "+count);
  trace("log : "+log);
 }
}

3.撰寫Server Java Class

Java Class要依循JavaBean的撰寫規範
才能進行序列化、反序列化的動作

myClass.java:

package idv.swl.remoting;

public class myClass implements java.io.Serializable {
    
    public int count;
    public String log;

    public myClass() {
    }
    
    public void setCount(int count) {
        this.count = count;
    }
    public int getCount() {
        return count;
    }
    
    public void setLog(String log) {
        this.log = log;
    }
    public String getLog() {
        return log;
    }
    
    public void doTrace() {
        System.out.println("count : " + count);
        System.out.println("log : " + log);
    }
}

4.撰寫測試程式

以下的測試程式是將自訂類別(myClass)物件在Client-Server之間互丟
並執行myClass for Java and AS的function 直到myClass.count計數器累加到3

Server Class:

package idv.swl.remoting;
public class server {
    
    public static myClass process(myClass obj) {
        obj.count++;
        obj.log += "java processing at " + new Date() + "n";
        obj.doTrace();
        return obj;
    }
    
}

Flash AS in Frame 1:
//==================================================
import idv.swl.remoting.myClass;
Object.registerClass("idv.swl.remoting.myClass", idv.swl.remoting.myClass);
//==================================================
var nc:NetConnection = new NetConnection();
nc.onResult = function(data) {
 trace("onResult : ");
 data.doTrace();
 if (data.count<3) {
  data.log += "Flash processing at "+new Date()+"n";
  nc.call("idv.swl.remoting.server.process", nc, data);
 }
};
nc.onStatus = function(data) {
 trace("onStatus : ");
 for (var i in data) {
  trace(i+" : "+data[i]);
 }
};
nc.connect("http://localhost:8084/RemotingTest/gateway");
//==================================================
var obj:myClass = new myClass();
obj.log = "";
obj.count = 0;
nc.call("idv.swl.remoting.server.process", nc, obj);

Flash Output:
onResult : 
count : 1
log : java processing at Mon Apr 04 14:55:03 CST 2005

onResult : 
count : 2
log : java processing at Mon Apr 04 14:55:03 CST 2005
Flash processing at Mon Apr 4 14:55:03 GMT+0800 2005
java processing at Mon Apr 04 14:55:03 CST 2005

onResult : 
count : 3
log : java processing at Mon Apr 04 14:55:03 CST 2005
Flash processing at Mon Apr 4 14:55:03 GMT+0800 2005
java processing at Mon Apr 04 14:55:03 CST 2005
Flash processing at Mon Apr 4 14:55:03 GMT+0800 2005
java processing at Mon Apr 04 14:55:03 CST 2005
Read more...

2005年9月6日 星期二

Remoting by NetConnection   [+/-]

Ticore's Blog

一般在使用Flash Remoting功能的時候
都是安裝Remoting Library AS1、AS2 Component來用
其實是可以直接用NetConnection呼叫Remoting的

因為AMF在Flash Player中的Serialize、Deserialize動作
都是透過NetConnection於底層完成,並非寫在AS
就是因為寫在底層,所以AMF會比其他格式來得更有效率

NetConnection具有兩種連線方式,決定於要連線URL通訊協定
對FlashCom RTMP連線是像Socket持續性即時連線
對Remoting Server HTTP則是非持續性連線

不過兩者都是以AMF格式作序列化

以下示範用NetConnection呼叫Remoting方式:

ActionScript Code:

/*
  Ticore's Blog
  http://ticore.blogspot.com/
*/
var nc:NetConnection = new NetConnection();
var url:String = "http://192.168.0.10:8084/FlashRemoting/gateway";
var lisObj:Object = {};
lisObj.onResult = function(data) {
        trace("onResult : "+data);
};
nc.onStatus = function(info) {
        trace("onStatus : "+info);
        for (var i in info) {
                trace("info["+i+"] : "+info[i]);
        }
};
nc.connect(url);
nc.call("swl.NewClass.Test", lisObj, 11);
//output: onResult : Test() with Number : 11.0

 

Java Class Code:

/*
  Ticore's Blog
  http://ticore.blogspot.com/
*/
package swl;
public class NewClass {
    
    public NewClass() {
    }
    
    public java.util.Map Test(java.util.Map map) {
        return map;
    }
    public String Test(java.util.ArrayList arraylist) {
        return "Test() with ArrayList : " + arraylist;
    }
    public String Test(String str) {
        return "Test() with String : " + str;
    }
    public String Test(String[] str) {
        return "Test() with String Array : " + str;
    }
    public String Test(Number num) {
        return "Test() with Number : " + num;
    }
    public String Test(boolean bo) {
        return "Test() with boolean : " + bo;
    }
    public String Test() {
        return "Test() no arguments";
    }
}
Read more...

2005年9月5日 星期一

12 Coins Puzzle 系統性解法   [+/-]

Ticore's Blog

問題:

有 12 個錢幣,其中一個是假的,不知道是比較重還是比較輕,你可以利用天秤秤三次,辨別出哪個是假的,並且得知這個假的錢幣是比較重或比較輕。

解答:

先將 12 枚硬幣以英文字母編號
以下列方式來秤



天秤左邊
天秤右邊
不秤
第一次
C D E K
F G H L
A B I J
第二次 B D F J E G I K A C H L
第三次 A E F L D H I J B C G K

將秤出來的結果查表,即可得知

結果 A重 A輕 B重 B輕 C重 C輕 D重 D輕 E重 E輕 F重 F輕 G重 G輕 H重 H輕 I重 I輕 J重 J輕 K重 K輕 L重 L輕
第一次
第二次
第三次

這樣的解法,沒有瑣碎的 if (...) {...} else {...}
極適合用於電腦程式的AI上

而且這樣做的話,可以一對多,同時猜測多個對象的答案
不需要針對不同的狀況,進行下一步出牌的推理運算

這樣簡單的公式背後是具有相當複雜的理論
但是相當具有系統性
假如連公式推導都系統化,甚至是不需要把這公式Hard Coding在程式內
也不需要限制12枚硬幣
可以動態依據硬幣數目推導出最少的次數

至於這樣的解法背後的意義以及推法,下次再POST....

相關連結:
12 枚硬幣秤重 - 公式解推導方式 (1)
12 枚硬幣秤重 - 公式解推導方式 (2)

Read more...