获取Flash动画文件SWF的图像帧宽度、高度和Flash播放速率

    前不久,研究了Flash动画文件SWF的数据结构,喜欢编写Flash播放器的朋友可以借鉴。SWF文件开头三个字节为“FWS”(表示未压缩过),或者为“CWS”(表示从第9个字节起的数据用Zlib压缩过)。第4个字节为Flash的版本号,5-8字节为SWF源文件字节大小(压缩前的),第9个字节为Flash的宽度与高度控制码,控制码的不同,后面存储宽度与高度的数据区所占的字节长度也不一样。程序如下(zlibwapi.dll可以到网上去下载一个):

'类文件:Getswffilesize.cls
Option Explicit
Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
Private Declare Function compressAPI Lib "zlibwapi.dll" Alias "compress" (ByRef dest As Any, ByRef destLen As Long, ByRef Source As Any, ByVal sourceLen As Long) As Long
Private Declare Function compressBound Lib "zlibwapi.dll" (ByVal sourceLen As Long) As Long
Private Declare Function uncompressAPI Lib "zlibwapi.dll" Alias "uncompress" (ByRef dest As Any, ByRef destLen As Long, ByRef Source As Any, ByVal sourceLen As Long) As Long
Private Declare Function adler32 Lib "zlibwapi.dll" (ByVal adler As Long, ByRef buf As Any, ByVal length As Long) As Long
Private Declare Function crc32 Lib "zlibwapi.dll" (ByVal crc As Long, ByRef buf As Any, ByVal length As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Private Const Z_OK As Long = &H0&
Private Const Z_ERROR As Long = -&H1&
Private Const Z_BUF_ERROR As Long = -&H5&

'规定字符串长度为2
Private Function Definestrlen(ByVal s As String) As String
    If Len(s) < 2 Then
       s = "0" & s
    Else
       s = s
    End If
    Definestrlen = s
End Function

'取得Flash动画文件SWF帧的分辨率大小、播放速率大小
Public Function GetFlashFileSize(ByVal SWFfile As String, ByRef SWFWidth As Long, ByRef SWFHeight As Long, ByRef SWFPlayRate As Double) As Long
    Dim FNum As Long, Temp As String, i As Long
    Dim refBuffer() As Byte, destBuffer() As Byte, origBytes() As Byte
    Dim origSize As Long '源文件字节大小
    Dim FlashW As Long, FlashH As Long 'Flash宽度,高度
    Dim Flashrate As Double 'Flash播放速率
    Dim OutCRC As Long 'CRC32校验
        
    If Not fileExist(SWFfile) Then Exit Function  '文件不存在则退出
    
    '将长文件名转换成短文件名
    Temp = String(LenB(SWFfile), Chr(0))
    GetShortPathName SWFfile, Temp, Len(Temp)
    Temp = Left(Temp, InStr(Temp, Chr(0)) - 1)
    
    FNum = FreeFile()
    Open Temp For Binary Access Read Lock Write As #FNum
    ReDim refBuffer(0 To (LOF(FNum) - 1)) As Byte
    ReDim destBuffer(0 To UBound(refBuffer) - 8)
    Get #FNum, , refBuffer() '取得文件所有内容
    Get #FNum, 9, destBuffer() '取得压缩字节流(文件头为CWS)
    Close #FNum
    
    If Hex$(refBuffer(0)) = "46" And Hex$(refBuffer(1)) = "57" And Hex$(refBuffer(2)) = "53" Then
       '文件头为FWS
       Debug.Print "文件头为FWS"
       Temp = ""
       Select Case Hex$(refBuffer(8))
           Case "50"
                For i = 9 To 13
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13))
                Next
                FlashW = CLng("&H" & Definestrlen(Hex$(refBuffer(9))) & Definestrlen(Hex$(refBuffer(10)))) / 10
                FlashH = CLng("&H" & Mid$(Temp, 6, 4)) / 10
                Flashrate = refBuffer(15)
           Case "58"
                For i = 9 To 14
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 2, 4)) / 40
                FlashH = CLng("&H" & Mid$(Temp, 7, 4)) / 10
                Flashrate = refBuffer(16)
           Case "60"
                For i = 9 To 14
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 2, 4)) / 10
                FlashH = CLng("&H" & Mid$(Temp, 8, 4)) / 10
                Flashrate = refBuffer(16)
           Case "68"
                For i = 9 To 15
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14)) & Hex$(refBuffer(15))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 3, 4)) / 40
                FlashH = CLng("&H" & Mid$(Temp, 9, 4)) / 10
                Flashrate = refBuffer(17)
           Case "70"
                For i = 9 To 15
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14)) & Hex$(refBuffer(15))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 3, 4)) / 10
                FlashH = CLng("&H" & Mid$(Temp, 10, 4)) / 10
                Flashrate = refBuffer(17)
           Case "78"
                For i = 9 To 16
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14)) & Hex$(refBuffer(15)) & Hex$(refBuffer(16))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 4, 4)) / 40
                FlashH = CLng("&H" & Mid$(Temp, 11, 4)) / 10
                Flashrate = refBuffer(18)
           Case "80"
                For i = 9 To 16
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14)) & Hex$(refBuffer(15)) & Hex$(refBuffer(16))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 4, 4)) / 10
                FlashH = CLng("&H" & Mid$(Temp, 12, 4)) / 10
                Flashrate = refBuffer(18)
           Case "88"
                For i = 9 To 17
                    Temp = Temp & Definestrlen(Hex$(refBuffer(i)))
                    'Hex$(refBuffer(9)) & Hex$(refBuffer(10)) & Hex$(refBuffer(11)) & Hex$(refBuffer(12)) & Hex$(refBuffer(13)) & Hex$(refBuffer(14)) & Hex$(refBuffer(15)) & Hex$(refBuffer(16)) & Hex$(refBuffer(17))
                Next
                FlashW = CLng("&H" & Mid$(Temp, 3, 6)) / 40
                FlashH = CLng("&H" & Mid$(Temp, 13, 4)) / 10
                Flashrate = refBuffer(19)
       End Select
       Debug.Print Hex$(refBuffer(8)), FlashW & " X " & FlashH, Flashrate, Temp
       GetFlashFileSize = True
    Else
       If Hex$(refBuffer(0)) = "43" And Hex$(refBuffer(1)) = "57" And Hex$(refBuffer(2)) = "53" Then
          '文件头为CWS
          Debug.Print "文件头为CWS"
          origSize = CLng("&H" & Hex$(refBuffer(7)) & Hex$(refBuffer(6)) & Hex$(refBuffer(5)) & Hex$(refBuffer(4)))
          'Debug.Print origSize
          '已知原字节流大小解压缩
          If uncompress(destBuffer, origSize - 8, OutCRC, origBytes) = Z_OK Then
             'Debug.Print "outcrc = &H" & Hex(outcrc), UBound(origBytes) + 1
             Temp = ""
             Select Case Hex$(origBytes(0))
                 Case "50"
                      For i = 1 To 5
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5))
                      Next
                      FlashW = CLng("&H" & Definestrlen(Hex$(origBytes(1))) & Definestrlen(Hex$(origBytes(2)))) / 10
                      FlashH = CLng("&H" & Mid$(Temp, 6, 4)) / 10
                      Flashrate = origBytes(7)
                 Case "58"
                      For i = 1 To 6
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 2, 4)) / 40
                      FlashH = CLng("&H" & Mid$(Temp, 7, 4)) / 10
                      Flashrate = origBytes(8)
                 Case "60"
                      For i = 1 To 6
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 2, 4)) / 10
                      FlashH = CLng("&H" & Mid$(Temp, 8, 4)) / 10
                      Flashrate = origBytes(8)
                 Case "68"
                      For i = 1 To 7
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6)) & Hex$(origBytes(7))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 3, 4)) / 40
                      FlashH = CLng("&H" & Mid$(Temp, 9, 4)) / 10
                      Flashrate = origBytes(9)
                 Case "70"
                      For i = 1 To 7
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6)) & Hex$(origBytes(7))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 3, 4)) / 10
                      FlashH = CLng("&H" & Mid$(Temp, 10, 4)) / 10
                      Flashrate = origBytes(9)
                 Case "78"
                      For i = 1 To 8
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6)) & Hex$(origBytes(7)) & Hex$(origBytes(8))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 4, 4)) / 40
                      FlashH = CLng("&H" & Mid$(Temp, 11, 4)) / 10
                      Flashrate = origBytes(10)
                 Case "80"
                      For i = 1 To 8
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6)) & Hex$(origBytes(7)) & Hex$(origBytes(8))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 4, 4)) / 10
                      FlashH = CLng("&H" & Mid$(Temp, 12, 4)) / 10
                      Flashrate = origBytes(10)
                 Case "88"
                      For i = 1 To 9
                          Temp = Temp & Definestrlen(Hex$(origBytes(i)))
                          'Hex$(origBytes(1)) & Hex$(origBytes(2)) & Hex$(origBytes(3)) & Hex$(origBytes(4)) & Hex$(origBytes(5)) & Hex$(origBytes(6)) & Hex$(origBytes(7)) & Hex$(origBytes(8)) & Hex$(origBytes(9))
                      Next
                      FlashW = CLng("&H" & Mid$(Temp, 3, 6)) / 40
                      FlashH = CLng("&H" & Mid$(Temp, 13, 4)) / 10
                      Flashrate = origBytes(11)
             End Select
             Debug.Print Hex$(origBytes(0)), FlashW & " X " & FlashH, Flashrate, Temp
             GetFlashFileSize = True
          Else
             MsgBox "解压缩文件失败!", "提示"
             FlashW = 0: FlashH = 0: Flashrate = 0: GetFlashFileSize = False
          End If
       Else
          MsgBox "未知格式SWF文件!", "提示"
          FlashW = 0: FlashH = 0: Flashrate = 0: GetFlashFileSize = False
       End If
    End If
    SWFWidth = FlashW: SWFHeight = FlashH: SWFPlayRate = Flashrate
    Erase origBytes, refBuffer, destBuffer '释放动态数组所占用的内存
End Function

'压缩字节流
Public Function compress(ByRef inBytes() As Byte, ByVal BufferSize As Long, ByRef incrc As Long, ByRef outBytes() As Byte) As Long
    If BufferSize > 0 Then
        incrc = crc32(crc32(0, ByVal 0&, 0), inBytes(0), BufferSize)
    
        Dim outLength As Long
        outLength = compressBound(BufferSize)
    
        ReDim outBytes(0 To outLength - 1) As Byte
    
        Dim ret As Long
        ret = compressAPI(outBytes(0), outLength, inBytes(0), BufferSize)
        Erase inBytes
        If ret = Z_OK Then
            ReDim Preserve outBytes(0 To outLength - 1)
            compress = ret
        Else
            compress = Z_ERROR
        End If
    End If
End Function

'已知原字节流大小,解压缩字节数组
Public Function uncompress(ByRef inBytes() As Byte, ByVal BufferSize As Long, ByRef OutCRC As Long, ByRef outBytes() As Byte) As Long
    ReDim outBytes(0 To (BufferSize - 1)) As Byte
    Dim ret As Long
    ret = uncompressAPI(outBytes(0), BufferSize, inBytes(0), UBound(inBytes) + 1)
    Erase inBytes
    If (ret = Z_OK) Then
        ReDim Preserve outBytes(0 To (BufferSize - 1))
        OutCRC = crc32(crc32(0, ByVal 0&, 0), outBytes(0), BufferSize)
        uncompress = Z_OK
    Else
        uncompress = Z_ERROR
    End If
End Function

'原字节流大小未知,解压缩字节数组
Public Function uncompressEx(ByRef inBytes() As Byte, ByRef OutCRC As Long, ByRef outBytes() As Byte, ByVal multiple As Integer) As Long
    Dim inLength As Long
    inLength = UBound(inBytes) + 1
    Dim gzSize As Long
    gzSize = multiple * inLength
    Dim outBuffer As Long
    Dim ret As Long
    Do
        outBuffer = gzSize
        ReDim outBytes(0 To (outBuffer - 1)) As Byte
        ret = uncompressAPI(outBytes(0), outBuffer, inBytes(0), inLength)
        gzSize = gzSize + inLength
    Loop While ret = Z_BUF_ERROR
    Erase inBytes
    If (ret = Z_OK) Then
        ReDim Preserve outBytes(0 To (outBuffer - 1))
        OutCRC = crc32(crc32(0, ByVal 0&, 0), outBytes(0), outBuffer)
        uncompressEx = Z_OK
    Else
        uncompressEx = Z_ERROR
    End If
End Function

'读出文件到字节流
Public Function fileToBuffer(ByVal inFile As String, ByRef outBuffer() As Byte) As Long
    ' make sure file exists
    If (Not fileExist(inFile)) Then Exit Function
    Dim FNum As Integer
    FNum = FreeFile()
    
    Open inFile For Binary Access Read Lock Write As #FNum
    ReDim refBuffer(0 To (LOF(FNum) - 1)) As Byte ' allocate buffer
    Get #FNum, , refBuffer() ' read file data into buffer
    Close #FNum
    
    ' return array
    outBuffer = refBuffer
    fileToBuffer = UBound(refBuffer) + 1
End Function

'将字节流保存到文件
Public Function flushToFile(ByVal inFile As String, ByRef outBuffer() As Byte) As Long
    If (fileExist(inFile)) Then Kill inFile
    Open inFile For Output As #1: Close #1 'create empty file
    
    Dim FNum As Integer
    FNum = FreeFile() ' get a free file handle
    Open inFile For Binary Access Write As #FNum
    Put #FNum, , outBuffer() 'flush buffer to local file
    Close #FNum
End Function

Private Sub ArrayCopy(ByRef arrSrc() As Byte, ByVal srcPos As Long, ByRef arrDest() As Byte, ByVal destPos As Long, ByVal length As Long)
    'make sure srcPos >= LBound(arrSrc) and srcPos + length < UBound(arrSrc) +1
    'make sure destPos >= LBound(arrDest) and destPos + length < UBound(arrDest) +1
    CopyMemory arrDest(destPos), arrSrc(srcPos), length
End Sub

Private Function WriteBuffer(buffer() As Byte, ByVal srcPos As Long, ByVal length As Long) As Byte()
    ReDim retBuffer(length - 1) As Byte
    CopyMemory retBuffer(0), buffer(srcPos), length
    WriteBuffer = retBuffer
End Function

'检测文件是否存在
Public Function fileExist(ByRef inFile As String) As Boolean
    On Error Resume Next
    fileExist = CBool(FileLen(inFile) + 1)
End Function


调用方法:

Option Explicit
'Form1窗体代码
Private Sub Command1_Click()
    Dim cFlash As New Getswffilesize
    Dim W As Long, H As Long, Rate As Double
    Call cFlash.GetFlashFileSize("D:\移动备份\歌曲\今天下载\爱很简单.swf", W, H, Rate)
    Debug.Print W, H, Rate
    Set cFlash = Nothing
End Sub


 

 

 


 

你可能感兴趣的:(多媒体)