How to get a width and a height from an SWF
Many users ask me how to get dimensions of a movie. The answer is simple: just decode an SWF header. All Macromedia Flash (SWF) files begin with the following header (see SWF specification for more information):
Field | Type | Comment |
Signature | UI8 | Signature byte always ‘F’ |
Signature | UI8 | Signature byte always ‘W’ |
Signature | UI8 | Signature byte always ‘S’ |
Version | UI8 | Single byte file version (e.g. 0x04F for SWF 4) |
FileLength | UI32 | Length of entire file in bytes |
FrameSize | RECT | Frame size in twips |
FrameRate | UI16 | Frame delay in 8.8 fixed number of frames per second |
FrameCount | UI16 | Total number of frames in movie |
If an SWF file begins with “CWS”, the header is zipped. Unzip it. Use zlib, for example. The sample code:
SIZE GetFlashMovieSize(LPCTSTR szSWFPath) { SIZE size = { 0 }; HANDLE hFile = CreateFile(szSWFPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE != hFile) { DWORD dwNumberOfBytesRead; // Read the first byte char chFirstByte; ReadFile(hFile, (LPVOID)&chFirstByte, sizeof(chFirstByte), &dwNumberOfBytesRead, NULL); // Skip signature (3 bytes), version (1 byte) and file size (4 bytes) const DWORD dwOffset = 3 + 1 + 4; SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN); char outbuffer[256]; if (67 == chFirstByte) // Compressed { char buffer[256]; DWORD dwNumberOfBytesRead; ReadFile(hFile, buffer, sizeof(buffer), &dwNumberOfBytesRead, NULL); z_stream stream = { 0 }; stream.next_in = (Bytef*)buffer; stream.avail_in = 256; stream.next_out = (Bytef*)outbuffer; stream.avail_out = 256; inflateInit(&stream); inflate(&stream, 1); inflateEnd(&stream); } else { DWORD dwNumberOfBytesRead; ReadFile(hFile, outbuffer, sizeof(outbuffer), &dwNumberOfBytesRead, NULL); } unsigned char nByte = outbuffer[0]; // How many bits each number occupy unsigned char intBits = nByte >> 3; int intTotalBits = intBits * 4 + 5; int intTotalBytes = (intTotalBits + 7) / 8; unsigned char * pnBytes = new unsigned char [intTotalBytes]; CopyMemory(pnBytes, outbuffer, min(intTotalBytes, sizeof(outbuffer))); int intOffset = 5; int intXMin = GetIntegerFromBits(pnBytes, intOffset, intBits) / 20; int intXMax = GetIntegerFromBits(pnBytes, intOffset + intBits, intBits) / 20; int intYMin = GetIntegerFromBits(pnBytes, intOffset + 2 * intBits, intBits) / 20; int intYMax = GetIntegerFromBits(pnBytes, intOffset + 3 * intBits, intBits) / 20; size.cx = intXMax - intXMin; size.cy = intYMax - intYMin; delete[] pnBytes; CloseHandle(hFile); } return size; } int GetIntegerFromBits(LPVOID lpData, int intOffset, int intLength) { int intResult = 0; LPBYTE lpBytes = static_cast(lpData); int intBitIndex = 0; int intSign; for (int intBitPos = intOffset; intBitPos < intOffset + intLength; intBitPos++, intBitIndex++) { int intByteIndex = intBitPos / 8; __int8 nByte = lpBytes[intByteIndex]; int intLocalBitIndex = 7 - intBitPos % 8; int intBitValue = ((nByte >> intLocalBitIndex) & 1); if (0 == intBitIndex) intSign = 1 == intBitValue ? -1 : +1; else { intResult <<= 1; intResult += intBitValue; } } intResult *= intSign; return intResult; }
Comments
PHP version
[source:php]
function b2i($d,$o,$l) {
$s=(ord($d[$o/8])>>(7-$o%8))&1; $r=0;
for ($i=$o+1;$i>(7-$i%8))&1;
$r=($r”;
$s=unpack(“V”,substr($d,4,4)); echo “FileSize : “.$s[1].” bytes”;
if (substr($d,0,3)==”CWS”) $d=substr($d,0,8).gzinflate(substr($d,8));
$nb=ord($d[8])>>3; // bytes needed
echo “Bytes required : “.$nb.””;
echo “width=”.(($this->b2i($d,8*8+5+$nb,$nb)-$this->b2i($d,8*8+5,$nb))/20).””;
echo “height=”.(($this->b2i($d,8*8+5+3*$nb,$nb)-$this->b2i($d,8*8+5+2*$nb,$nb))/20).””;
echo “”;
[/source]
—
Thanks to TCK
What about Perl version?
Unfortunaly, I haven’t version for Perl…
Thank you so much..
It would be very helpfull to me.
Write a Comment