SWF文件结构研究

来源:互联网 发布:ff14人男捏脸数据 编辑:程序博客网 时间:2024/05/01 09:58

代码位置

结构含义

备注

0.1.2

固定为46 57 53,也就是字母‘F’‘W’‘S’
也有的文件为43 57 53,也就是字母‘C’‘W’‘S’
“F”表示未压缩,“C”表示压缩式的,“W”无特殊意义

“S”无特殊意义

3

文件版本号

可根据此值与当前播放器控件的版本号比较,看是否需要更新

4.5.6.7

文件大小

正确的文件大小应该是按7654的顺序来排列得到的十六进制数,单位是字节。

 8.9.a.b.c.d.e.f.10h-0

影片宽高数据控制码

名字
类型
含义
Nbits
UB[5]
表示每个数字必
须的二进制位数
Xmin
SB[Nbits]
x最小值
Xmax
SB[Nbits]
x最大值
Ymin
SB[Nbits]
Y最小值
Ymax
SB[Nbits]
Y最大值

78 00 05 5F 00 00 0F A0 00
先取前5位二进制,
换成二进制,按照15位分割
0111 1||000 0000 0000 0000 ||0101 0101 1111 000||0 0000 0000 0000 00|| 00 1111 1010 0000 0||000 0000
然后我们可以算出
Xmin = (000 0000 0000 0000)2=(0)10
Xmax = (0101 0101 1111 000)2= (11000)10
Ymin = (0 0000 0000 0000 00)2 =(0)10
Ymax = (00 1111 1010 0000 0) 2= (8000)10
11000 * 8000;一般情况下,1 twip等于1/20象素。
550*400

10h-1,10h-2

表示帧速为

00 18 表示为16+8=24

10h-3.10h-4

影片的总帧数

02 00 表示为总数为2

Flash 生成的文件二进制数据码头文件标志结束,以下就是swf文件结构的一个形象概念:
(文件header)(文件body)
              |
(tag 1)(tag 2)(tag 3)(……)
   |
(tag header)(tag body)
   |
(tag 类型代码)(tag 长度)

                                                        截取图片

以下是关于SWF文件头的官方说明

区域

数据类型

含义

标识

UI8(8位二进制无符号整数)

"F"表示该文件是未压缩的

"C"表示压缩文件(SWF6及后续版本支持)

标识

UI8

总是"W"

标识

UI8

总是 "S"

版本

UI8

SWF文件版本

文件大小

UI32

文件字节大小

画面尺寸

RECT

twips为单位

帧速

UI16

8.8形式的定点小数

总帧数

UI16

总帧数

图片中16位:44 11,将小尾字节顺序转换成大尾顺序就是11 44,单个转换成为二进制字节即为:0001 0001 0100 0100,取高10位是(0001 0001 01)2=(69)10,低6位是(00 0100)2=(4)10.根据高10位的69,查询swf文件中的tag值和action,可以知道TagType69的是FileAttribute Tag。低6位的值4表示Tag数据大小占4个字节,因此我们取出后续4个字节为:00 00 00 00

FileAttributes Tag的结构说明(FileAttributes Tag只在8及后续版本中)

数据类型

含义

Tag

RECORDHEADER

TagType=69

Reserved

UB[3]

总是0

hasMetaData

UB[1]

1表示含有MetaData标签

0表示不含

Reserved

UB[3]

总是0

UseNetWork

UB[1]

如果为1,则在本地加载时该文件有网络权限。为0,则在本地加载时该文件只有本地权限。

Reserved

UB[24]

总是0

取下一个Tag,依然取2个字节43 02,转化成02 43,然后高十位=(0000 0010 01)2=(9)10,6位=(00 0011)2=(3)10,10位的9表明这是一个SetBackgroundColor tag,6位的3表明数据占3个字节,OK,我们取出后续的3个字节是 FF FF FF,这背景颜色:白色。

再取下一个Tag 3F 03转化成03 3F,高10=(0000 0011 00)2=(12)10,6(11 1111)2=(63)10,高十位的12表示这是个DoAction标签,低6位的63表明数据长度有后续的4个字节决定,再取后续的4个字节为02 00 00 00,它表明这个Tag的数据长度占2个字节,再取后续的2个字节是07 0007表示Action代码,查Action代码就可以知道它表示ActionStop,也就是写在第一帧的代码AS Code  /*stop();*/07后面的00,就表示DoAction Tag结束了。

取下一个Tag FF 0A转换0A FF,高10位=(0000 1010 11)2=(43)10,6位=(11 1111)2=(63)10,10位的43表明这是一个FrameLabel标签,6位的63表明数据大小由后续的4个字节指明,取出后续的4个字节为06 00 00 00,也就说该Tag的数据占6个字节,继续取后续的6个字节,73 74 61 72 74 00,将16进制值转换成字符串就是"start"00是字符串结束标志。

Next Tag ,40 00,转换成 00 40,高10位=(0000 0000 01)2=(1)10,6=(00 0000)2=(0)10,高十位的1表明这是一个ShowFrame Tag,当前帧的内容都已进行完毕,可以显示当前帧了。

Next Tag , 3F 03与前面相同,接着取2个字节:05 0005 代码表示ActionPrevFrame,也就是写的函数的AS Code “prevFrame();” ,00表示DoAction Tag结束了。

Next TagFF 0A,表明这是一个FrameLabel标签,也就是我们所说的帧标签。低6位的63表明数据大小由后续的4个字节指明,我们取出后续的4个字节为04 00 00 00,也就说该Tag的数据占4个字节,继续取后续的4个字节,65 6E 64 00,将16进制值转换成字符串,就是"end"00,是字符串结束标志。

Next Tag,40 00,转换成 00 40,高十位=(0000 0000 01)2=(1)10,6=(00 0000)2=(0)10,高十位的1表明这是一个ShowFrame Tag,就是当前帧内容都已准备完毕,可以显示当前帧了。

Next Tag 00 00,不用转换了,高十位是0,低6位也是0,表明这是个End Tag

文件中的基本数据类型有整型(包括8,16,32的有符号和无符号,但是我在变成中感觉不到两者的区别),定点数,浮点数,变长数。下面的数据类型也是样式书中定义的基本类型,但是他们的定义都是以上面的4中作为基础的:

UIx x位无符号整型;(如UI8表示8位无符号整型,即一个byte的无符号整型)
SIx x
位有符号整型;
UIx[n] x
位无符号整型的长度是n的数组;
SIx[n] x
位有符号整型的长度是n的数组;

FIXED  32
16.16定点数
FIXED8 16
8.8定点数

FLOAT16 16
位半精度浮点数
FLOAT   32
位单精度浮点数
DOUBLE  64
位双精度浮点数

UB[n] n
位变长数表示无符号整型
SB[n] n
位变长数表示有符号整型
FB[n] n
位变长数表示定点数

 

swf中基本的数据结构

1swf的长度单位,swf使用twips表示坐标中的距离,1 twips=1/20 pixel。(我现在知道拉!flash的反走样是使用超采样地~~)这样分数的pixel可以使用整数的twips表示。样式书还说明了其他的好处,不过这和我有什么关系?

2,整型和字节顺序

swf使用8位,16位,32位,64位,有符号和无符号整形类型。所有的整形都是用little-endian的字节顺序(即数值低位储存在字节高位)。然后在每一个字节中采用big-endian编序。这样你就不会误会,字节80表示的确实是 128,而不是1    例子:16位的0xe712 被保存成 12 e7.32位的0x456e7120 被保存成20 71 6e 45. 

3,定点数

swf中有两种定点数16位(8.8)和32位(16.16)。使用little-endian字节顺序

4,浮点数

16位(半精度half),32位(单精度float),64位两种(双精度double)。

5,变长数(bit value

长度可变的数,变长数可以表示无符号,有符号,和16.16定点数。

变长数不须要byte对齐(其他类型须要),如果需要byte对齐的类型紧接着变长数出现,需要补零。bit value作为不同的类型(前面说的3中)在解释上使用补01的方法。比如SB[4](有符号4位变长数) = 1110解释成16位有符号整形为 1111111111111110 = 2


字符串,字符串是以全0结束的byte序列,采用utf-8编码。有关utf-8可以参考http://www.unicode.org/unicode/faq/utf_bom.html#UTF8
语言种类是一个byte,描述的不是编码而是自然语言。用来处理字体还有在需要换行的时候处理断字,比如一个很长的英文单词出现在行尾但显示不下,可能会被处理显示到行首。
record
,这个有点像C语言的structure,或者支持类的语言中没有方法的类。它按照格式顺序的储存一些上述的类型。

 

RGB color record

项目

 类型

 说明

Red

UI8 

红色值 

Green

UI8

绿色值

Blue 

UI8 

蓝色值

 

ARGB

 

Aplha

UI8

透明值,0为完全透明

Red

UI8 

红色值 

Green

UI8

绿色值

Blue 

UI8 

蓝色值

 

RGBA

Red

UI8

红色值 

Green

UI8 

绿色值

Blue

UI8

蓝色值

Aplha

UI8 

透明值,0为完全透明


上面的3个是表示颜色的

Matrix
表示的是一个形状的仿射变换,有关仿射变换可以参考java.awt.geom.AffineTranform类,或者flash.geom.Matrix类的说明,或者任何一本大学的几何教材。

 项目

类型 

说明 

HasScale  

UB[1]

如果包含缩放,则为

NScaleBits

如果HasScale=1UB[5]否则没有该项

指示下面两项,每项要使用的bit

ScaleX

如果HasScale=1FB[NScaleBits]

x方向上的缩放

ScaleY

如果HasScale=1FB[NScaleBits]

y方向上的缩放

HasRotate

UB[1]

如果包含旋转,或者扭曲,则为1

NRotateBits

如果HasRotate=1UB[5]

指示下面两项,每项要使用的bit

RotateSkew0

如果HasRotate=1FB[NScaleBits]

有关旋转和扭曲的第一个值

RotateSkew0 

如果HasRotate=1FB[NScaleBits]

有关旋转和扭曲的第二个值

NTranslateBits

UB[5]

指示下面两项,每项要使用的bit

TranslateX

SB[NTranslateBits]

x方向上平移的量,单位是twips

TranslateY

SB[NTranslateBits]

y方向上平移的量,单位是twips


这个matrix record对应一个2x3矩阵:
  ScaleX       RotateSkew0 
( RotateSkew1  ScaleY      )
  TranslateX   TranslateY
对于在一个坐标系中的(x, y),变换后的 (x', y')按照如下方法得到
:
x' = x * ScaleX + y * RotateSkew1 + TranslateX
y' = x * RotateSkew0 + y * ScaleY + TranslateY

 

还有两个:Color Matrix recordColor Matrix with aplha record,是处理颜色转换,这和我暂时没有很大关系,所以如果将来感兴趣了再去参考吧。注意到这些后面的这些record上都对应了flash.geom包的类,但是它们却并非flash8中加入的新成员。所以不要以为只关心7以前的版本就完全没有必要看它们。


文件结构

至此,一个深刻的问题出现在我的面前。我要怎么使用这些类型?这里连一个声明/调用的语法都没有。要注意,现在我的事情是理解swf文件的结构(最后要生成一个)。这不是编程,而是编码。所以我必须按照swf的文件结构,按照一定的顺序把正确类型的数据放在正确的位置。这个就是本文的正体,上面噜苏的一堆其实算是对上一篇的补完。

swf
文件是文件头和一些叫做tag的组成的。

上次介绍了header,这次来看一看tag:

tag
的头

tag
是以tag的类别和一个表述该tag的长度的域开始的,根据这个tag的长度不同,这个tag的头有两种:短格式的头和长格式的。短格式的tag要求数据内容(不包括头)的长度不超过62 bytes;而长格式则可以最多达4GB
短格式

项目

类型 

说明 

TagCodeAndLength

UI16

10位是tag类别,低6位是长度

长格式

项目

类型 

说明 

TagCodeAndLength 

UI16

形式上和短格式一致,但是低6位的长度的数值固定为0x3f

Length  

SI32

数据长度

tag的种类
在一个swf中包含两中tag分别是Definition(定义)Control(控制)。定义块中包含了对swf要包含内容的定义。比如一个图形,文字之类。定义块中要为每一个内容的定义指派一个唯一的id叫做character id(不要误会character的意义,这里不是指字符,而大约是标志的意思,而我想从这里开始使用标志这个词)。swf把这些标志(character)存放在一个叫做字典(dictionary)的结构中。注意定义块不会导致任何的屏幕绘制。


控制块处理,创建字典中标志的实例,绘制屏幕,控制流程等。

顺序
除了FileAttribute要放在最前(这是一些全局的东西),end它要放在最末。块之间不需要顺序。但是要保证依存关系,比如块B要引用块A的标志,就不能在A的前面出现。Stream块需要按照顺序。

关于DefineFont2介绍
这个tag的作用是定义一个字体,或者一组静态轮廓字,用以给DefineEdit Text使用。
关于文字的几乎所有信息,都可以在这个tag中进行设置,
它的结构如下:

其实如果单纯分析动态文本的这个tag的信息,只需要分析到下面的fontName部分就足够了,其他信息只对轮廓字,也就是静态文字有效。动态文字在信息上,关键的只有一个字体名,而静态文字却包含了他的轮廓信息(包含在shape里),这就是动态文字和静态文字最大的不同。

长度(bit

名称

说明

Headerlength

Header

Tag head, type of head 48

16

FontID

字符标号唯一的标签

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

根据FontFlagsWideCodes16位,编码表为固定值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位,否则没有该字段

 

原创粉丝点击