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

如何将原始数据显示为图像(Visual Studio c#),c#,image,visual-studio,drawing,C#,Image,Visual Studio,Drawing,我将接收一些原始数据,这些数据将存储在字节数组中,其中每2个字节是一个像素值(16位/px)。首先,该阵列将包含100x100*2字节(足以容纳100x100像素图像)。我想在窗体窗口中显示此数据。最后,我想用新数据刷新图像,使其看起来像视频流。不需要严格的帧速率。如何做到这一点?有C#中的代码示例吗 编辑: 在对几十个类似的问题提出了一些建议和评论之后,我仍然无法继续下去。这是我尝试做的大致想法,但是图像没有显示在表单的图片框中我的实现有什么具体错误,以及如何修复它 // array of d

我将接收一些原始数据,这些数据将存储在字节数组中,其中每2个字节是一个像素值(16位/px)。首先,该阵列将包含100x100*2字节(足以容纳100x100像素图像)。我想在窗体窗口中显示此数据。最后,我想用新数据刷新图像,使其看起来像视频流。不需要严格的帧速率。如何做到这一点?有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);
使用此构造函数:

public Bitmap(
    int width,
    int height,
    int stride,
    PixelFormat format,
    IntPtr scan0
)
将位图的形状、跨距(每行多少字节,包括填充)、像素格式和像素数据作为
void*
指针传递给它。您可以使用指针操作创建后者,并像使用指针操作一样填充它。创建位图后,不要忘记释放此内存

编辑以说明更新的问题:

只需调用
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
但是,您可以使用封送拆收器将内存从托管复制到非托管(在C#中,脏手通常是不受欢迎的):

位图
是一个
图像
(如中所示,它是从中派生出来的),但是您使用的
图形.DrawImage()
是错误的。正如错误所说,它不是一个静态方法,而是将其绘制到特定的图形上下文中。现在,图形上下文是什么,取决于您:

  • 如果您想绘制它以响应
    WM_paint
    ,请使用
    paint
    事件——它为您提供了一个特殊的
    图形
    对象,该对象设置为剪切,并按照窗口系统的指示进行所有操作
  • 如果要在位图上绘制,以便以后以某种方式显示(常用,也称为双缓冲),请在源位图上使用
    Graphics.FromImage()
    ,然后在其上绘制位图

位图
构造函数返回结果后,您可以(也应该)立即删除虚拟内存缓冲区。不要泄漏内存,请使用
try..finally
construct.

主要问题是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;
}
private void Form1\u加载(对象发送方,事件参数e)
{
//创建像素数据放入图像,使用2,因为它是16bpp
随机r=新随机();
整数宽度=100;
整数高度=100;
字节[]像素值=新字节[宽度*高度*2];
对于(int i=0;i

这个想法来源于。

您可能想看一看,是否可以迭代数组并使用
Bitmap.SetPixel()
?正如@Eldarien所说,您需要使用
Format48bppRgb
谢谢。请您提供更多关于如何使用此位图的信息。怎么处理它。如何显示图像?我对这个很陌生。您可能参考了某个示例?您可以从图像或框架的
绘制
事件中获得
图形
上下文,并使用
图形绘制图像。DrawImage
。刚刚更新了我的问题。这就是我到目前为止所想到的,这就是我力量的终点。请,帮助。更新的答案也一样,希望有帮助。你真的应该读一篇关于GDI/GDI+的深入文章,但是大多数初学者发现他们并不拥有用户的屏幕这一事实完全令人困惑。好的,谢谢。我会继续努力的。关于“图形上下文”-我只想显示图像
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;
}