swf檔案格式(結構)

來源:互聯網
上載者:User

這個在自己開發協助工具輔助時很有用啊,轉來學習一下

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了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.