守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 941|回复: 0

[基础入门] 实战Alchemy,Huffman的Alchemy实现

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51691
    钢镚
    1422

    开源英雄守望者

    发表于 2015-4-7 10:18:44 | 显示全部楼层 |阅读模式
    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最后加入
    1. export PATH=/cygdrive/D/java/flex_sdk_4.1.0.16076/bin:$PATH

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

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

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

    5. export FLEX_HOME=D:/java/flex_sdk_4.1.0.16076

    6. 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. 执行以下命令

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

    2. $ ./config

    3. Generating alchemy-setup...

    4. Turning execution bit on for Alchemy binaries...

    5. cygwin warning:

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

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

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

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

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

    11. ?

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

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

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

    15. ??"alc-off" restores original path.

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

    17. You need Flash 10 or AIR 1.5 and the Flex 3.2 SDK installed for testing.
    18. ?
    复制代码
    7. 测试一下以下命令:
    1. $ explorer .

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

    3. $ java -help

    4. $ perl --help

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

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

    3. $ gcc -v

    4. Using built-in specs.

    5. Target: i686-pc-cygwin

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

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

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

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

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

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

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

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

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

    15. Thread model: single

    16. gcc version 4.0.1 (Apple Computer, Inc. build 5449)
    复制代码
    可以看到alchemy官方版附带的gcc版本是4,用苹果机编译。

    ?

    ?

    ?

    ?

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

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

    ?

    ?

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

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

    ?

    ?

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

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

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

    ?

    ?
    1. package
    2. {
    3.   import flash.display.Sprite;
    4.   import flash.events.Event;
    5.   import flash.utils.ByteArray;
    6.   import flash.utils.Endian;
    7.   
    8.   /** * ... * @author  */
    9.   public class Main extends Sprite
    10.   {
    11.     import cmodule.huff.CLibInit;
    12.    
    13.     private static const clibinit:CLibInit = new CLibInit();
    14.     private static const hufflib:Object = clibinit.init();
    15.    
    16.     public function Main():void
    17.     {
    18.       if (stage)
    19.         init();
    20.       else
    21.         addEventListener(Event.ADDED_TO_STAGE, init);
    22.     }
    23.    
    24.     private function init(e:Event = null):void
    25.     {
    26.       removeEventListener(Event.ADDED_TO_STAGE, init);// entry point
    27.       
    28.       //--------------------------------------------------
    29.       
    30.       [Embed(source='../lib/output.dat', mimeType='application/octet-stream')]
    31.       var output_dat:Class;//注意,是强制转换,不是new
    32.       var data:ByteArray = ByteArray(new output_dat());
    33.       trace("ByteArray.length = ", data.length);
    34.       data.position = 0;//不知为何,与网络传输时正好相反
    35.       //0xFF000000 --readUnsignedInt--> 0xFF
    36.       data.endian = Endian.LITTLE_ENDIAN;  
    37.       if (data.bytesAvailable > 0)
    38.       {
    39.         // 第一个32位数是解压长度
    40.         var uncompress_length:uint = data.readUnsignedInt();
    41.         var inputdata:ByteArray = new ByteArray();
    42.         data.readBytes(inputdata);
    43.         trace("inputdata.bytesAvailable", inputdata.bytesAvailable);
    44.         trace("uncompress_length:", uncompress_length);
    45.         inputdata.position = 0;
    46.         //解码
    47.         var uncompress_bytes:ByteArray = huff_uncompress(inputdata, inputdata.bytesAvailable, uncompress_length);
    48.         uncompress_bytes.position = 0;
    49.         trace("uncompress:", uncompress_bytes.bytesAvailable, "bytes");
    50.         var str:String = uncompress_bytes.readMultiByte(uncompress_bytes.bytesAvailable, "gbk");
    51.         trace(str);
    52.       }
    53.       
    54.       //--------------------------------------------------
    55.       
    56.       //压缩测试
    57.       /*
    58.       var compress_length:uint = huff_compress_size();
    59.       trace("compress_length", compress_length);
    60.       */
    61.       /**/
    62.       uncompress_bytes.position = 0;
    63.       trace("uncompress_bytes.bytesAvailable:", uncompress_bytes.bytesAvailable);
    64.       var compress_bytes:ByteArray = huff_compress(uncompress_bytes, uncompress_bytes.bytesAvailable);
    65.       var compress_length:uint = huff_compress_size();compress_bytes.position = 0;
    66.       trace("compress_length:", compress_length);
    67.       trace("compress:", compress_bytes.bytesAvailable, "bytes");
    68.       compress_bytes.position = 0;
    69.       while (compress_bytes.bytesAvailable > 0)
    70.       {
    71.         var byte:uint = compress_bytes.readByte() & 0xff;
    72.         trace(byte.toString(16));
    73.       }
    74.       /**/
    75.     }
    76.     //对应huff.gg中的三个导出API
    77.     //方便参数类型检查
    78.     public function huff_uncompress(bytes:ByteArray, insize:int, outsize:int):ByteArray
    79.     {
    80.       return hufflib.huff_uncompress(bytes, insize, outsize);
    81.     }
    82.    
    83.     public function huff_compress(bytes:ByteArray, insize:int):ByteArray
    84.     {
    85.       //
    86.       trace("insize:", insize);
    87.       return hufflib.huff_compress(bytes, insize);
    88.     }
    89.    
    90.     public function huff_compress_size():int
    91.     {
    92.       return hufflib.huff_compress_size();
    93.     }
    94.   }
    95. }
    复制代码
    ?
    ?

    ?

    ?

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

    纯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



    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2019-8-20 21:42 , Processed in 0.040951 second(s), 31 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表