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. 0×04F 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