public Bitmap GetNextFrame( )
{
lock ( sync )
{
if ( file == IntPtr.Zero )
{
throw new System.IO.IOException( "Cannot read video frames since video file is not open." );
}
// get frame at specified position
IntPtr DIB = Win32.AVIStreamGetFrame( getFrame, position );
if ( DIB == IntPtr.Zero )
throw new VideoException( "Failed getting frame." );
Win32.BITMAPINFOHEADER bitmapInfoHeader;
// copy BITMAPINFOHEADER from unmanaged memory
bitmapInfoHeader = (Win32.BITMAPINFOHEADER) Marshal.PtrToStructure( DIB, typeof( Win32.BITMAPINFOHEADER ) );
// create new bitmap
Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb );
// lock bitmap data
BitmapData imageData = image.LockBits(
new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb );
// copy image data
int srcStride = imageData.Stride;
int dstStride = imageData.Stride;
// check image direction
if ( bitmapInfoHeader.height > 0 )
{
// it`s a bottom-top image
int dst = imageData.Scan0.ToInt32( ) + dstStride * ( height - 1 );
int src = DIB.ToInt32( ) + Marshal.SizeOf( typeof( Win32.BITMAPINFOHEADER ) );
for ( int y = 0; y < height; y++ )
{
Win32.memcpy( dst, src, srcStride );
dst -= dstStride;
src += srcStride;
}
}
else
{
// it`s a top bootom image
int dst = imageData.Scan0.ToInt32( );
int src = DIB.ToInt32( ) + Marshal.SizeOf( typeof( Win32.BITMAPINFOHEADER ) );
// copy the whole image
Win32.memcpy( dst, src, srcStride * height );
}
// unlock bitmap data
image.UnlockBits( imageData );
// move position to the next frame
position++;
return image;
}
}
}