2016-10-27 90 views
1

我正在使用Kinect傳感器深度數據創建圖像。我想將傳感器集成到winforms應用程序中,所以我將示例MS應用程序轉換爲爲Picturebox創建位圖。該圖像只用於測試,所以我不關心性能問題。 我遇到的問題是WriteBitmap的返回值無效並導致引發異常。唯一的例外是位圖格式無效

Exception thrown: 'System.ArgumentException' in System.Drawing.dll 

的代碼:

public partial class Results : Form 
    { 
     private KinectSensor sensor; 
     private DepthImagePixel[] depthPixels; 

     private byte[] colorPixels; 
     public Results() 
     { 
      InitializeComponent(); 
     } 

     private void Results_Load(object sender, EventArgs e) 
     { 
      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.sensor.DepthFrameReady += this.SensorDepthFrameReady; 
       // Start the sensor! 
       try 
       { 
        this.sensor.Start(); 
       } 
       catch (IOException) 
       { 
        this.sensor = null; 
       } 
      } 

      if (null == this.sensor) 
      { 
       this.statusBarText.Text = "No sensor detected"; 
      } 

     } 

     private void Results_FormClosing(object sender, FormClosingEventArgs e) 
     { 
      if (null != this.sensor) 
      { 
       this.sensor.Stop(); 
      } 

     } 

     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). 
         byte intensity = (byte)(depth >= minDepth && depth <= maxDepth ? depth : 0); 

         this.colorPixels[colorPixelIndex++] = intensity; 
         this.colorPixels[colorPixelIndex++] = intensity; 
         this.colorPixels[colorPixelIndex++] = intensity; 
         // We're outputting BGR, the last byte in the 32 bits is unused so skip it 
         ++colorPixelIndex; 
        } 
        //// Write the pixel data into our bitmap 
        try { 
         //// Write the pixel data into our bitmap 
         if (this.logImage.Image != null) this.logImage.Image.Dispose(); 
         this.logImage.Image = null; 
         this.logImage.Image = WriteBitmap(this.sensor.DepthStream.FrameWidth, this.sensor.DepthStream.FrameHeight, this.colorPixels); 
        }catch(Exception ex) 
        { 
         Console.Write(ex); 
        } 
       } 
      } 
     } 

     Bitmap WriteBitmap(int width, int height, byte[] imageData) 
     { 
      using (var stream = new MemoryStream(imageData)) 
      using (var bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppRgb)) 
      { 
       BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, 
                   width, 
                   height), 
                ImageLockMode.WriteOnly, 
                bmp.PixelFormat); 

       Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length); 

       bmp.UnlockBits(bmpData); 
       return bmp; 
      } 

     } 
    } 

回答

1

的問題是,所述位圖被設置在所述WriteBitmap方法中,儘管返回的參考。我會想,通過返回一個參考GC無法觸及它。我重新安排了代碼,這樣創建和分配都發生在WriteBitmap中。現在它看起來像這樣

Bitmap bmp = null; 
    void WriteBitmap(int width, int height, byte[] imageData) 
    { 
     if (this.logImage.Image != null) 
     { 
      this.logImage.Image.Dispose(); 
      this.logImage.Image = null; 
     } 

     bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppRgb); 
     try 
     { 
      BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, 
                  width, 
                  height), 
               ImageLockMode.WriteOnly, 
               bmp.PixelFormat); 

      Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length); 

      bmp.UnlockBits(bmpData); 
      this.logImage.Image = bmp; 
     } 
     catch (Exception ex) 
     { 
      Console.Write(ex); 
     } 
    } 

它正在工作。