Monday, August 27, 2007

How to create Flash Projector?

What's Flash projector? In brief, it's an application that converts flash files (SWF, FLV) to executable files (EXE). There are few such products in the market. For example, Flajector.

So how to create flash projector. The most important tasks you should to solve:

1. Embedding flash activex (ocx) in an EXE.
2. Working without accessing to TEMP directory. Another words, no temporary files are created during application life.
3. It should be compatible with all Windows versions: 98 and so on.

Sometime ago I found a good framework that helps to solve all these tasks. It's F-IN-BOX. There are few editions: Delphi Edition, DLL Edition, .NET Edition.

As soon as I know, Janus uses f-in-box .NET Edition.

UPDATE: Oh yeah, Flajector also uses f-in-box (DLL Edition, I think so).

Extract size from SWF file

Original news here

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 < intbyteindex =" intBitPos" nbyte =" lpBytes[intByteIndex];" intlocalbitindex =" 7" intbitvalue =" ((nByte">> intLocalBitIndex) & 1);

if (0 == intBitIndex)
intSign = 1 == intBitValue ? -1 : +1;
else
{
intResult <<= 1;
intResult += intBitValue;
}
}

intResult *= intSign;

return intResult;
}