加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swf文件格式解析入门(文件头解析)

发布时间:2020-12-15 18:23:43 所属栏目:百科 来源:网络整理
导读:这里是使用as3语言来对swf文件做解析,其它语言可以参考。 一,准备工作 从Adobe官网下载一份swf文件格式说明文档 http://www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf avm2虚拟机说明文档 http://www.adobe.com/conten

这里是使用as3语言来对swf文件做解析,其它语言可以参考。

一,准备工作
从Adobe官网下载一份swf文件格式说明文档
http://www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf
avm2虚拟机说明文档
http://www.adobe.com/content/dam/Adobe/en/devnet/actionscript/articles/avm2overview.pdf

采用flash builder新建一个项目。
// 嵌入测试的swf资源
[Embed (source = "../testswf/test.swf",mimeType = "application/octet-stream")]
private var content:Class;

// 初始化字节对象
var bytes:ByteArray = new content() as ByteArray;
// 设置为主机字节序
bytes.endian = Endian.LITTLE_ENDIAN;

二,开始解析工作
swf文件格式为:[header][FileAttributes tag][Tag][Tag]...[Endtag]
我们首先来解析header部分,如果这个部分会解析了,下面就很顺利了。
由于以上的文档都是flash player 9.0的时候写的,有部分10的特性没写在里面。
解析的时候如果遇到未知的类型,可以网上查查

1,解析文件头
swf文件是采用主机字节序

SWF File Header
Field?????????? Type??????????? Comment
Signature?????? UI8???????????? Signature byte:
??????????????????????????????? “F” 未压缩
??????????????????????????????? “C” 压缩
Signature?????? UI8???????????? 固定为“W”
Signature?????? UI8???????????? 固定为“S”
Version???????? UI8???????????? 版本号 (如: 0x06 表示swf6)
FileLength????? UI32??????????? 该swf文件的长度,单位:字节
FrameSize?????? RECT??????????? swf的舞台大小,单位:twips 1px = 20twips
FrameRate?????? UI16??????????? 帧率,这里总共有16位,只有后面8位有效
FrameCount????? UI16??????????? 总帧数

先读取3个字节的文件头
var sign:String = bytes.readUTFBytes(3);
if (sign != 'CWS' && sign != 'FWS')
??? throw new Error ("文件头错误");
读取文件版本
version = bytes.readByte();
读取文件长度
fileLength = bytes.readInt();

如果文件签名是CWS,即是压缩过的,则需要进行解压缩
解压缩是从FrameSize这个地方开始到文件末尾
if (sign == 'CWS'){
??? var tempBytes:ByteArray = new ByteArray();
??? tempBytes.writeBytes(bytes,bytes.position);
??? tempBytes.uncompress();
????
??? var temp:int = bytes.position;
??? bytes.length = bytes.position;
??? bytes.writeBytes(tempBytes);
??? tempBytes.length = 0;
??? bytes.position = temp;
}

然后读取FrameSize

Bit Values 格式
Type??????? Comment
SB[nBits]?? 有符号位值 (nBits表示用多少位来存储这个值)
UB[nBits]?? 无符号位值 (nBits表示用多少位来存储这个值)

RECT 格式
Field?????? Type??????? Comment
Nbits?????? UB[5]?????? Bits used for each subsequentfield
Xmin??????? SB[Nbits]?? x minimum position for rectangle in twips
Xmax??????? SB[Nbits]?? x maximum position for rectangle in twips
Ymin??????? SB[Nbits]?? y minimum position for rectangle in twips
Ymax??????? SB[Nbits]?? y maximum position forrectangle in twips

第一个Nbits为5位长度的UB,这个值就是下面的[Nbits]值
这里就需要先写个函数,读取指定字节长度的值
注意:这里的单位都是twips 1px = 20twips
舞台的宽=Xmax-Xmin
舞台的高=Ymax-Ymin

/**
* 读取一定长度的位?
* 无符号的
*?
* @param bytes 二进制序列
* @param bitStartPosition 开始读取的位置,从0开始算
* @param bitLength???? 读取长度
* @return 无符号数字
*?
*/?????
public static function readUBits(bytes:ByteArray,bitStartPosition:int,bitLength:int):uint
{
??? var bitBuffer:int;
??? var bitCursor:int;
????
??? var remainLength:int;
??? var result:uint=0;
????
??? bitCursor= bitStartPosition % 8;
??? bytes.position = bitStartPosition / 8;
????
??? if (bitCursor == 0)
??? {
??????? bitBuffer = bytes.readUnsignedByte();
??????? bitCursor = 8;
??? }else{
??????? bitBuffer = bytes.readUnsignedByte();
??????? bitBuffer = bitBuffer & (0xFF >> bitCursor);
??????? bitCursor = 8 - bitCursor;
??? }
????
??? while(bytes.bytesAvailable > 0)
??? {
??????? remainLength = bitLength - bitCursor;
??????? if (remainLength > 0){
??????????? result = result | (bitBuffer << remainLength);
??????????? bitLength -= bitCursor;
??????????? bitBuffer = bytes.readUnsignedByte();
??????????? bitCursor = 8;
??????? }else{
??????????? result = result | (bitBuffer >>-remainLength);
??????????? return result;
??????? }
??? }
????
??? return 0;
}


/**
* 读取一定长度的位?
* 有符号的
*?
* @param bytes 二进制序列
* @param bitStartPosition 开始读取的位置,从0开始算
* @param bitLength 读取长度
* @return 有符号数字
*?
*/?????
public static function readSBits(bytes:ByteArray,bitLength:int):int{
????
??? var result:int = readUBits(bytes,bitStartPosition,bitLength);
????
??? var offset:int = (32 - bitLength);
??? // 补齐符号位
??? result = ((result << offset) >> offset);
????
??? return result;
}


/**
* 读取rect结构
*?
* @param bytes
* @param rect 如果传入,则使用该对象
* @return?
*?
*/?????
public static function readRect(bytes:ByteArray,rect:Rect = null):Rect
{
??? if (rect == null)
??????? rect = new Rect();
????
??? var start:int = bytes.position* 8;
??? var length:uint = readUBits(bytes,start,5);
????
??? rect.xMinTwips = readSBits(bytes,start + 5,length);
??? rect.xMaxTwips = readSBits(bytes,start + 5 + length,length);
??? rect.yMinTwips = readSBits(bytes,start + 5 + length * 2,length);
??? rect.yMaxTwips = readSBits(bytes,start + 5 + length*3,length);
????
??? return rect;
}


然后读取帧率
bytes.position++;// 帧率后8位有效,跳过1个字节(8位)
frameRate = bytes.readByte();

读取总帧数
totalFrames = bytes.readShort();

文件头就解析完成了

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读