เมื่อคลิกที่ checkbox ที่มีข้อความว่า Reflect ผลลัพธ์ก็จะเปลี่ยนเป็น
นอกจากนี้เรายังสามารถกดปุ่ม Save เพื่อบันทึกรูปขณะนั้นได้
ส่วนของ UI
<Window x:Class="KinectMirrorSave.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" SizeToContent="WidthAndHeight" Loaded="Window_Loaded"> <StackPanel Orientation="Horizontal"> <Image Name="kinectVideo" Height="480" Width="640" /> <StackPanel Width="80"> <CheckBox Content="Reflect" Name="cbReflect" Margin="10,20"/> <Button Name="bttSave" Content="Save" Margin="10,20" Click="onSave" HorizontalAlignment="Center" VerticalAlignment="Center"></Button> </StackPanel> </StackPanel> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Microsoft.Kinect; using System.IO; namespace KinectMirrorSave { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { KinectSensor myKinect; public MainWindow() { InitializeComponent(); } //When a window loads private void Window_Loaded(object sender, RoutedEventArgs e) { //Check if there is any connecting Kinect if (KinectSensor.KinectSensors.Count == 0) { MessageBox.Show("No Kinect detected!", "Error"); //end this app Application.Current.Shutdown(); } //Try to initialize Kinect try { //Get the first Kinect connected to this computer myKinect = KinectSensor.KinectSensors[0]; //Enable the color video stream myKinect.ColorStream.Enable(); //Start the sensor myKinect.Start(); } catch { MessageBox.Show("Initialize Kinect failed!", "Error"); //end this app Application.Current.Shutdown(); } //Video event handler myKinect.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(myKinect_ColorFrameReady); } //******** Update display when video frame is ready********* //color data array byte[] colorData = null; WriteableBitmap imageBitmap = null; private void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e) { using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { //if get new video frame if (colorFrame == null) return; //create an array of pixel data if (colorData == null) colorData = new byte[colorFrame.PixelDataLength]; //extract pixel data from the frame to the array colorFrame.CopyPixelDataTo(colorData); //call unsafe method to modify the pixel data if (cbReflect.IsChecked == true) { //reflect a half left image to a half right reflectImage(colorData, colorFrame.Width, colorFrame.Height); } //prepare a saved frame if (takePicture) { //create a bitmap from the current frame capBitmap = BitmapSource.Create( colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, colorData, colorFrame.Width * colorFrame.BytesPerPixel); //switch a photo captured flag takePicture = false; } //For the first video frame, no bitmap, create a writable bitmap of video size if (imageBitmap == null) { imageBitmap = new WriteableBitmap( colorFrame.Width, colorFrame.Height, 96, //dpiX 96, //dpiY PixelFormats.Bgr32, null //palette:none ); } //For other video frames, write video data to bitmap imageBitmap.WritePixels( new Int32Rect(0, 0, colorFrame.Width, colorFrame.Height), colorData, //video data colorFrame.Width * colorFrame.BytesPerPixel, //stride 0 //offset to the array ); //set bitmap to image view kinectVideo.Source = imageBitmap; } } //************ unsafe method to modify pixel data ************** //Reflect the half left of the image to the half right private unsafe void reflectImage(byte[] colorData, int width, int height) { //fixed pixel data array in memory, otherwise it can be moved and be inaccessible by a pointer fixed (byte* pImage = colorData) { //in this block the data array in memory will be fixed //we use integer pointer to move by one pixel, faster than by one byte //however, we cannot get color data, OK for reflection //loop through each row for (int row = 0; row < height; row++) { //set a start pointer to the beginning of each row int* pStart = (int*)pImage + (row * width); //set an end pointer to the end of each row int* pEnd = pStart + width - 1; //loop through each column of the row while (pStart < pEnd) { //assign right pixel to left pixel *pEnd = *pStart; //move start pointer to right pStart++; //move end pointer to left pEnd--; } }//end for } }//end unsafe method //*********** Click a save button ********************* bool takePicture; BitmapSource capBitmap = null; //bitmap for captured frame private void onSave(object sender, RoutedEventArgs e) { //set a flag to capture image in video frame event takePicture = true; // Configure save file dialog box Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); dlg.FileName = "capture"; // Default file name dlg.DefaultExt = ".jpg"; // Default file extension dlg.Filter = "Pictures (.jpg)|*.jpg"; // Filter files by extension //if select Dialog OK if (dlg.ShowDialog() == true) { // Save document string filename = dlg.FileName; using (FileStream stream = new FileStream(filename, FileMode.Create)) { //encode and save to JPG format JpegBitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(capBitmap)); encoder.Save(stream); } } } } }