Bitmaps to videos |
Written by Harry Fairhead | ||||||
Tuesday, 21 July 2009 | ||||||
Page 4 of 5
Getting the compressionNow we have a stream we could start storing bitmaps in it – but few video players, and certainly not Windows Media Player, actually know how to handle an uncompressed stream. We therefore have to create a compressed stream from the uncompressed stream and the simplest way of doing this is to let the user select from a dialog box that the API provides. This is the reason we needed the hwnd parameter in the constructor to allow the dialog box to have a reference to its parent window. The compression dialog
First we need a structure to define the compression options: [StructLayout(LayoutKind.Sequential,
The API function that displays the dialog box is defined as:
[DllImport("avifil32.dll")] The last two parameters are different from anything used so far and likely to cause trouble if you don’t treat them correctly. Both ppavi and ppOptions are pointers to pointers. As a result we have to pin the memory areas to which they refer to stop them being moved by the Garbage Collector. We also need some unmanaged memory for the API function to use to store the user’s selections. This can be provided using the AllocHGlobal method of the Marshal object: IntPtr buf = Marshal.AllocHGlobal( Next we need to get a handle, basically a pointer, to this area of memory and pin it: GCHandle handle1 = GCHandle.Alloc( We can now call the API function: result = AVISaveOptions( The constants used are: private const int Finally we transfer the selection made by the user to the structure and free the memory and the handle to the memory:
AVICOMPRESSOPTIONS opts = If the user presses the OK button the result of the function is one. Now we have to make the compressed stream using the options selected by the user and then set its format. The two functions needed for this are: [DllImport("avifil32.dll")] [DllImport("avifil32.dll")] To make the compressed stream we simply use: result = AVIMakeCompressedStream( which returns a pointer, pStream, to the compressed stream. To set the format of the compressed stream we need to use the bitmap information header and as before this needs to be pinned before being passed to the API: handle = GCHandle.Alloc(bm.bmIH, The final API call writes the first bitmap’s data to the compressed stream and this has to be pinned before use: handle = GCHandle.Alloc(bm.bmIH, We also need a global variable to keep track of the number of frames written: private int FrameCount = 0; and a definition for the constant: private const int AVIIF_KEYFRAME = 0x00000010; And we also need to remember to set it to one after successfully writing one frame: FrameCount = 1; The definition of the API function is: [DllImport("avifil32.dll")] Additional frames and clean upThe FirstFrame method is quite long because as well as storing the first frame it also has to set everything up. The NextFrame method is much simpler because all we have to do is read the next bitmap and then write it to the stream: public void NextFrame(string BMPFile) Before the program ends we have to close the streams and the file: public void closeAll() The API functions are defined as: [DllImport("avifil32.dll")] <ASIN:0735618216> <ASIN:0735611807> <ASIN:0672329638>
|
||||||
Last Updated ( Tuesday, 21 July 2009 ) |