实战Alchemy,Huffman的Alchemy实现

huffman编码是常见的压缩算法之一,

例如我们平常看到的jpeg图片就是用huffman进行熵编码压缩。

?

我实现了huffman的alchemy版和AS3版两个版本。

纯AS3实现是把C算法完整地移植过去的(使用uint的Array数组模拟char[])

因为huffman算法在网上比较容易找到,我就不详细介绍。

下面只着重记录如何用Alchemy技术把huffman的API暴露到AS3,

然后与纯AS3实现的结果进行比较。

(这里说的huffman算法压缩后头四个字节为解压长度,压缩使用位流)

?

一、安装Alchemy。

Alchemy的安装方法以前已经说过,不过我是按照官方的做法再做了一次

(稍有不同的是我的alchemy不需要alc-on):

以下以windows xp+cygwin为开发环境(假设已经安装flex sdk和jdk)

1. 在adobe官方网站下载alchemy的cygwin二进制包。

?

2. 本地或在线安装cygwin,Select packages时选中make,perl、zip(不需要安装gcc,也不需要安装源代码)。

本地安装是cygwin把在线安装的文件缓存在硬盘中,最开始一般都是在线安装。

选择zip时要小心,不要选其它名字带zip的压缩工具。zip程序用于后面生成swc文件。

?

3. 启动cygwin的批处理文件Cygwin.bat,完成cygwin的全部安装。

?

4. 把alchemy的二进制文件解压到cygwin安装目录下

?

5. 在/etc/profile最后加入

export PATH=/cygdrive/D/java/flex_sdk_4.1.0.16076/bin:$PATH

export PATH=/cygdrive/D/java/jdk1.6.0_20/bin:$PATH

export PATH=/alchemy-cygwin-v0.5a/achacks:/alchemy-cygwin-v0.5a/bin:$PATH

export ALCHEMY_HOME=/alchemy-cygwin-v0.5a

export FLEX_HOME=D:/java/flex_sdk_4.1.0.16076

export ASC=C:/cygwin3/alchemy-cygwin-v0.5a/bin/asc.jar

注意:这里jdk、flex sdk的位置和alchemy的目录位置可变;

cygdrive用于转换windows的绝对路径;

冒号用于分割;

另外FLEX_HOME和ASC最好不要用cygdrive转换,因为它用于flex的jar文件定位,

windows下的java可能无法识别路径名而报错;

因为cygwin没有装gcc,所以我直接把achacks目录加入PATH(与官网的安装方法不一样,所以后面不需要alc-on那么麻烦)

把/etc/profile保存为Unix换行(注意:需要用特殊的编辑器编辑,我是使用Notepad2 MOD菜单中的“行末符号->Unix换行”保存)

重新启动cygwin控制台以使环境变量生效。

?

6. 执行以下命令

$ cd /alchemy-cygwin-v0.5a/

$ ./config

Generating alchemy-setup...

Turning execution bit on for Alchemy binaries...

cygwin warning:

??MS-DOS style path detected: C:/cygwin3/alchemy-cygwin-v0.5a/alchemy-setup

??Preferred POSIX equivalent is: /alchemy-cygwin-v0.5a/alchemy-setup

??CYGWIN environment variable option "nodosfilewarning" turns off this warning.

??Consult the user's guide for more details about POSIX paths:

?? ?http://cygwin.com/cygwin-ug-net/using.html#using-pathnames

?

Add "source /alchemy-cygwin-v0.5a/alchemy-setup" to your login script.

??"alc-home" takes you to the Alchemy install folder.

??"alc-on" puts Alchemy gcc toolchain replacements at the front of your path.

??"alc-off" restores original path.

??"alc-util" shows you various Alchemy-related environment vars

You need Flash 10 or AIR 1.5 and the Flex 3.2 SDK installed for testing.
?

7. 测试一下以下命令:

$ explorer .

$ mxmlc -help (如果无法运行,请确保jar的路径是windows的绝对路径,设置FLEX_HOME环境变量)

$ java -help

$ perl --help

$ zip --help

?

8. 测试gcc是否正常:(不需要alc-on,是因为我已经把alchemy的gcc加入了PATH,而且cygwin中并没有装真正的gcc)

$ which gcc

/alchemy-cygwin-v0.5a/achacks/gcc

$ gcc -v

Using built-in specs.

Target: i686-pc-cygwin

Configured with: /home/anon/llvm-gcc4.0-2.1.source/configure ?: (reconfigured) /

home/anon/llvm-gcc4.0-2.1.source/configure ?: (reconfigured) /home/anon/llvm-gcc

4.0-2.1.source/configure --disable-libgcj --disable-libjava : (reconfigured) ../

../src/llvm-gcc4/configure --prefix=/home/anon/llvm-gcc4 --disable-threads --dis

able-nls --disable-shared --enable-languages=c,c++ --disable-c-mbchar --program-

prefix=llvm- --enable-llvm=/home/anon/src/llvm : (reconfigured) /home/anon/src/l

lvm-gcc4/configure --prefix=/home/anon/llvm-gcc4 --disable-threads --disable-nls

?--disable-shared --enable-languages=c,c++ --disable-c-mbchar --program-prefix=l

lvm- --enable-llvm=/home/anon/src/llvm

Thread model: single

gcc version 4.0.1 (Apple Computer, Inc. build 5449)

可以看到alchemy官方版附带的gcc版本是4,用苹果机编译。

?

?

?

?

二、编写代码编译运行,比较Alchemy和AS3实现的结果。

为了简单起见忽略huffman压缩和解压算法的实现代码。

?

?

Alchemy的API导出文件(.gg文件)

---------------------------

?

?

{/*    注意用大括号包含C代码,   一些通常用到的C函数定义,方便C和AS3的类型转换*/

----------------------------------------------

Alchemy实现的主入口代码如下:

?

?

package {import flash.display.Sprite;import flash.events.Event;import flash.utils.ByteArray;import flash.utils.Endian;/** * ... * @author  */public class Main extends Sprite {import cmodule.huff.CLibInit;private static const clibinit:CLibInit = new CLibInit();private static const hufflib:Object = clibinit.init();public function Main():void {if (stage) init();else addEventListener(Event.ADDED_TO_STAGE, init);}private function init(e:Event = null):void {removeEventListener(Event.ADDED_TO_STAGE, init);// entry point//--------------------------------------------------[Embed(source='../lib/output.dat', mimeType='application/octet-stream')]var output_dat:Class;//注意,是强制转换,不是newvar data:ByteArray = ByteArray(new output_dat());trace("ByteArray.length = ", data.length);data.position = 0;//不知为何,与网络传输时正好相反//0xFF000000 --readUnsignedInt--> 0xFF data.endian = Endian.LITTLE_ENDIAN;  if (data.bytesAvailable > 0){// 第一个32位数是解压长度var uncompress_length:uint = data.readUnsignedInt();var inputdata:ByteArray = new ByteArray();data.readBytes(inputdata);trace("inputdata.bytesAvailable", inputdata.bytesAvailable);trace("uncompress_length:", uncompress_length);inputdata.position = 0;//解码var uncompress_bytes:ByteArray = huff_uncompress(inputdata, inputdata.bytesAvailable, uncompress_length);uncompress_bytes.position = 0;trace("uncompress:", uncompress_bytes.bytesAvailable, "bytes");var str:String = uncompress_bytes.readMultiByte(uncompress_bytes.bytesAvailable, "gbk");trace(str);}//--------------------------------------------------//压缩测试/*var compress_length:uint = huff_compress_size();trace("compress_length", compress_length);*//**/uncompress_bytes.position = 0;trace("uncompress_bytes.bytesAvailable:", uncompress_bytes.bytesAvailable);var compress_bytes:ByteArray = huff_compress(uncompress_bytes, uncompress_bytes.bytesAvailable);var compress_length:uint = huff_compress_size();compress_bytes.position = 0;trace("compress_length:", compress_length);trace("compress:", compress_bytes.bytesAvailable, "bytes");compress_bytes.position = 0;while (compress_bytes.bytesAvailable > 0){var byte:uint = compress_bytes.readByte() & 0xff;trace(byte.toString(16));}/**/}//对应huff.gg中的三个导出API//方便参数类型检查public function huff_uncompress(bytes:ByteArray, insize:int, outsize:int):ByteArray{return hufflib.huff_uncompress(bytes, insize, outsize);}public function huff_compress(bytes:ByteArray, insize:int):ByteArray{//trace("insize:", insize);return hufflib.huff_compress(bytes, insize);}public function huff_compress_size():int{return hufflib.huff_compress_size();}}}
?
?

?

?

-------------------------------------------------

纯AS3实现的主入口代码如下:

?

?

?

package huff {import flash.display.Sprite;import flash.utils.ByteArray;import flas两种实现的输出如下所示,

* 解压出"Hello World!",

* 压缩除了alchemy没有加入开头4字节的长度外,其余和AS3版相同。

?

---------------------

alchemy实现的输出:

posted on 2011-01-27 14:53  低调的沧桑  阅读(1101)  评论(0编辑  收藏  举报

导航