- 积分
- 136405
- 注册时间
- 2014-12-27
- 最后登录
- 2026-3-3
- 在线时间
- 606 小时
- 威望
- 562
- 贡献
- 29
- 金币
- 52905
- 钢镚
- 1422
- 交易凭证
- 1
- 分享
- 0
- 精华
- 33
- 帖子
- 2094
- 主题
- 1742
TA的每日心情 | 擦汗 2018-4-10 15:18 |
|---|
签到天数: 447 天 [LV.9]以坛为家II
超级版主
    
- 威望
- 562
- 贡献
- 29
- 金币
- 52905
- 钢镚
- 1422
 
|
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;//注意,是强制转换,不是new
- var 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实现的输出:
本文来自:http://www.cnblogs.com/176170847/archive/2011/01/27/1946222.html
|
|