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 FPS |
FrameCount | UI16 | Total number of frames in movie |
If an SWF file begins with "CWS"
, the header is compressed (zipped). You should unzip it using something like zlib.
Here’s the sample code in C++:
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;
char chFirstByte;
ReadFile(hFile, (LPVOID)&chFirstByte, sizeof(chFirstByte), &dwNumberOfBytesRead, NULL);
const DWORD dwOffset = 3 + 1 + 4;
SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN);
char outbuffer[256];
if (chFirstByte == 'C') // Compressed
{
char buffer[256];
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, Z_SYNC_FLUSH);
inflateEnd(&stream);
}
else
{
ReadFile(hFile, outbuffer, sizeof(outbuffer), &dwNumberOfBytesRead, NULL);
}
unsigned char nByte = outbuffer[0];
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<LPBYTE>(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 (intBitIndex == 0)
intSign = (intBitValue == 1) ? -1 : +1;
else
{
intResult <<= 1;
intResult += intBitValue;
}
}
intResult *= intSign;
return intResult;
}
This method gives you the movie dimensions in pixels by extracting values from the SWF file header.