swf文件數據格式分析


由於最近項目需要對swf文件進行分析,在網上找了不少資料,也參照了adobe官方發佈的swf file format文檔,但是並不是很明白。後來經過幾天的努力,終於有所頓悟(可憐天生遲鈍,領悟能力比較差吧,那只有勤能補拙,多花點時間了)。下面把這幾 天的努力成果和大家分享一下(其中部分資料是整理自網友,不過由於分不清誰是原創,我也沒法給出完整的原文地址了,部分是經過自己修正的)。在整理網友的 資料時,大部分人的都是在對沒有壓縮的swf文件進行分析的,弄得我自己在測試的時候怎麼總感覺出不來結果。後來繼續查資料才弄明白了怎麼對swf文件進 行解壓縮。自flash 6以後的版本,生成的swf文件都支持壓縮了,所以對於未壓縮的swf文件解析實在是沒有什麼多大用處了。

    下面我們來看一下如何分析的吧!我以經過壓縮的文件進行分析。(其實我也找不到那麼低版本未壓縮的swf文件了)

    swf文件頭信息

   swf文件頭包含的信息量巨大。告訴了人們SWF文件工作的方式方法等基本信息。

       Macromedia Flash文件格式是Macromedia Flash播放器在互聯網上進行矢量圖形和動畫發佈的文件格式。

      SWF文件格式不是爲圖像編輯器之間共享圖像而是爲高效的解釋格式設計的,它的設計是爲了滿足以下條件:

      A:在屏幕上即時顯示:此格式的最主要目標是在屏幕上即時顯示和支持實例,彩色圖像的快速播放,動畫和交互式按鈕。

      B:可擴展性:此格式爲標籤式格式,因此其播放器能夠通過增加新的特性來進行升級而兼容其播放器的早期版本。

      C:網絡發佈:此格式能夠在有限的網絡資源和不可預測的網絡狀況下進行傳輸,文件被壓縮到很小並且支持流式播放。SWF文件是一種二進制格式的文件,它不 能像HTML文件一樣可以直接閱讀和理解。SWF文件使用了諸如位壓縮、可選字段式結構等方法來減小文件的尺寸。

      D:簡易性:此格式簡單的結構使Flash播放器變得很小且便於攜帶。另外,Flash播放器僅僅依賴操作系統特性中有限的集合。

      E:文件獨立性:文件的顯示不依賴任何諸如字體之類的擴展資源。

      F:可變性:文件能夠在有限的硬件環境下很好的工作,而且能夠儘可能的利用更好的硬件,這一點很重要,因爲用戶的計算機有着不同的顯示器設置和色彩深度。

      G:速度:文件能夠以很快的速度和很高的質量播放。

      H:支持腳本:此格式包含了約定格式的標籤,標籤規定了堆棧式機器解釋字節碼的順序。字節碼支持一種叫做ActionScript(動作腳本)的語言。 Flash播放器規定了運行時的ActionScript(動作腳本)模式,此模式允許原始的繪製、服務和Flash播放器特性之間相互作用。

     SWF文件的擴展名爲.swf,它是一種MIME(多用途的網際郵件擴充協議)類型的應用程序(X-Shockwave-Flash)。

     SWF格式經歷了若干個版本。在第5個版本中,SWF的標籤設置經過了一次較大規模的充實和完善。從第6個版本之後,文件格式變化較小,例如僅在 ActionScript中越來越多的Flash新特性部分或者完全的被實現。因此,如果打算增加SWF文件中使用較新特性的內容,那麼就應該熟悉 Flash播放器提供的ActionScript對象模型,對於這些最好的參考是O’Reilly的《ActionScript: the Definitive Guide》,由科林·莫克出版社出版。

     SWF文件頭:所有的SWF文件均以以下頭部開始:

     

文件頭部是由一個三字節的標識符開始,爲0x46、0x57、0x53(“FWS”)或者0x43、0x57、0x53(“CWS”)其中之一。 “FWS”標識符說明該文件是未壓縮的SWF文件,“CWS”標識符則說明該文件前8個字節之後(即文件長度字段之後)的全部數據爲開源的標準ZLIB方 式壓縮。

ZLIB庫所使用的數據格式在1950至1952年的請求註解, Internet標準文檔(RFCS)中被詳細說明。CWF文件壓縮形式僅適用於版本6或者更高。

標識符之後是一個字節的版本號,這個版本號並不是一個ASCII碼,而是一個8位的數字,比如,版本4用0x04標識,而不是ASCII碼“4”(0x35)。

文件長度字段是整個包含文件頭在內的文件字節長度,如果是未壓縮的SWF文件(標識符FWS),那麼長度字段應該是和文件大小恰好匹配,如果是一個 經過壓縮的SWF文件(標識符CWS),那麼文件長度字段是指文件經過解壓縮之後的總長度,因此它一般不會和文件大小匹配,使用未壓縮的文件尺寸能夠讓解 壓過程獲得更高的效率。

幀尺寸字段定義了影片的寬度和高度,它使用了RECT結構進行存儲,這就意味着它的尺寸能夠根據座標編碼所需的位數變化。幀尺寸的RECT結構使用的X和Y軸的最小值總爲0。而X和Y軸最大值分別表示了寬度和高度(參閱位值的使用)

幀率是以幀每秒爲單位的幀回放比率,此比率在SWF文件包含流式聲音數據或者Flash播放器運行在低速CPU下時並不會得到保證。

幀數是整個SWF影片幀的總數量。

SWF文件結構

文件頭之後是一系列連續的標籤數據塊,所有的標籤都共享一種通用格式,因此任何解析SWF文件的程序都能跳過它不能識別的數據塊。塊內數據能夠指向當前一個塊內的偏移量,但不能指向其它數據塊內的偏移量。這就使得標籤能夠被處理SWF文件的工具進行移除、插入或修改操作。

SWF文件格式

===============================================

標籤格式

每個標籤都是由一個類型和一個長度值開始的,存在兩種標籤頭部格式:短格式和長格式。短標籤頭部用於62字節或者更小的標籤數據,長標籤頭部能夠用於任何大小不超過4GB的標籤數據,從長遠來看這將會是非常實用的。

注意:標籤編碼和長度字段並不是一個10位的位字段後面跟着6位的位字段,而是一個雙字節的字,SWF文件不間斷的字節排序使得這兩者具有不同的佈局。

該字段中的長度並不包含標籤開始處的記錄頭部(即該字段所佔有的長度)。

如果標籤的長度大於或者等於63字節,那麼它會被存儲在長標籤頭部。長標籤頭部由一個標識長度爲63字節(0x3f)的短標籤頭部和一個32位的長度組成。

描述標籤和控制標籤

SWF中的標籤分描述標籤和控制標籤兩種:

描述標籤這種標籤描述了SWF影片的內容—形狀、文本、圖像、聲音等等。每個定義標籤都爲其描述的內容指定了一個被稱爲“角色ID”的唯一ID。Flash播放器把這些角色存放在一種叫“字典”的庫裏。描述標籤本身不能驅動某個事件的產生。

控制標籤這種標籤可以創建和驅動字典中角色的實例,控制影片的播放。

SWF文件標籤分類

通常,SWF文件中的標籤可以任意出現。但儘管如此,也必須遵循少數幾個規則:

1、一個標籤只能依賴前面定義過的標籤。任何一個標籤都不能依賴在才後面定義的標籤。

2、描述標籤必須在使用它的任何控制標籤之前定義。

3、流式聲音標籤必須以順序方式存儲。不規範的流式聲音標籤將會導致聲音播放不正常。

4、結束標籤一般是SWF文件的最後一個標籤。

字典

字典是存放已經定義好的角色的庫,它可以被控制標籤所應用。字典的建立和使用應遵循以下規則:

1、描述標籤定義了諸如形狀、字體、位圖或者聲音。

2、每一個描述標籤都被指定一個唯一的角色ID。

3、字典中的內容被存儲在角色ID之後。

4、控制標籤能夠通過角色ID在字典中找到所需內容並對其執行某種操作,例如顯示形狀或者播放聲音。

每個角色ID必須指定一個唯一的ID,不允許重複ID。例如,第一個角色ID是1,第二個是2。角色0被指定爲表示空角色的專用ID。

並不是只有控制標籤才能引用字典。描述標籤同樣也可以使用字典中的數據進行更復雜的角色定義。例如,按鈕和剪輯標籤都使用到了定義它們內容的角色。文本標籤也包含了字體角色以便於爲文本選擇不同的字體。

以下圖表說明了描述標籤、控制標籤和字典之間的一種典型交互關係:

===============================================

* 詳見顯示列表

處理SWF文件

Flash播放器會在遇到“顯示幀”標籤之前處理SWF文件中所有的標籤。這樣,顯示列表將被複制到場景中,在處理下一個幀之前Flash播放器會 一直處於空閒狀態。第一幀的內容是第一個顯示幀之前的所有控制標籤操作所積累的效果。而第二個幀的內容是第二個顯示幀之前的所有控制標籤操作所積累的效 果,依此類推。

文件壓縮策略

由於SWF文件在網絡中的傳輸日趨頻繁,那麼文件被儘可能的壓縮將是非常重要的。有幾種方法可以達到此目的。以下提到幾種方法:

複用角色字典的結構能夠讓SWF文件的元素很方便的得到複用。例如,形狀、按鈕、字體或者位圖可以被一次存儲,多次引用。

壓縮當一條線的起始座標被假定是前一條線的結束座標的時候,形狀能夠使用一種非常有效的三角編碼方式壓縮。距離一般也使用與最後位置的相對關係來表示。

默認值矩陣和顏色轉換式通常擁有比其他結構更爲通用的字段。例如:對於矩陣,轉換字段是它最常用的字段,而縮放比例和旋轉使用比較少。因此如果縮放字段沒有出現,那麼它會被默認爲100%。如果旋轉字段沒有出現,那麼就假定沒有旋轉。使用默認值能夠縮小文件尺寸。

改變編碼按規定,SWF文件只能將變化存放在狀態之間。但顯示列表使用的形狀數據結構和位置、運動、移動模型卻是相反的。

形狀數據結構形狀數據結構使用了唯一的結構來減小文件的尺寸以及非常有效的在場景中播放實名形狀。

概要

SWF文件由頭部和其後的許多標籤組成。有描述標籤和控制標籤兩種。描述標籤定義了被視爲角色的對象,它被定義在字典中。控制標籤操作和使用角色,以及控制影片的流程。

下面來看一個例子,下面是經過壓縮的一個swf文件的二進制文件截圖:

其中的CWS表示文件是經過壓縮的,0A表示文件版本號是10(即flash10)。這是前面四組數字的意思。後面的64 05 00 00四組數字表示了文件的大小。但是這裏它是倒序的,所以其實是00 00 05 64,轉換成10進制就是1380字節了。

現在我們已經解析了前面8個字節,從第9個字節開始,我們來看一下文件的尺寸吧。但由於版本6以後版本的swf文件從第9個字節開始進行了Zlib 壓縮,而我們這裏是flash10因此也是經過Zlib壓縮的。我們對它做Zlib解壓縮一下得到的一連串字節如下(從第9字節開始):

第9字節

 

 

 

 

 

 

 

 

 

 

 

第21字節

78

00

05

5F

00

00

0F

A0

00

00

18

01

00

這樣的話,我們可以來看看文件尺寸了。swf文件的尺寸是採用RECT存儲的,RECT是flash存儲結構的一種。下面來具體看看怎麼獲取尺寸吧。

1.首先把第9個字節轉換成二進制,即爲01111000,取其中前5位數(01111),得到15,這裏爲什麼要取前5位呢?主要是因爲這5位數 存放是RECT結構的各個屬性值的位數,說白一點就是:後面的X軸方向最小值、X軸方向最大值、Y軸方向最小值和Y軸方向最大值需要多少位二進制位存放數 據,這裏得到的是01111(15)。由於尺寸需要存放的數據有X軸方向最小值、X軸方向最大值、Y軸方向最小值和Y軸方向最大值,並且每個數據的位數是 15位,再加上5位表示位數。因此我們至少需要4*15+5=65位來表示文件尺寸,用65/8=8.125,所以我們至少需要9個字節來表示文件的尺 寸。

2.把78 00 05 5F 00 00 0F A0 00等9個字節轉換成二進制爲:

   01111000 00000000 00000101 01011111 00000000 00000000 00001111 10100000 00000000

   先取前5位爲屬性值位數存放數據,然後每15位分隔一下,剩餘的位數爲多餘,捨棄。如下

  

轉換成十進制得到:

X軸方向最小值=0

X軸方向最大值=11000

Y軸方向最小值=0

Y軸方向最大值=8000

所以寬度(width)=(X軸方向最大值-X軸方向最小值)/20=(11000-0)/20=550,高度(height)=(Y軸方向最大值-Y軸方向最小值)/20=(8000-0)/20=400

PS:這裏爲什麼要除以20呢?因爲swf文件中的長度單位是twip,而20twip=1像素。

下面來看一下幀頻,幀頻是用2個字節表示的,即這裏的00 18,轉換成十進制數爲24,則此處幀頻是24。

再來看看下一個幀數吧,幀數也是用2個字節表示的,即這裏的01 00,但是這裏必須採用倒序方式解析,則幀數爲1。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章