请选择 进入手机版 | 继续访问电脑版
收藏本站腾讯微博新浪微博
点点网模板设计大赛 phpchina

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 用悬赏 三天解决问题 解决访问速度慢 论坛支持农历生日 - 给官方提建议

论坛活动及任务 归纳网站最新活动 地图任务 邮件更新任务:保护帐号安全

积分换实物,来参加蓝色理想积分兑换吧! 联系招聘客服 蓝色理想帮你找工作! 万元奖励等你拿——点点网模板设计大赛

查看: 32360|回复: 60

[AS1&2] Flash AS2 中的拍照图片传输量太大的解决思路 [复制链接]

FlashK 楼主
帖子
553
体力
2405
威望
82
发表于 2006-11-24 18:12:28 |显示全部楼层
原理就是将flash中BitmapData中得到的RGB编码成字符串(XML),然后在服务器端进行反解码。

可惜我不会服务器端的,有兴趣的可以来玩玩~`
开始。
我们利用Flash的Bitmap来抓拍一个当前MC中的位图数据,然后输出。
ActionScript:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=NUM10 ]";
  7. for (var i = 1; i<myBitmap.height; i++) {
  8.         for (var j = 1; j<myBitmap.width; j++) {
  9.                 data += myBitmap.getPixel(i, j)+",";
  10.         }
  11. }
  12. trace(data);
复制代码

这样你就得到了类似下面的数据输出:
============
[bitmap width=400 height=300 sendBy=Flash Encode=NUM10 ]
16728576,16728576,16730112,16730112,16731648,16731648,16733440,16734976,16734976,16736512,16736512,16738048,16739584,16739584,16741120,16741120,16742656,16744192,16744192,16745728,16745728,16747264,16748800,16748800,16750336,16750336,16751872,16751872,16753408,16755200,16755200,16756736,16756736,16758272,16759808,16759808,16761344,16761344,16762880,16764416,16764416,16765952,16765952,16767488,16769024,16769024,16770560,16770560,16772096,16772096,16773632,16775168,16775168,16776960,16776960,16449280,16121600,16121600,15793920,16728576,16730112,16730112,

这样每一个以“,”分隔就是每一个像素的RGB值。(其实“,”分隔符是可以去掉的,也不必去标明每个像素位置,因为位图数据都是以一行一行的流记录的,每个像素占的字节数也是相同,记得以前学设计的时候书上好像是这么说的。。)
(这里为了可读性,没有去掉“,”分隔符,实际用的时候你将它去掉,下同)
事实上这样的数据量是很大的,以一个二进制文件为例,对比一下,一个二进制的60*60的bmp文件是11K左右,而以这样的数据来保存的文件在28K左右。差不多是3倍。而一个320*240的图像则会达到600多K,400*300则可能会到1M左右(这是不可想象的...)

其实这些数据都是以字符串发送的,它并不是数字或者二进制,而Flash又只能发送字符串(其它网页的东东好像也一样),那怎么办呢?
那就要换个思路了,我们要充分利用字符串。(其实字符串也是以二进制在网上传输的)
我们知道字符串不只只是只有0-9这几个数字。也就是说一个超过10的数字,你也能在字符串里找到一个和它对应的字符。这就是将RGB数值映射到字符串中去。一个字符就可以表示10以外的数,这样一来就可以减小文件大小。

我们来改一下我们的ActionScript:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=NUM16 ]";
  7. for (var i = 1; i<myBitmap.height; i++) {
  8.         for (var j = 1; j<myBitmap.width; j++) {
  9.                 data += myBitmap.getPixel(i, j).toString(16)+",";
  10.         }
  11. }
  12. trace(data);
复制代码


这次我们得到了一个带字母的输出:
==============
[bitmap width=400 height=300 sendBy=Flash Encode=NUM16 ]
ff4200,ff4200,ff4800,ff4800,ff4e00,ff4e00,ff5500,ff5b00,ff5b00,ff6100,ff6100,ff6700,ff6d00,ff6d00,ff7300,ff7300,ff7900,ff7f00,ff7f00,ff8500,ff8500,ff8b00,ff9100,ff9100,ff9700,ff9700,ff9d00,ff9d00,ffa300,ffaa00,ffaa00,ffb000,ffb000,ffb600,ffbc00,ffbc00,ffc200,ffc200,ffc800,ffce00,ffce00,ffd400,ffd400,ffda00,ffe000,ffe000,ffe600,ffe600,ffec00,ffec00,fff200,fff800,fff800,ffff00,ffff00,faff00,f5ff00,f5ff00,f0ff00,ff4200,ff4800,ff4800,ff4e00,ff5500,ff5500,ff5b00,ff5b00,

做过网页的朋友应该很清楚。这个就是网页颜色的十六进制码。我们用了一个Flash内置的函数toString(16)将得到的RGB数字转成带字母A,B,C、D,E,F的十六进制字符。
在十六进制中,字母A-F表示10-15这6个数。

对比一下刚刚的数据。16728576它占了8个字符。这次我们ff4200只用了6个字符就表示了它(这个可以反过来还原成刚刚的数),这样一来数据大小就减小了1/4。

[ 本帖最后由 FlashK 于 2006-11-25 00:38 编辑 ]
已有 1 人评分威望 收起 理由
mirycat + 4 精品文章

总评分: 威望 + 4   查看全部评分

欢迎来我的全Flash站收藏:http://www.flashk3.com/
西部数码顶级域名注册商39元抢注!
FlashK 楼主
帖子
553
体力
2405
威望
82
发表于 2006-11-24 23:29:29 |显示全部楼层
再来改进一下我们的ActionScript:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]";
  7. for (var i = 1; i<myBitmap.height; i++) {
  8.         for (var j = 1; j<myBitmap.width; j++) {
  9.                 var num = myBitmap.getPixel(i, j);
  10.                 data += String.fromCharCode(num);
  11.         }
  12. }
复制代码


这次我们用了Number内置的toString(36)的来将我们的RGB数字转成由0-9和A-Z共36种字符表示的字符串。
(为什么用内置的是因为它比较快,也方便)

现在的输出是这样子的:
========
[bitmap width=400 height=300 sendBy=Flash Encode=NUM36 ]
9yjuo,9yjuo,9yl1c,9yl1c,9ym80,9ym80,9ynls,9yosg,9yosg,9ypz4,9ypz4,9yr5s,9yscg,9yscg,9ytj4,9ytj4,9yups,9yvwg,9yvwg,9yx34,9yx34,9yy9s,9yzgg,9yzgg,9z0n4,9z0n4,9z1ts,9z1ts,9z30g,9z4e8,9z4e8,9z5kw,9z5kw,9z6rk,9z7y8,9z7y8,9z94w,9z94w,9zabk,9zbi8,9zbi8,9zcow,9zcow,9zdvk,9zf28,9zf28,9zg8w,9zg8w,9zhfk,9zhfk,9zim8,9zjsw,9zjsw,9zl6o,9zl6o,9skcg,9lji8,9lji8,9eio0,9yjuo,9yl1c,9yl1c,9ym80,

这一次我们只用了五个字符来表示刚刚8个表示的RGB值。(比十六制的还要少)

还能不能再压缩呢?当然还能,事实上,应该可以达到和二进制文件一样的大小。

我们知道字符串在Flash中是以UTF-8传递的(还记得Flash6的那个乱码问题吗,当时确实很头疼的,不过现在8用起来不错)
怎么样将RGB数字编码成UTF-8字符串呢?幸好Flash还有个fromCharCode(num);它将返回一个由参数中的 Unicode 值表示的字符组成的字符串。

ActionScript:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=60 height=60 ]";
  7. for (var i = 1; i<myBitmap.height; i++) {
  8.         for (var j = 1; j<myBitmap.width; j++) {
  9.                 var num = myBitmap.getPixel(i, j);
  10.                 data += String.fromCharCode(num)+",";
  11.         }
  12. }
  13. trace(data);
复制代码


现在输出:
===============
[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]
唔,吓,䬍,䐇,㨁,㐁,㐁,㄀,㄀,⸀,⸀,㜀,㔁,㔇,㐉,ㄏ,】,⨊,☂,⌀,␀,⌀,␄,⌂,␀,━,│,┇,☂,✃,⠅,☃,␄,⌅,␁,␀,⨅,⨆,∄,∆,┑,Ḉ,᠂, , ,⌈,∆,℅,ḃ,ἃ,ἃ,℄, ,ḃ,ᴃ,ἃ,ἀ,∁,⬋,圓,嘕,吔,匓,刔,伔,伔,䰑,䨏,䜎,䜎,䌍,㤊,㈆,Ⰵ,★,☇,⤆,⨆,✂,␀,⠆,Ⰶ,⸅,⼄,㈅,㈈,㌍,㘔,㈐,⤇,✅,☄,⌁,✉, ,␄,☈,Ⱃ,㌛,躁,邁,楘,⠓,␏,Ἄ,ḋ,Ḋ,ḅ, ,℅,∅, ,∆,┇,⨉,㈌,『,㌒,圉,吒,吒,唎,后,刑,不,不,們,䨑,䜎,丘,㴊, ,⨀,ⴃ,⨃,␀,⤄,ⴉ,⸉,⼊,ㄋ,㌍,㐊,㐈,㐊,ㄉ,㘐,ⴇ,☂,✃,⌃,┅,⠂,⤋,☆,⤆,⬓,幐,뚵,웄,릵,癮,剆,⨙,‍,ᜂ,┍,Ḇ,ᤁ, ,⌇,✇,

这里我们将RGB的颜色转成一个Unicode的字符串。这样就将每个像素的RGB映射到了一个字符串中。
(事实上我对能不能将16777215色彩映射到UTF-8中感到有怀疑,回头好好研究一下)

这段代码在我的P4 2.8G上面运行了3842ms左右的时间。而FlashPlayer的用户则可能会更慢(因为普通用户的电脑可能会差一点,而且Flash也不可能多台电脑一起,速度至上啊,是不是)。
我们的用户可能要花上7-10秒(视CPU速度,它的运算量是一定的)的时间来完成上面的运算。太慢了,是不是?

让我们来好好优化一下代码来提高速度:
ActionScript改成这样:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]";
  7. for (var i = 1; i<300; i++) {
  8.         for (var j = 1; j<400; j++) {
  9.                 var num = myBitmap.getPixel(i, j);
  10.                 data += String.fromCharCode(num);
  11.         }
  12. }
复制代码


或者:

  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]";
  7. var width = myBitmap.width;
  8. var height = myBitmap.height;
  9. for (var i = 1; i<height; i++) {
  10.         for (var j = 1; j<width; j++) {
  11.                 var num = myBitmap.getPixel(i, j);
  12.                 data += String.fromCharCode(num);
  13.         }
  14. }
复制代码


这一次,我们将运算速度提到了3599ms左右。你也可以在你的电脑上试试。

如果有人不知道如何测试代码运算速度,可以看看这个。就以上面的代码为例:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]";
  7. timer = getTimer();
  8. for (var i = 1; i<300; i++) {
  9.         for (var j = 1; j<400; j++) {
  10.                 var num = myBitmap.getPixel(i, j);
  11.                 data += String.fromCharCode(num);
  12.         }
  13. }
  14. trace(getTimer()-timer);
复制代码

[ 本帖最后由 FlashK 于 2006-11-26 14:25 编辑 ]
欢迎来我的全Flash站收藏:http://www.flashk3.com/
租服务器,上51IDC | [长沙]招聘:PHP经理10K/WEB前端6K/PHP开发6K

使用道具 举报

kvgnt 
帖子
532
体力
2072
威望
1
居住地
福建省 泉州市
发表于 2006-11-24 23:54:59 |显示全部楼层
期待。。。
http://blog.csdn.net/kvgnt

使用道具 举报

我是棉花糖

银牌会员

帖子
936
体力
2563
威望
6
发表于 2006-11-25 00:40:01 |显示全部楼层
LZW 是一种无损压缩算法,GIF格式就是采用此种压缩算法。用楼主的原始数据经过 LZW for AS2 算法压缩后,只有原始尺寸的 1/3。

P.S: AS3 的 ByteArray 内已经内建了对 ZLIB 算法的支持,ZLIB 算法是 LZ77(即 LZW)算法的变种,被应用于 PNG 格式的压缩算法中。

[ 本帖最后由 abc12hjc 于 2006-11-25 00:43 编辑 ]

使用道具 举报

小小菜鸟

钻石会员

帖子
3095
体力
10742
威望
0
发表于 2006-11-25 00:46:38 |显示全部楼层
...厉害,,

使用道具 举报

FlashK 楼主
帖子
553
体力
2405
威望
82
发表于 2006-11-25 01:49:46 |显示全部楼层
LZW确实有时可以压得很低,不过这上面的例子比较特别。像这个:16736512,16736512 有两个像素是相同的。在最极端的情况下,如果整个画布都是一种颜色的话,就可以用16736512(168)这样的方法来描述。(表示后面有168个16736512这样的值)

GIF压缩我感觉是比较笨的。它只会对图像作横向压缩。如果是柱子它就不行了。LZW也可以用在最后压缩一次:)

PS:我在这贴子中只想弄一个当前在FlashPlayer8/AS2中一个可以普遍实用的解决方案。(我标明了AS2,呵呵~`)
解决下面的问题:
一、压缩文件大小。尽可能的支持更大的图片(最优先考虑)(不过大图片会更消耗CPU)
二、最大优化性能,使它能够实际使用(Flash很多东东好像很慢,就像这里的String)
二、如果有可能,考虑图像压缩算法(这个很头疼)


让我们来进一步优化我们的速度,ActionScript改成这样:

  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]";
  7. function colorToString():Void {
  8.         var width = myBitmap.width;
  9.         var height = myBitmap.height;
  10.         for (var i = 1; i<height; i++) {
  11.                 for (var j = 1; j<width; j++) {
  12.                         var num = myBitmap.getPixel(i, j);
  13.                         data += String.fromCharCode(num);
  14.                 }
  15.         }
  16. }
  17. timer = getTimer();
  18. colorToString();
  19. trace(getTimer()-timer);
复制代码


我们将一上面的代码写到一个function 中,这一次我们将速度优化到了2852ms左右。
快了很多,是不是?

不过这还不够,让我们继续优化速度。
ActionScript:
  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var data:String = "[bitmap width=400 height=300 sendBy=Flash Encode=UTF-8 ]";
  7. function colorToString():Void {
  8.         var a = data;
  9.         var width = myBitmap.width;
  10.         var height = myBitmap.height;
  11.         for (var i = 1; i<height; i++) {
  12.                 for (var j = 1; j<width; j++) {
  13.                         var num = myBitmap.getPixel(i, j);
  14.                         a += String.fromCharCode(num);
  15.                 }
  16.         }
  17.         data = a;
  18. }
  19. timer = getTimer();
  20. colorToString();
  21. trace(getTimer()-timer);
复制代码


这次,速度又有提升,所消耗的时间为1986ms

待续。。。

[ 本帖最后由 FlashK 于 2006-12-8 09:42 编辑 ]
欢迎来我的全Flash站收藏:http://www.flashk3.com/

使用道具 举报

meud 
帖子
794
体力
3228
威望
0
发表于 2006-11-25 04:29:03 |显示全部楼层
还有一个方法啊……
记录第一个像素的颜色值,第二个开始计算与前一个像素的差值,如果颜色相同,那么差值为0,即只要发送一个字节就OK了。

[ 本帖最后由 meud 于 2006-11-25 04:31 编辑 ]
无能事即能无事,无事则无事事矣。
不可解亦可不解,不解以不解解之。

使用道具 举报

紫极光

钻石会员

帖子
1828
体力
9409
威望
1
发表于 2006-11-25 08:50:49 |显示全部楼层
我汗..这样的帖子才是好帖子啊..我不太懂压缩方面呢.不过结合其它的Camera对象来用的话很不错呢...希望能有个好的结论出来..
~FOREVER HOT~
http://www.shinez23.cn/ --- 紫*极光

使用道具 举报

FlashK 楼主
帖子
553
体力
2405
威望
82
发表于 2006-11-26 12:57:33 |显示全部楼层
原帖由 meud 于 2006-11-25 04:29 发表
还有一个方法啊……
记录第一个像素的颜色值,第二个开始计算与前一个像素的差值,如果颜色相同,那么差值为0,即只要发送一个字节就OK了。



嗯~` 以后也考虑实现这个

[ 本帖最后由 FlashK 于 2006-11-26 13:40 编辑 ]
欢迎来我的全Flash站收藏:http://www.flashk3.com/

使用道具 举报

寂寞火山

荣誉管理 手机认证 

帖子
2584
体力
10205
威望
197
发表于 2006-11-26 17:23:00 |显示全部楼层
FlashK现在又开始研究图象和视频了,发现你研究什么都研究的很深啊,厉害!向你学习

使用道具 举报

7cai 
帖子
3
体力
25
威望
0
发表于 2006-11-26 17:40:50 |显示全部楼层
好贴要顶啊

使用道具 举报

追意

高级会员

帖子
292
体力
746
威望
0
发表于 2006-11-27 09:48:15 |显示全部楼层
这些方法解决了到服务器端的数据传输量,不过却增加了客户端的负担。在客户端,光光执行图片的像素扫描都得花不少时间,如果再在其中增加这些算法,不知道如果要扫描一张大图,客户端得花多少时间处理,对于没什么耐心的网友而言,这种代价是否合适。。
还有一点,就是在扫描数据时,直接用嵌套for语句,在普通电脑上是不行的。前两天做了个320x240的扫描循环,我自己电脑是P42.4,1G内存,还好,只是执行时浏览器暂时呆掉,结果客户那边一用发现很多浏览器直接死掉(如果你做了一个扫描像素的进度条,那么实际执行时你会发现,也许进度条并不会如你所愿地显示),建议用enterframe或setInterval来替代其中一个循环,可以适当解决问题。

使用道具 举报

帖子
113
体力
408
威望
0
发表于 2006-11-27 09:50:10 |显示全部楼层
谁出来说说服务端怎么解决的吧
www.zhaohongri.com

使用道具 举报

weni 
帖子
45
体力
5
威望
0
居住地
广东省 广州市
发表于 2006-11-27 14:28:50 |显示全部楼层
你们现在讨论的两种方法(使用fromCharCode和LZW压缩)在我的blog里早就提出过了(http://www.weni.cn/index.php?play=reply&id=57),而且进行过试验了。
有兴趣的可以去看看。

使用道具 举报

weni 
帖子
45
体力
5
威望
0
居住地
广东省 广州市
发表于 2006-11-27 14:33:07 |显示全部楼层
使用大头贴最好的方案是使用as3,直接在客户端将拍出的画面编码成jpg或者png格式,再传到服务端,效率比as2的高n倍。。
我在 碰碰网(http://show.pengpeng.com/tt/) 开发的大头贴就是使用as3开发的 ,有兴趣的朋友可以去体验一下!

使用道具 举报

帖子
82
体力
102
威望
0
发表于 2006-11-27 16:06:38 |显示全部楼层
读图片的话,直接用for循环来做会造成客户端一下子的卡住,用户体验不是很好
孤域客的办法非常好,即使这样会慢一些,用户体验也会更好

使用道具 举报

得失

银牌会员

帖子
677
体力
2573
威望
1
发表于 2006-11-27 16:18:01 |显示全部楼层
虽然传输量减小了,但是客户端和服务器端的负荷都会增加。

使用道具 举报

帖子
36
体力
58
威望
2
居住地
广东省 广州市
发表于 2006-11-27 16:33:42 |显示全部楼层
我机测试最后端代码
1508ms
期待继续优化。。。

使用道具 举报

weni 
帖子
45
体力
5
威望
0
居住地
广东省 广州市
发表于 2006-11-28 14:02:37 |显示全部楼层
原帖由 weni 于 2006-11-27 14:33 发表
使用大头贴最好的方案是使用as3,直接在客户端将拍出的画面编码成jpg或者png格式,再传到服务端,效率比as2的高n倍。。
我在 碰碰网(http://show.pengpeng.com/tt/) 开发的大头贴就是使用as3开发的 ,有兴趣 ...


我上面的方案,由于直接在客户端生成图片,服务端根本没什么计算,只是纯粹的保存图片。从而没什么压力
客户端as3的运行效率是as2的几十倍,生成320×240的图片,普通计算机基本没上面延时,生成的jpg图片质量0.7的基本可以控制在30K左右。

使用道具 举报

我是棉花糖

银牌会员

帖子
936
体力
2563
威望
6
发表于 2006-11-28 14:32:49 |显示全部楼层
@楼上:请仔细看楼主的标题

使用道具 举报

得失

银牌会员

帖子
677
体力
2573
威望
1
发表于 2006-11-28 16:36:20 |显示全部楼层

回复 #19 weni 的帖子

flash可以在客户端生成图片么,不行吧(编码),服务端还是有一定的压力的因为要写文件嘛

使用道具 举报

生命与花的寓言

中级会员

帖子
370
体力
691
威望
0
发表于 2006-11-28 17:37:37 |显示全部楼层
强啊,好贴必顶哈。希望楼主继续~
关于生命与花的寓言…

使用道具 举报

xfys 
帖子
106
体力
273
威望
0
发表于 2006-11-28 17:51:57 |显示全部楼层
lz,能不能把swf中的一个mc的图像或者一个矩形区域[假设是100,100到300,300]的图像,抓拍下来,保存到本地硬盘?或者暂时存在swf中?

使用道具 举报

帖子
27
体力
13
威望
0
发表于 2006-11-29 02:13:30 |显示全部楼层
3楼正解,两年前我已经尝试过了。
还有一个思路,利用unicode写成gif或ipeg的字符串,提交给后台后改文件头后直接写二进制文件,这样做的好处就是负担全在客户端,服务器基本没有负担了。

使用道具 举报

FlashK 楼主
帖子
553
体力
2405
威望
82
发表于 2006-11-29 16:11:52 |显示全部楼层
回去查了一下,UTF-8只支持65536个字符,这样更麻烦了
这样一个字符串只能支持两个RGB分量的信息(RG或者GB)我们现在这样记录RGB信息:第一个字符串记录第一个像素的R和G信息,第二个字符串记录第一个像素的B和第二个像素的R,第三个字符串记录第二个像素的G和B信息。
依此类推。格式如下:
RG,BR,GB,RG,BR,GB,RG,BR,GB....

ActionScript改成这样:

  1. import flash.display.BitmapData;
  2. var myBitmap:BitmapData = new BitmapData(400, 300, true, 0x00ffffff);
  3. myBitmap.draw(_root);
  4. b.attachBitmap(myBitmap, 10);
  5. //
  6. var charCode:Array = new Array("☂");
  7. for (var i = 0; i<256*256; i++) {
  8.         charCode[i] = String.fromCharCode(i);
  9. }
  10. //
  11. var data = "[bitmap width=400 height=300 ]";
  12. function colorToString():Void {
  13.         var preB = 0;
  14.         var k = 1;
  15.         var height = myBitmap.height;
  16.         var width = myBitmap.width;
  17.         var a = "";
  18.         var ar = new Array();
  19.         for (var i = 1; i<height; i++) {
  20.                 for (var j = 1; j<width; j++) {
  21.                         var color = myBitmap.getPixel(i, j);
  22.                         var B = color%256;
  23.                         var tmp = color-B;
  24.                         var G = (tmp/256)%256;
  25.                         var R = (tmp-G*256)/65536;
  26.                         k++;
  27.                         var t = k%2;
  28.                         if (t == 1) {
  29.                                 var code = charCode[R*256+G];
  30.                                 preB = B;
  31.                                 a += code;
  32.                         } else {
  33.                                 var code = charCode[preB*256+R];
  34.                                 var code2 = charCode[G*256+B];
  35.                                 a += code+code2;
  36.                         }
  37.                 }
  38.         }
  39.         data = a;
  40. }
  41. timer = getTimer();
  42. colorToString();
  43. trace(getTimer()-timer);
复制代码


现在要开始自已取得RGB分量信息了.可以用这个代码来获得RGB的16进制信息,然后再每次取两个字符就行:
  1.                 var num = myBitmap.getPixel(i, j).toString(16);
  2.                 var R = num.slice(0, 2);
  3.                 var G = num.slice(2, 4);
  4.                 var B = num.slice(4, 6);
复制代码

不过这个速度太慢了,我们可以自已用数学运算来算,像下面的代码这样:
  1.                 var color = myBitmap.getPixel(i, j);
  2.                 var R = Math.floor(color/65536);
  3.                 var G = Math.floor(color%65536/256);
  4.                 var B = color%256;
复制代码

或者:
  1.                 var color = myBitmap.getPixel(i, j);
  2.                 var B = color%256;
  3.                 var G = ((color-B)/256)%256;
  4.                 var R = (color-B-G*256)/256/256;
复制代码

这里用了速度优化,测试时用了1306ms.

更多具体代码稍后讲解...

[ 本帖最后由 FlashK 于 2006-11-29 16:44 编辑 ]
欢迎来我的全Flash站收藏:http://www.flashk3.com/

使用道具 举报

帖子
80
体力
315
威望
1
发表于 2006-11-29 16:40:57 |显示全部楼层
我想为了兼容ARGB还是用2字节对齐的好,这样编码也比较方便,虽然冗余比楼上的大,恩大约1.5倍吧。

使用道具 举报

FlashK 楼主
帖子
553
体力
2405
威望
82
发表于 2006-11-29 17:04:11 |显示全部楼层
to:weni
AS3 的jpg压缩很不错啊~`PNG压缩我感觉应该没什么用处.对人物和风景的压缩比很低,对网页拍屏类的东西倒是压缩很高.

而负担这回事我感觉放在服务端会好一些,毕竟服务器的性能都很好.Flash这边最好就少点运算,少点传输数据了.

其实AS3和Remoting都可以用来作二进制传输.FCS/FMS其实也可以,不过这里只讨论AS2怎么弄和优化性能了,呵~`
欢迎来我的全Flash站收藏:http://www.flashk3.com/

使用道具 举报

cnxcs 
帖子
694
体力
2544
威望
0
发表于 2006-11-29 17:28:49 |显示全部楼层
原帖由 meud 于 2006-11-25 04:29 发表
还有一个方法啊……
记录第一个像素的颜色值,第二个开始计算与前一个像素的差值,如果颜色相同,那么差值为0,即只要发送一个字节就OK了。



主意不错,偶了一直为传输图像数据大而苦脑,做了个大头照,320*240,传输的数据打印出来有500多K,16进制的,

主要问题:
1.客气端计算慢(这个是主要问题)
2.网络数据传输

我担心要是再算颜色对比,可能客户端会慢得出题.

使用道具 举报

cnxcs 
帖子
694
体力
2544
威望
0
发表于 2006-11-30 16:52:38 |显示全部楼层
没有压缩多少,和前一个像素比对做的

做出的效果:


,0,2081,0,6082,-8104,40g2,2081,-2081,182,20o2,g3,g3,2081,-2,-82,-183,-o2,-40o3,-4105,-6185,-2081,g2,20o4,a185,40g2,-8183,2081,-207v,-82g8,-860h,1o4,s6on,-3snm,a000,-i1gb,-a40c,-o5gj,5rvq,-eb9lh,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7qpjm,1848c,207v,-g188,o187,1g5gh,1m5ok,c1o5,8104,8082,e1o7,2184,-3vo0,a1o6,a002,2081,2103,20g3,60o3,g1,2103,40g2,40g2,20g2,-20g3,-20fu,60o5,-2,7u,-40nu,0,20o0,2081,40g0,1vo2,-3v7v,g1,0,4003,-2,0,-2081,0,60o3,o2,-21o5,-1uvu,-2083,3uvu,-3uvu,-4103,-103,2081,-o2,-2082,-2081,2081,1vvu,0,40g2,-60o1,2081,-2000,0,4002,-2081,-1vo0,2081,0,-1vfv,-o2,0,2081,-g1,-1vo1,4184,2081,-1vo0,-40g2,-20g0,2081,2081,40g2,-40g2,3vfv,2081,-40g2,0,40g2,-40g3,4185,20g2,2083,-6001,fv,1vo0,3vvv,-20o2,-61g5,-2105,-i2ob,40g2,4104,6186,40g2,8104,-a1g4,0,2,-41g7,-i7ol,-m209,g40d,i5gk,e3o8,-3vg1,1tfq,-s68l,-65gf,-e99tf,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7opbl,1a5gi,-40o7,3ufq,m28a,184gd,1q68m,a1g4,a185,-3vfv,i289,40g2,1,8104,20fu,80o6,-3v7v,4083,a1o6,40g2,-1vfv,60o3,2081,-2081,81,-207v,60o3,60o3,-40g4,-6182,60o3,-2081,40g2,0,-4001,40g2,0,0,40g2,-3vg3,2081,-4080,2081,60o3,4003,-40g2,-60o5,-2081,8082,-20g2,-40g2,-2081,-40g2,8082,-20g3,-2081,0,0,2081,-2000,2000,1vo0,-1vo0,-4081,4184,-40g1,0,0,-407v,40g2,-2,0,2000,-2082,5vg1,20o2,40g2,-1vfv,40g2,-80o3

[ 本帖最后由 cnxcs 于 2006-11-30 17:00 编辑 ]

使用道具 举报

帖子
27
体力
13
威望
0
发表于 2006-12-2 00:15:06 |显示全部楼层
你想办法把unicode编码变成ascii编码,同样长度的字符串,字节数就会少掉50%。例如 “ABC”,unicode编码是0x0041,0x0042,0x0043,而ascii编码是0x41,0x42,0x43。而flash向外传递变量时,总是以unicode方式传递的,除非你使用了useSystemCode=true(大概是这么写的吧,好久不用忘了)
如果利用自定义编码,同样长度的字符串,字节数就会少掉75%。因为你仅仅为了传递0~F的信息(4bit),而目前的情况是每个数字会占用16bit。所以,有四分之三的水分可以压缩掉。例如FF0000 EEDDCC.... FF1123 表示连续的颜色点,直接写成字符传 String.fromCharCode(ff00)+String.fromCharCode(00ee)+...+String.fromCharCode(1123),具体的代码很简单,逻辑上就是 数字---->字符串----->压缩字符串。关于这点,lz已经领悟到了,恭喜。
如果还想减小,必须使用无损压缩方式进行压缩,如lzw,lzw的特点是压缩时速度很慢,但解码时速度快,也就是说,单个用户上传的时候,等候的时间会稍长些,但服务器的负担会很小。

再次提醒,尝试是好事,但这样做的意义不大,节约了网络传输时间,可加重了两端的负担,尤其是加重了服务器的负担,并不可取。唉,令人又爱又恨的flash,号称以客户体验为本的flash,居然不提供图片输出功能,郁闷啊。

[ 本帖最后由 chenlangeer 于 2006-12-4 17:03 编辑 ]

使用道具 举报

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

Archiver|手机版|安久科技提供CDN|blueidea.com ( 京ICP备05002321号 )  

GMT+8, 2012-2-4 15:14 , Processed in 0.588807 second(s), 9 queries , Gzip On, Memcache On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部