位图格式无效

时间:2016-10-27 10:54:15

标签: .net kinect

我正在使用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 个答案:

答案 0 :(得分: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);
        }
    }

它正在发挥作用。