swf文件格式【转】

这个在自己开发辅助工具时很有用啊,转来学习一下

 

swf文件的整体结构是 header + body的组成。

文件的开始是一个[文件头]
它的结构如下:

[Copy to clipboard] [ - ]CODE:
字节       名称             说明
1           Signature      “F”表示非加密格式,“C”表示加密格式
1           Signature      “W”无特殊意义
1           Signature      “S”无特殊意义
1           Version         版本号,它表示对应播放器版本
4           FileLength     整个文件长度,低位在前
N           FrameSize     RECT结构体,表示屏幕大小,具体结构和长度根据数据变化,分析方法另外讨论。
2           FrameRate     帧频,默认为12,高位在前
2           FrameCount   帧数,表明文件根下的帧数,低位在前
以上是swf中,最简单的一个tag,一个完整的swf文件是由很多独立的tag组成的。每一个tag都包括一个头和一个数据体,头有2种类型,短tag型和长tag型。

短tag型由2byte构成,前10个bit表示tag类型,后6个bit表示tag长度。

长tag型由6byte构成,前10个bit表示tag类型,后6个bit固定为全1,后4个byte代表tag长度。

tag的长度不同于文件头的长度FileLength,它是除去tag头后的长度。

(另外)只有非加密的swf文件可以直接用以上的方法解析,加密的文件需要另外增加一步处理。具体方法由于牵涉到版权问题,这里我不加说明。


这份资料可能对flash设计意义不大,但如果有人用的着,我会继续分析一下,如果有人也在做这方面的调查,欢迎和我一起讨论。


第2节

前节说明了swf文件是由1个head和1个body构成的。
并且解析了header的结构,和一个tag的header部分的简单说明。

下面余下的就是swf文件的body了。

整个文件body是由大量的tag组成的,通过分析tag的head部分,可以立刻知道这个tag的类型代码和长度。

如果你无法识别这个tag的类型,也可以利用tag的长度,直接跳过这个tag。

这种方式保证了版本的兼容性,即使出现了新的tag,老版本的播放器还是能够解析完整个swf文件而不出现错误,大不了就是不能提供新的功能而已。

以下就是swf文件结构的一个形象概念。

[Copy to clipboard] [ - ]CODE:
(文件header)(文件body)
               |
(tag 1)(tag 2)(tag 3)(……)
    |
(tag header)(tag body)
    |
(tag 类型代码)(tag 长度)
这样大家是否对swf文件的结构有了一个基本的认识?

下一节我会分析一下几个swf必有的tag,包括 backgroundColor tag,showFrame tag和end tag

第3节
setBackgroundColor tag

这个tag是直接跟在文件head后面的第一个tag,是文件中必然存在的。
它的结构如下:

[Copy to clipboard] [ - ]CODE:
长度(bit)            名称                         说明
16                  header                     tag头,短tag型 类型码为9
24                  BackgroundColor        RGB类型,右3个字节,分别表示红、绿、蓝
showFrame tag

这是文件最后第2个tag,它是必然存在的。
结构如下:

[Copy to clipboard] [ - ]CODE:
长度(bit)            名称                         说明
16                   header                     tag头,短tag型 类型码为1
end tag

结束tag,它的作用不用我说了,必然是文件的最后一个tag。

[Copy to clipboard] [ - ]CODE:
长度(bit)            名称                         说明
16                   header                     tag头,短tag型 类型码为0
下一节我将讲的是character ID 和Depth的意义和textField的基本tag组成。
(另外)感谢AOL的补充和解释。

第4节
一个textField就是一个文本框,文本框有3种,静态的,动态的,和输入型。作为tag的话,它只有2种,静态的和动态的,输入型不过是动态的一种特别形式。

这里讨论动态文本框的组成。
它由3个tag组成,2个定义tag和一个控制tag
分别是:
定义tag    DefineFont2   DefineEditText   (针对player 7.0 如有不同情况请检查播放器版本)
控制tag    PlaceObject2

DefineFont2 定义了一个字体信息, DefineEditText引用了定义的字体,并定义了显示的文字信息,而PlaceObject引用了定义的文字信息,并控制了文字的显示。

他们之间的引用就是依靠character ID进行的。

character ID就是一个从1开始的数字标示,如果中间出现缺漏,从缺漏开始的所有character ID都被忽略,而重复的话,后出现的将覆盖先出现的tag。

DefineFont2用一个character ID 来标示自己,DefineEditText和PlaceObject2也同样如此。但并不是所有的tag都有character ID。
另外,PlaceObject2虽然也有character ID,但它并不是用来标示自己的,而是用来调用的。

而深度Depth在3个tag中只有PlaceObject2拥有。

这3个tag的关系就是这样。这3个tag的结构我会在下节中说明。(抱歉,每次都说一点点!)

第5节

DefineFont2
这个tag的作用是定义一个字体,或者一组静态轮廓字,用以给DefineEditText使用。

关于文字的几乎所有信息,都可以在这个tag中进行设置,因此,这也是一个相当复杂的tag。
它的结构如下:

[Copy to clipboard] [ - ]CODE:
长度(bit)                        名称                         说明
headerLength                header                  tag头,类型码为48
16                        FontID                    character ID,唯一的标示
1                          FontFlagsHasLayout   根据字面解释,判断是否有变型的标记
1                          FontFlagsShiftJIS       是否使用ShiftJIS编码
1                          FontFlagsSmallText    是否使用小字体显示
1                          FontFlagsANSI           是否使用ANSI编码
1                          FontFlagsWideOffsets 是否使用32位偏移量
1                          FontFlagsWideCodes   是否使用16位文字编码
1                          FontFlagsItalic            文字是否是斜体
1                          FontFlagsBold             文字是否是粗体
8                          LanguageCode           语言编码,有相应的编码表对应
8                          FontNameLen            文件名长度
FontNameLen*8            FontName               文件名称(使用utf8编码) 
16                               NumGlyphs              轮廓字个数
32/16                          OffsetTable              根据FontFlagsWideOffsets,为32位,否则为16位
32/16                          CodeTableOffset      同上
不定*NumGlyphs           GlyphShapeTable      轮廓字信息,为shape结构(又是一个复杂结构)
16/8                    CodeTable               根据FontFlagsWideCodes,为16位。编码表,为固定值UCS-2
16/0                    FontAscent             根据FontFlagsHasLayout,为16位,否则没有该字段
16/0                   FontDescent            根据FontFlagsHasLayout,为16位,否则没有该字段
16/0                   FontLeading            根据FontFlagsHasLayout,为16位,否则没有该字段
16/0*NumGlyphs         FontAdvanceTable   根据FontFlagsHasLayout,为16位,否则没有该字段
RECT*NumGlyphs        FontBoundsTable     根据FontFlagsHasLayout,为16位,否则没有该字段
16/0                          KerningCount         根据FontFlagsHasLayout,为16位,否则没有该字段
KERNINGRECORD*KerningCount
                         FontKerningTable     根据FontFlagsHasLayout,为16位,否则没有该字段
如果你仔细看了上面的内容,我挺佩服你的。

其实如果单纯分析动态文本的这个tag的信息,只需要分析到上面的fontName部分就足够了,其他信息只对轮廓字,也就是静态文字有效。

看到这个大家应该都明白了一点,动态文字在信息上,关键的只有一个字体名,而静态文字却包含了他的轮廓信息(包含在shape里)。
这就是动态文字和静态文字最大的不同。

下一节讲下一个tag      DefineEditText


rect结构这个没有说清楚.它是flash存储结构的一种.

      属性         类型                     说明  
      Nbits            nBits = UB[5]           rect结构的各个属性值的位数
      Xmin            SB[nBits]            x轴方向的最小值
      Xmax            SB[nBits]            x轴方向的最大值
      Ymin            SB[nBits]            y轴方向的最小值
      Ymax            SB[nBits]            y轴方向的最大值


这里涉及到swf文件中的一个长度单位:twip. 1 twip也就是一像素的1/20.

Nbits一般等于最大属性值的位数.比如影片有这个属性:

属性             十进制             二进制
Xmin = 127 decimal =     1111111 binary 
Xmax = 260 decimal =    10000100 binary 
Ymin =   15 decimal =        1111 binary 
Ymax = 514 decimal = 1000000010 binary


那么最大的属性值是ymax了.它为514了,它有十位,加上正负数的一个sign就十一位了.那么Nbits应该会是11.


这时:
属性             十进制                   二进制
Nbits =    11 decimal =        1011
Xmin =    127 decimal =     00001111111 binary 
Xmax =   260 decimal =    00010000100 binary 
Ymin =    15 decimal =     00000001111 binary 
Ymax =   514 decimal =    01000000010 binary

用java读取就可以:

//其中readUBits是读取unsigned bit的函数
//readSBits是读取signed bit的函数
public Rectangle2D readRect()
         throws IOException {

         byteAlign();
         int nbits = (int)readUBits(5);
         int xmin = (int)readSBits(nbits);
         int xmax = (int)readSBits(nbits);
         int ymin = (int)readSBits(nbits);
         int ymax = (int)readSBits(nbits);
         return new Rectangle2D.Double(xmin/TWIPS, ymin/TWIPS, (xmax-xmin)/TWIPS, (ymax-ymin)/TWIPS);
     }

 


我算是抛砖引玉吧,兄弟们有更多的内容大家一起加!

这是swf 文件的组成形式.swf文件头占21字节,尾标签(EndTag)占三个字节.其它的tag每个都有统一的组成结构,而且它们是彼此独立的.从这个tag不能访问那个tag的数据.每个tag内部的数据读取方法是根据数据的偏移量(offset)来读取.因为是独立的,所以你可以用工具来修改,添加,删除swf文件里面的tag.

 


// java的添加tag 
     final TagCollection tc = new TagCollection();     
     tc.add(tag1);     
     tc.add(tag2);     
     ...     
     final TagEnumeration te = tc.close();     

重复sansunzw兄弟的了:
tag可以分为两种,一种是定义型tag,另外一种是控制型tag.
tag按长度也可以两种,一种是长型tag,一种是短型tag.]
tag一般都由tag头开始.
短型tag的tag头有十六位,高十位为tag的类型,低六位为定义这个tag的长度.因为是6位,所以短型tag只能最多是2^6 =64字节左右大小.swf 有规定不能超过62字节大小.
长型tag的tag头有48位,16位tag类型定义+32位tag长度定义.所以长型tag最大长度能为2^32=4G字节.这可远远超过了我们平时用到的那个数量级了.

//这个java 的关于swf tag头的一个类
//很多相关的代码不列了
public class TagHeader {

     int tagID;
     long length;

     public TagHeader(int tagID, long length) {
         this.tagID = tagID;
         this.length = length;
     }
    
     public void setTag(int tagID) {
         this.tagID = tagID;
     }
    
     public int getTag() {
         return tagID;
     }
    
     public void setLength(long length) {
         this.length = length;
     }
    
     public long getLength() {
         return length;
     }
}

 

定义型和控制型tag(Definition and Control Tags)是swf文件tag的两种类型。定义型tag定义的swf影片的内容,像形状啊,文字啊,位图啊,声音啊等等。每个定义型tag都分配

了一个唯一的标识ID叫做角色ID.flash播放器则把这些角色放到一个存储空间里面,这个存储空间我们一般叫它字典。用定义型tag是不会绘制任何图形的,不会产生任何动画的。

因为这些事都交由控制型tag来做。控制型tag做的就是从字典里取出角色,操作这些的绘制和运动等,控制整个影片的流程。

这些tag是怎么排序存储起来的呢?总的来说,tag可以出现任何情况的排序方法,但也不是随便乱排咯。 它遵循一些规则。


1.一个tag只能依靠在它之前的tag,不能依靠在它之后的tag.
2.一个定义了角色的定义型tag必须在引用这个角色的控制型tag之前。
3.流媒体tag必须有顺序,没有顺序的流媒体播放起来也是没有顺序的
4.结尾标签(tag)应该在swf文件的最后。

(待续)

 

swf文件是由文件头和文件体组成,两者都不定长,文件头定义了本swf文件的版本、是否压缩、文件大小、场景大小、帧率、总帧数共6个内容,这些内容非明文,均以数字的存储方式表现出来,楼主提供的第一个表格详细指示了这些内容的相关信息,稍微补充一下,第一个字‘C’代表本swf文件是否被压缩,当你用flash6以后版本,public setting设置里会有“压缩影片”,选中后,出来的swf文件都是‘C’开头的。 压缩影片,是指从文件头中的filelength部分以后所有内容,包括文件体,都被标准压缩算法处理了。算法是zlib,压缩的好处,就是swf文件变小。
下面举例:
   46 57 53 05 AF 00 00 00 78 00 05 5f 00 00 0f a0
   00 00 0c 01 00 43 02 ff ff ff 00 06 3f 03 15 00 00 00

46 57 53 就是‘fws’的asc码,此处显示的都是16进制,大家注意了。
05 代表本swf是flash5兼容格式,如果是0c,就表示本swf是flash12格式,嘿嘿,不知道将来的flash12会是什么样子。
af 00 00 00就是16进制数‘af’的存储方式,af转换成10进制是175,就是本swf文件的总长度。
78 00 05 5f 00 00 0f a0 00,表示了场景大小,这个长度不定,此处占用了9个byte,究竟为什么占用9个,大家可以看rect的结构指示,此处不再做介绍。
00 0c 表示帧率12,c就是12,没有人反对吧。
01 00表示本swf文件共1帧。
文件头到此结束,以上结构是必须的,不能少任何一项。
43 02 ff ff ff 是个“块”,这里罗嗦一下,文件体是由大量的块组成的,这些块内容独立,一起配合显示动画,比如有的块表示了一个矩形,有的块存储了一段音乐,有的块表示了此处为一帧,等等。    块,组成了文件体,但每一个块都是可以割舍的,这5个 byte的块表示了底色,红为ff,绿为ff,兰为ff,合起来就是白色啦。再罗嗦一下,块,不严格的说,就是楼主所说的tag。块是堆砌在一起的,两个块之间没有什么分割符号,因为每个块的长度都有定义,比如这个块,43 02就表示了本块占用3 byte,加上43 02,就是5个byte,所以后面的:00 06就不是本块内容啦。为什么43 02表示本块代表底色,还占3个byte呢?哎,偏题了,说到文件体了。以后再作介绍吧。
最后介绍一个,00 06表示本文件保护,不允许导入到别的flash中,这也是一个块,嘿嘿,最小的块就是由2byte组成,把它去掉就不保护了,好像是废话啊,哈哈,别忘了改一下文件长度位,减少2。如果带密码,此处就不是00 06了。

 

【原帖:http://bbs.blueidea.com/thread-1509786-1-1.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值