這個在自己開發協助工具輔助時很有用啊,轉來學習一下
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 是個“塊”,這裡羅嗦一下,檔案體是由大量的塊組成的,這些塊內容獨立,一起配合顯示動畫,比如有的塊表示了一個矩形,有的Block Storage了一段音樂,有的塊表示了此處為一幀,等等。 塊,組成了檔案體,但每一個塊都是可以割捨的,這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了。