我有一个包含从相机获取的图像数据的数组。 该阵列仅包含与每个像素相关的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
然而,在较大的图像上,这确实需要一些时间,是否有更有效的方法可以实现图像的实时显示?
答案 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
当然,上述功能并未完全针对您的目的进行优化。您可以跳过每次重新创建灰度调色板并保存副本,将其作为参数传递或将其构建为类等。这可以节省一些时间。尽管如此,即使每次都创建调色板,这应该比您使用的代码快几千倍。