/// <summary> /// Get image from the opened XIMEA camera. /// </summary> /// /// <param name="timeout">Maximum time to wait in milliseconds till image becomes available.</param> /// <param name="makeCopy">Make a copy of the camera's image or not.</param> /// /// <returns>Returns image retrieved from the camera.</returns> /// /// <remarks><para>If the <paramref name="makeCopy"/> is set to <see langword="true"/>, then the method /// creates a managed copy of the camera's image, so the managed image stays valid even when the camera /// is closed. However, setting this parameter to <see langword="false"/> creates a managed image which is /// just a wrapper around camera's unmanaged image. So if camera is closed and its resources are freed, the /// managed image becomes no longer valid and accessing it will generate an exception.</para></remarks> /// /// <exception cref="VideoException">An error occurred while communicating with a camera. See error /// message for additional information.</exception> /// <exception cref="NotConnectedException">No camera was opened, so can not access its methods.</exception> /// <exception cref="TimeoutException">Time out value reached - no image is available within specified time value.</exception> /// public Bitmap GetImage( int timeout, bool makeCopy ) { lock ( sync ) { CheckConnection( ); int errorCode; XimeaImage ximeaImage = new XimeaImage( ); unsafe { ximeaImage.StructSize = sizeof( XimeaImage ); } // get image from XIMEA camera try { errorCode = XimeaAPI.xiGetImage( deviceHandle, timeout, ref ximeaImage ); } catch ( AccessViolationException ) { errorCode = 9; } // handle error if any HandleError( errorCode ); // create managed bitmap for the unmanaged image provided by camera PixelFormat pixelFormat = PixelFormat.Undefined; int stride = 0; switch ( ximeaImage.PixelFormat ) { case ImageFormat.Grayscale8: pixelFormat = PixelFormat.Format8bppIndexed; stride = ximeaImage.Width; break; case ImageFormat.RGB24: pixelFormat = PixelFormat.Format24bppRgb; stride = ximeaImage.Width * 3; break; case ImageFormat.RGB32: pixelFormat = PixelFormat.Format32bppRgb; stride = ximeaImage.Width * 4; break; default: throw new VideoException( "Unsupported pixel format." ); } Bitmap bitmap = null; if ( !makeCopy ) { bitmap = new Bitmap( ximeaImage.Width, ximeaImage.Height, stride, pixelFormat, ximeaImage.BitmapData ); } else { bitmap = new Bitmap( ximeaImage.Width, ximeaImage.Height, pixelFormat ); // lock destination bitmap data BitmapData bitmapData = bitmap.LockBits( new Rectangle( 0, 0, ximeaImage.Width, ximeaImage.Height ), ImageLockMode.ReadWrite, pixelFormat ); int dstStride = bitmapData.Stride; int lineSize = Math.Min( stride, dstStride ); unsafe { byte* dst = (byte*) bitmapData.Scan0.ToPointer( ); byte* src = (byte*) ximeaImage.BitmapData.ToPointer( ); if ( stride != dstStride ) { // copy image for ( int y = 0; y < ximeaImage.Height; y++ ) { Accord.SystemTools.CopyUnmanagedMemory( dst, src, lineSize ); dst += dstStride; src += stride; } } else { Accord.SystemTools.CopyUnmanagedMemory( dst, src, stride * ximeaImage.Height ); } } // unlock destination images bitmap.UnlockBits( bitmapData ); } // set palette for grayscale image if ( ximeaImage.PixelFormat == ImageFormat.Grayscale8 ) { ColorPalette palette = bitmap.Palette; for ( int i = 0; i < 256; i++ ) { palette.Entries[i] = Color.FromArgb( i, i, i ); } bitmap.Palette = palette; } return bitmap; } }
public static extern int xiGetImage(IntPtr deviceHandle, int timeout, [In, MarshalAs(UnmanagedType.Struct)] ref XimeaImage image);