我做了一个解压SWF文件的工具.
但是有点问题.先把原理发来.让大家看看.我在本地建了一个SWF文件。用16进制编写器,分析了。看下面我的分析
我的swf文件的16进制编码如下:
43 57 53 07 76 00 00 00 78 9C AB 60 60 8D 67 60
E0 5F C0 C0 C0 C3 C8 E0 CC F4 FF .. .. .. .. ..
.....
.....(从FF开始到01为数据区,包括FF和01)
.....
.....
................................ 01 B7 D1 12 8A
==================================================================
下面以我的SWF文件结构为例,我们来解析一下。
43 57 53 // swf头文件信息 3字节 CWS为压缩格式,采用zlib压缩..
07 // swf版本号 1字节
38 01 00 00 // 文件长度 4字节 // 计算是反过来算低位在前前8个字节没有压缩,后面全是压缩的。下面的内容就是要解压的内容。78 // 影片宽高数据控制码. -> 控制码对应值看下表.
// 这里的78对应下面550*400
9C AB 60 60 8D 67 60 E0 //影片的宽度与高度数据存放区
// 所占字节数由控制码决定
// 通过78查到的应该是:
//0 0 0 5 5 F 0 0 0 0 0 F A 0 0 0 被压缩了。
5F // 一个字节,作用不详.
C0 // 影片的放影速度 没压缩应该是 0C =12帧/秒。
C0 C0 // ,影片只有一帧. 计算是反过来算低位在前C3 // 作用不详.
C8 // 作用不详.E0 // 背景色中红色值
CC // 背景色中绿色值
F4 // 背景色中蓝色值 FF...01 // 影片数据区 ++ (重点)B7 D1 12 8A // 文件结束符。正常是文件的最后四个字节为40 00 00 00 -----------------------------------------------------------------
下表中将控制码所在的字节分为两部分(高四位和低四位)。高低位不同的组合决定了数据区占用字节数以及不同的高度算法。 相应的控制码后的蓝色条表示数据区所占用的字节。五星代表有效数据(注意每个五星只占半个字节),其中前面几个连续的五星对应的数据记录了高度值,后面几个连续的五星 对应的数据记录了宽度值。 将连续的五星所在位置的数(十六进制)组合起来,得到四位或六位的十六进制数,将此数转换成十进制数,白色五星得到的数除以10就是影片宽度数值,红色五星得到的数除以40就是影片高度数值。 我对每一种控制码都给出一个具体例子,请对比文件中相应的字节和实际的宽度和高度值。控制码对应表 ( 一般就是这几种)
======================================================
控制码 0 1 2 3 4 5 6 7 8 宽×高
50 **** **** 18×18
0 0 B 4 0 0 0 B 4 0
58 **** **** 36×18
0 0 5 A 0 0 0 0 B 4 0 0
60 **** **** 100×48
0 0 3 E 8 0 0 0 1 E 0 0
68 **** **** 160×100
0 0 1 9 0 0 0 0 0 3 E 8 0 0
70 **** **** 400×320
0 0 0 F A 0 0 0 0 0 C 8 0 0
78 **** **** 550×400
0 0 0 5 5 F 0 0 0 0 0 F A 0 0 0
80 **** **** 1600×1200
0 0 0 3 E 8 0 0 0 0 0 2 E E 0 0
88 ****** **** 2880×2880
0 0 0 1 C 2 0 0 0 0 0 0 7 0 8 0 0 0
但是有点问题.先把原理发来.让大家看看.我在本地建了一个SWF文件。用16进制编写器,分析了。看下面我的分析
我的swf文件的16进制编码如下:
43 57 53 07 76 00 00 00 78 9C AB 60 60 8D 67 60
E0 5F C0 C0 C0 C3 C8 E0 CC F4 FF .. .. .. .. ..
.....
.....(从FF开始到01为数据区,包括FF和01)
.....
.....
................................ 01 B7 D1 12 8A
==================================================================
下面以我的SWF文件结构为例,我们来解析一下。
43 57 53 // swf头文件信息 3字节 CWS为压缩格式,采用zlib压缩..
07 // swf版本号 1字节
38 01 00 00 // 文件长度 4字节 // 计算是反过来算低位在前前8个字节没有压缩,后面全是压缩的。下面的内容就是要解压的内容。78 // 影片宽高数据控制码. -> 控制码对应值看下表.
// 这里的78对应下面550*400
9C AB 60 60 8D 67 60 E0 //影片的宽度与高度数据存放区
// 所占字节数由控制码决定
// 通过78查到的应该是:
//0 0 0 5 5 F 0 0 0 0 0 F A 0 0 0 被压缩了。
5F // 一个字节,作用不详.
C0 // 影片的放影速度 没压缩应该是 0C =12帧/秒。
C0 C0 // ,影片只有一帧. 计算是反过来算低位在前C3 // 作用不详.
C8 // 作用不详.E0 // 背景色中红色值
CC // 背景色中绿色值
F4 // 背景色中蓝色值 FF...01 // 影片数据区 ++ (重点)B7 D1 12 8A // 文件结束符。正常是文件的最后四个字节为40 00 00 00 -----------------------------------------------------------------
下表中将控制码所在的字节分为两部分(高四位和低四位)。高低位不同的组合决定了数据区占用字节数以及不同的高度算法。 相应的控制码后的蓝色条表示数据区所占用的字节。五星代表有效数据(注意每个五星只占半个字节),其中前面几个连续的五星对应的数据记录了高度值,后面几个连续的五星 对应的数据记录了宽度值。 将连续的五星所在位置的数(十六进制)组合起来,得到四位或六位的十六进制数,将此数转换成十进制数,白色五星得到的数除以10就是影片宽度数值,红色五星得到的数除以40就是影片高度数值。 我对每一种控制码都给出一个具体例子,请对比文件中相应的字节和实际的宽度和高度值。控制码对应表 ( 一般就是这几种)
======================================================
控制码 0 1 2 3 4 5 6 7 8 宽×高
50 **** **** 18×18
0 0 B 4 0 0 0 B 4 0
58 **** **** 36×18
0 0 5 A 0 0 0 0 B 4 0 0
60 **** **** 100×48
0 0 3 E 8 0 0 0 1 E 0 0
68 **** **** 160×100
0 0 1 9 0 0 0 0 0 3 E 8 0 0
70 **** **** 400×320
0 0 0 F A 0 0 0 0 0 C 8 0 0
78 **** **** 550×400
0 0 0 5 5 F 0 0 0 0 0 F A 0 0 0
80 **** **** 1600×1200
0 0 0 3 E 8 0 0 0 0 0 2 E E 0 0
88 ****** **** 2880×2880
0 0 0 1 C 2 0 0 0 0 0 0 7 0 8 0 0 0
解决方案 »
- 移动侦测技术怎么实现?
- 推荐好书就给分
- 关于sendarp的用法,想从IP直接得到MAC地址
- 关于fast repotrt的一个极菜简单问题,来者有分,分不够,可以再加(无未结帖记录)
- 关于TChart的中文使用说明
- Delphi 6 启动时,出现提示注册的对话框,惨啊,不知怎么注册?
- VB老手,Delphi菜鸟,初级问题请关注?
- 报考初级程序员必须用C语言吗?DELPHI不行吗?
- 征集Delphi爱好者的E-Mail,不管你是爱好者还是高手请写出你的E-Mail最好还加上QQ,以便大家交流!
- 怪问题,高分相送,程序的某一个窗体在运行一段时间后便消失了,不能显示了,谁能指点?
- 关于ComboBox的显示风格
- Filter退出查询问题
unit MainUnit;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ComCtrls,zLib;type
TMainFrm = class(TForm)
GroupBox1: TGroupBox;
Label1: TLabel;
swfPathET: TEdit;
Label2: TLabel;
SpeedButton1: TSpeedButton;
iCode: TEdit;
SpeedButton2: TSpeedButton;
infoM: TMemo;
SB: TStatusBar;
OpenDialog: TOpenDialog;
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
MainFrm: TMainFrm;implementation
Const
selectSWF = '请选择文件!';
inputmmcode = '请输插入代码!';
NotSWFFile = '选择的文件不是有效的SWF文件!';
var
fFlag : string;
fversion : string;
fLength,zipLength : integer;{$R *.dfm}procedure Showmsg(msg : string);
begin
application.MessageBox(pchar(msg),'提示',mb_ok+mb_iconinformation);
end;Function unzipswf(swfStream : TMemoryStream;var unZipStream : TMemoryStream) : boolean;
var
fheard: array[0..7] of char;
fbody : pchar;
count : integer;
SourceStream : TDecompressionStream;
DestStream : TMemoryStream;
procedure parseheard;
begin
fFlag := fheard[0]+fheard[1]+fheard[2];
fversion := IntToStr(ord(fheard[3]));
flength := (ord(fheard[7]) * $ffffff) +(ord(fheard[6]) *$ffff)
+(ord(fheard[5])* $ff) +ord(fheard[4]);
zipLength := flength -8 ; // 解压文件的长度.
end;
begin
result := False;
swfStream.Position := 0;
swfStream.Read(fheard,sizeof(fheard));
parseheard;
if (fFlag <> 'FWS') and (fFlag <> 'CWS') then begin
ShowMsg(NotSWFFile);
exit;
end;
if fFlag = 'FWS' then unZipStream := swfStream;
if fFlag = 'CWS' then begin // 压缩的格式,现在解压.
DestStream := TMemoryStream.Create;
Try
count := swfStream.Read(fbody,sizeof(fbody));
while count > 0 do begin
DestStream.Write(fbody,sizeof(fbody)); //读出从第9字节开始后的内容.进行解压.
count := swfStream.Read(fbody,sizeof(fbody));
end;
destStream.SaveToFile('c:\abc.swf');
destStream.Position := 0; SourceStream := TDecompressionStream.Create(destStream);
try
count := SourceStream.Read(fbody,sizeof(fbody));
unZipStream.Position := 0;
while count > 0 do begin
unZipStream.Write(fbody, count);
count := SourceStream.Read(fbody,sizeof(fbody));
//我总认为上面这句有问题.请大家帮我看看.
end;
finally
SourceStream.Free;
end;
finally
DestStream.Free;
end;
end;
result := true;
end;procedure TMainFrm.SpeedButton1Click(Sender: TObject);
begin
if OpenDialog.Execute then
swfpathET.Text := OpenDialog.FileName;
end;procedure TMainFrm.SpeedButton2Click(Sender: TObject);
function CheckUserInput : Boolean;
begin
result := false;
if trim(swfpathet.Text) = '' then begin
Showmsg(selectSWF);
exit;
end;
if trim(icode.Text) = '' then begin
showmsg(inputmmcode);
exit;
end;
result := true;
end;
var
swfStream : TMemoryStream;
unzipStream : TMemoryStream;
begin
if CheckUserInput then begin
swfStream := TMemorystream.Create;
swfStream.LoadFromFile(swfpathet.text);
unzipStream := TMemoryStream.Create;
if unzipswf(swfStream,unZipStream) then
unZipStream.SaveToFile('c:\px.swf'); // 这个是测试用的,生成解压的内容来看.
unZipStream.Free;
swfStream.free;
end;
end;end.
////////////////////
程序读取压缩长度是4的倍数是可以正常解压文件.
但是其他的好像不行.会出现假死状态.
请大家帮我解决下.
谢谢....
//
// RestoreCompressed 转化压缩过的影片
//
// sSwfName 影片文件名称
//
// 另外,本函数用到了两个外部变量: FileLength, FileBuf
// 本函数改写了它们的值
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
function RestoreCompressed( sSwfName, sSaveName: String ): Boolean;
var
f,fw : File;
fws : string[3]; //标示信息
version : Byte; //SWF文件版本号
CurrentPos : Integer; //内存读写位置
zStream : TDecompressionStream; //实现压缩数据还原
inStream : TMemoryStream; //压缩数据流
begin
Result := FALSE; FileMode := fmOpenRead;
AssignFile( f, sSwfName );
Reset( f,1 );
SetLength( FileBuf, FileSize(f) );
BlockRead( f,FileBuf[0], Filesize(f) ); //将文件读入内存
CloseFile( f ); //下面为读取SWF文件的文件头Header部分
CurrentPos:=0;
//读取'FWS'标示
SetLength(fws,3);
Move( FileBuf[CurrentPos], fws[1], 3 );
Inc( CurrentPos, 3 );
if fws <> 'CWS' then
begin
SetLength( FileBuf,0 );
ShowMessage('This SWF is not compressed.');
exit;
end; //读取版本号
Move( FileBuf[CurrentPos], version, Sizeof(version) );
Inc( CurrentPos, Sizeof(version) );
if Version < VERSION_ALLOW then
begin
SetLength(FileBuf,0);
ShowMessage('This SWF version is not 5 or higher, can not be operated currently.');
exit;
end;
//读取SWF文件长度
Move( FileBuf[CurrentPos] ,FileLength,Sizeof(FileLength) );
Inc( CurrentPos, Sizeof(FileLength) );
//FileBuf下面的内容都是压缩数据
inStream := TMemoryStream.Create;
//将压缩数据读入inStream压缩数据流
inStream.Write( FileBuf[CurrentPos], Length(FileBuf)-3-Sizeof(version)-Sizeof(FileLength) );
inStream.Position := 0;
//实现还原
zStream:=TDecompressionStream.Create( inStream );
//数据还原后所需缓冲区长度会加长
SetLength(FileBuf,FileLength);
//将还原的数据写会缓冲区
zStream.Read( FileBuf[3+Sizeof(version)+Sizeof(FileLength)],
FileLength-3-Sizeof(version)-Sizeof(FileLength) );
zStream.Free;
inStream.Free;
fws := 'FWS';
//将原CWS改为FWS
Move( fws[1], FileBuf[0],3 ); AssignFile( fw, sSaveName );
ReWrite( fw,1 );
BlockWrite( fw,FileBuf[0],Length(FileBuf) );
CloseFile( fw );
SetLength( FileBuf,0 ); Result := TRUE;
end;const
VERSION_ALLOW = 5; // 可处理的最低影片版本
FileBuf : Array of Byte; // 将SWF文件读入内存存放