//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ namespace Microsoft.Samples.Kinect.DepthBasics { using System; using System.Globalization; using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Kinect; /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { /// /// Active Kinect sensor /// private KinectSensor sensor; /// /// Bitmap that will hold color information /// private WriteableBitmap colorBitmap; /// /// Intermediate storage for the depth data received from the camera /// private DepthImagePixel[] depthPixels; /// /// Intermediate storage for the depth data converted to color /// private byte[] colorPixels; /// /// Initializes a new instance of the MainWindow class. /// public MainWindow() { InitializeComponent(); } /// /// Execute startup tasks /// /// object sending the event /// event arguments private void WindowLoaded(object sender, RoutedEventArgs e) { // Look through all sensors and start the first connected one. // This requires that a Kinect is connected at the time of app startup. // To make your app robust against plug/unplug, // it is recommended to use KinectSensorChooser provided in Microsoft.Kinect.Toolkit (See components in Toolkit Browser). foreach (var potentialSensor in KinectSensor.KinectSensors) { if (potentialSensor.Status == KinectStatus.Connected) { this.sensor = potentialSensor; break; } } if (null != this.sensor) { // Turn on the depth stream to receive depth frames this.sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30); // Allocate space to put the depth pixels we'll receive this.depthPixels = new DepthImagePixel[this.sensor.DepthStream.FramePixelDataLength]; // Allocate space to put the color pixels we'll create this.colorPixels = new byte[this.sensor.DepthStream.FramePixelDataLength * sizeof(int)]; // This is the bitmap we'll display on-screen this.colorBitmap = new WriteableBitmap(this.sensor.DepthStream.FrameWidth, this.sensor.DepthStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null); // Set the image we display to point to the bitmap where we'll put the image data this.Image.Source = this.colorBitmap; // Add an event handler to be called whenever there is new depth frame data this.sensor.DepthFrameReady += this.SensorDepthFrameReady; // Start the sensor! try { this.sensor.Start(); } catch (IOException) { this.sensor = null; } } if (null == this.sensor) { this.statusBarText.Text = Properties.Resources.NoKinectReady; } } /// /// Execute shutdown tasks /// /// object sending the event /// event arguments private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e) { if (null != this.sensor) { this.sensor.Stop(); } } /// /// Event handler for Kinect sensor's DepthFrameReady event /// /// object sending the event /// event arguments private void SensorDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) { using (DepthImageFrame depthFrame = e.OpenDepthImageFrame()) { if (depthFrame != null) { // Copy the pixel data from the image to a temporary array depthFrame.CopyDepthImagePixelDataTo(this.depthPixels); // Get the min and max reliable depth for the current frame int minDepth = depthFrame.MinDepth; int maxDepth = depthFrame.MaxDepth; // Convert the depth to RGB int colorPixelIndex = 0; for (int i = 0; i < this.depthPixels.Length; ++i) { // Get the depth for this pixel short depth = depthPixels[i].Depth; // To convert to a byte, we're discarding the most-significant // rather than least-significant bits. // We're preserving detail, although the intensity will "wrap." // Values outside the reliable depth range are mapped to 0 (black). // Note: Using conditionals in this loop could degrade performance. // Consider using a lookup table instead when writing production code. // See the KinectDepthViewer class used by the KinectExplorer sample // for a lookup table example. byte intensity = (byte)(depth >= minDepth && depth <= maxDepth ? depth : 0); // Write out blue byte this.colorPixels[colorPixelIndex++] = intensity; // Write out green byte this.colorPixels[colorPixelIndex++] = intensity; // Write out red byte this.colorPixels[colorPixelIndex++] = intensity; // We're outputting BGR, the last byte in the 32 bits is unused so skip it // If we were outputting BGRA, we would write alpha here. ++colorPixelIndex; } // Write the pixel data into our bitmap this.colorBitmap.WritePixels( new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight), this.colorPixels, this.colorBitmap.PixelWidth * sizeof(int), 0); } } } /// /// Handles the user clicking on the screenshot button /// /// object sending the event /// event arguments private void ButtonScreenshotClick(object sender, RoutedEventArgs e) { if (null == this.sensor) { this.statusBarText.Text = Properties.Resources.ConnectDeviceFirst; return; } // create a png bitmap encoder which knows how to save a .png file BitmapEncoder encoder = new PngBitmapEncoder(); // create frame from the writable bitmap and add to encoder encoder.Frames.Add(BitmapFrame.Create(this.colorBitmap)); string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat); string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); string path = Path.Combine(myPhotos, "KinectSnapshot-" + time + ".png"); // write the new file to disk try { using (FileStream fs = new FileStream(path, FileMode.Create)) { encoder.Save(fs); } this.statusBarText.Text = string.Format("{0} {1}", Properties.Resources.ScreenshotWriteSuccess, path); } catch (IOException) { this.statusBarText.Text = string.Format("{0} {1}", Properties.Resources.ScreenshotWriteFailed, path); } } /// /// Handles the checking or unchecking of the near mode combo box /// /// object sending the event /// event arguments private void CheckBoxNearModeChanged(object sender, RoutedEventArgs e) { if (this.sensor != null) { // will not function on non-Kinect for Windows devices try { if (this.checkBoxNearMode.IsChecked.GetValueOrDefault()) { this.sensor.DepthStream.Range = DepthRange.Near; } else { this.sensor.DepthStream.Range = DepthRange.Default; } } catch (InvalidOperationException) { } } } } }