vb.net如何在字节数组中显示图片框中的8位图像

时间:2014-07-14 08:29:19

标签: arrays vb.net image

我有一个包含从相机获取的图像数据的数组。 该阵列仅包含与每个像素相关的8位数据。目前我执行以下操作以在图片框上显示图像:

    Dim bm As New Bitmap(CInt(width), CInt(height))
    Dim bufcnt As Integer = 0
    Dim mrow As Integer
    Dim mcol As Integer
    For mrow = 0 To height - 1
        For mcol = 0 To width - 1
            bm.SetPixel(mcol, mrow, Color.FromArgb(imageBuffer(bufcnt), imageBuffer(bufcnt), imageBuffer(bufcnt)))
            bufcnt = bufcnt + 1
        Next mcol
    Next mrow
    PCBIMG.Image = bm

然而,在较大的图像上,这确实需要一些时间,是否有更有效的方法可以实现图像的实时显示?

1 个答案:

答案 0 :(得分:2)

以下是使用Marshal.Copy一次移动整个位图的示例。位图格式必须为Format8bppIndexed,以便您可以将原始数据直接移动到位图对象中,而不是手动将每个像素转换为24bpp。 8bpp索引格式实际上可以显示24位颜色的任何8位子集,因此您需要为图像定义调色板。我假设你想要灰度,所以调色板只是1:1的地图。

为此,您需要以下导入:

Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices

然后:

Function ConvertBytesToBitmap(ByVal inBytes() As Byte, _
                              ByVal imgWidth As Integer, _ 
                              ByVal imgHeight As Integer) As Bitmap

    Dim b As New Bitmap(imgWidth, imgHeight, PixelFormat.Format8bppIndexed)

    ' Define a greyscale colour palette
    Dim ncp As ColorPalette = b.Palette
    Dim i As Integer
    For i = 0 To 255
        ncp.Entries(i) = Color.FromArgb(255, i, i, i)
    Next
    b.Palette = ncp

    ' Copy the bytes to the bitmap's data region
    Dim BoundsRect As New Rectangle(0, 0, imgWidth, imgHeight)
    Dim bmpData As BitmapData = b.LockBits(BoundsRect, _
                                           ImageLockMode.WriteOnly, _
                                           b.PixelFormat)

    ' Bitmap.Scan0 returns a pointer to the image data array
    ' The data format is a 1D array, row-major format
    Dim ptr As IntPtr = bmpData.Scan0

    Dim numberOfBytes As Integer = bmpData.Stride * b.Height

    Marshal.Copy(inBytes, 0, ptr, numberOfBytes)
    b.UnlockBits(bmpData)
    Return b

End Function

为了展示一个使用示例,我选择了一个400x200像素的图像,并用水平渐变填充它:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim i As Integer
    Dim j As Integer
    ' Create example image buffer for 400x200px image
    Dim imgBuffer(79999) As Byte

    ' Fill example image buffer with horizontal gradient
    For i = 0 To 199
        For j = 0 To 399
            imgBuffer(j + i * 400) = 255 * j / 400
        Next
    Next

    PictureBox1.Image = ConvertBytesToBitmap(imgBuffer, 400, 200)
End Sub

当然,上述功能并未完全针对您的目的进行优化。您可以跳过每次重新创建灰度调色板并保存副本,将其作为参数传递或将其构建为类等。这可以节省一些时间。尽管如此,即使每次都创建调色板,这应该比您使用的代码快几千倍。