F-IN-BOX Blog

F-IN-BOX News, Tips and Tricks

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



1
Author:  admin | Date:  13 August, 2007 | Time:  2:49 am

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

2
Author:  Vyacheslav | Date:  26 December, 2007 | Time:  6:24 am

What about Perl version?

3
Author:  admin | Date:  26 December, 2007 | Time:  5:32 pm

Unfortunaly, I haven’t version for Perl…

4
Author:  selee | Date:  26 September, 2008 | Time:  5:38 am

Thank you so much..
It would be very helpfull to me.



Write a Comment

Note: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>