如何将原始数据显示为图像(Visual Studio c#)

我将接收一些将存储在字节数组中的原始数据,其中每2个字节是一个像素值(16位/ px)。 首先,arrays将包含100×100 * 2字节(足以容纳100×100像素的图像)。 我想在窗体窗口中显示此数据。 最后,我想用新数据刷新图像,使其看起来像一个video流。 不需要严格的帧速率。 如何才能做到这一点? C#中的任何代码示例?

编辑:经过一些建议和审查数十个类似的问题,我仍然无法得到这个。 这是我想要做的一般概念,但图像不会显示在表单上的图片框中。 我的实施有什么特别的错误以及如何解决它

// array of data I collected byte[] dataArray = new byte[100 * 100 * 2]; //create a pointer to the data IntPtr hglobal = Marshal.AllocHGlobal(100 * 100 * 2); // copy my array to global Marshal.Copy(dataArray, 0, hglobal, dataArray.Length); // create a bitmap: 100x100 pixels, 2bytes/pixel, 16bitgrayscale Bitmap newBitmap = new Bitmap(100, 100, 2 * 100, PixelFormat.Format16bppGrayScale, hglobal); // display bitmap pictureBox1.Image = newBitmap; // free the memory Marshal.FreeHGlobal(hglobal); 

主要问题是不支持PixelFormat.Format16bppGrayScale(至少在我的Win 8.1 x64系统上)。 所以你必须在显示之前将图像转换为rgb:

 private void Form1_Load(object sender, EventArgs e) { //Create pixel data to put in image, use 2 since it is 16bpp Random r = new Random(); int width = 100; int height = 100; byte[] pixelValues = new byte[width * height * 2]; for (int i = 0; i < pixelValues.Length; ++i) { // Just creating random pixel values for test pixelValues[i] = (byte)r.Next(0, 256); } var rgbData = Convert16BitGrayScaleToRgb48(pixelValues, width, height); var bmp = CreateBitmapFromBytes(rgbData, width, height); // display bitmap pictureBox1.Image = bmp; } private static byte[] Convert16BitGrayScaleToRgb48(byte[] inBuffer, int width, int height) { int inBytesPerPixel = 2; int outBytesPerPixel = 6; byte[] outBuffer = new byte[width * height * outBytesPerPixel]; int inStride = width * inBytesPerPixel; int outStride = width * outBytesPerPixel; // Step through the image by row for (int y = 0; y < height; y++) { // Step through the image by column for (int x = 0; x < width; x++) { // Get inbuffer index and outbuffer index int inIndex = (y * inStride) + (x * inBytesPerPixel); int outIndex = (y * outStride) + (x * outBytesPerPixel); byte hibyte = inBuffer[inIndex + 1]; byte lobyte = inBuffer[inIndex]; //R outBuffer[outIndex] = lobyte; outBuffer[outIndex + 1] = hibyte; //G outBuffer[outIndex + 2] = lobyte; outBuffer[outIndex + 3] = hibyte; //B outBuffer[outIndex + 4] = lobyte; outBuffer[outIndex + 5] = hibyte; } } return outBuffer; } private static Bitmap CreateBitmapFromBytes(byte[] pixelValues, int width, int height) { //Create an image that will hold the image data Bitmap bmp = new Bitmap(width, height, PixelFormat.Format48bppRgb); //Get a reference to the images pixel data Rectangle dimension = new Rectangle(0, 0, bmp.Width, bmp.Height); BitmapData picData = bmp.LockBits(dimension, ImageLockMode.ReadWrite, bmp.PixelFormat); IntPtr pixelStartAddress = picData.Scan0; //Copy the pixel data into the bitmap structure System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, pixelStartAddress, pixelValues.Length); bmp.UnlockBits(picData); return bmp; } 

想法取自这个主题 。

使用此Bitmap构造函数:

 public Bitmap( int width, int height, int stride, PixelFormat format, IntPtr scan0 ) 

您将位图的形状,步幅(每行包含多少字节,包括填充),像素格式和像素数据作为void *指针传递给它。 您可以使用Marshal.AllocHGlobal创建后者,并使用指针操作正常填充它。 创建位图后,请不要忘记释放此内存。

编辑以解释更新的问题:

只需调用IntPtr.ToPointer()即可获取指针。 如果你熟悉C,剩下的应该是蛋糕:

 var p=(char *)hglobal.ToPointer(); // bad name by the way, it's not a handle, it's a pointer p[0]=0; // access it like any normal pointer 

但是,您可以使用Marshaller将内存从托管复制到非托管(在C#中通常不赞同你的手):

 Marshal.Copy(dataArray, 0, hglobal, dataArray.Length); // again, terrible name 

Bitmap是一个Image (就像在它中派生的那样),但是你使用的是Graphics.DrawImage()错误。 正如错误所说,它不是静态方法,您将其绘制到特定的图形上下文。 现在那个图形背景是什么,这取决于你:

  • 如果要根据WM_PAINT绘制它,请使用Paint事件 – 它为您提供了一个特殊的Graphics对象,它设置了剪切和窗口系统指示的所有内容。
  • 如果你想在位图上绘制它以便稍后以某种方式显示(常用,也称为双缓冲),在源位图上使用Graphics.FromImage() ,然后在其上绘制位图。

一旦从Bitmap构造函数返回结果,就可以(并且应该)删除虚拟内存缓冲区。 不要泄漏内存,使用try..finally构造。