还有另一种更快、更方便的方法。如果您查看 Bitmap 构造函数,您会发现一个将 IntPtr 作为最后一个参数的构造函数。该 IntPtr 用于保存像素数据。那么如何使用呢?
Dim imageWidth As Integer = 1920
Dim imageHeight As Integer = 1080
Dim fmt As PixelFormat = PixelFormat.Format32bppRgb
Dim pixelFormatSize As Integer = Image.GetPixelFormatSize(fmt)
Dim stride As Integer = imageWidth * pixelFormatSize
Dim padding = 32 - (stride Mod 32)
If padding < 32 Then stride += padding
Dim pixels((stride \ 32) * imageHeight) As Integer
Dim handle As GCHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned)
Dim addr As IntPtr = Marshal.UnsafeAddrOfPinnedArrayElement(pixels, 0)
Dim bitmap As New Bitmap(imageWidth, imageHeight, stride \ 8, fmt, addr)
您现在拥有的是一个简单的整数数组和一个引用同一内存的位图。您对整数数组所做的任何更改都将直接影响位图。让我们通过简单的亮度变换来尝试一下。
Public Sub Brightness(ByRef pixels() As Integer, ByVal scale As Single)
Dim r, g, b As Integer
Dim mult As Integer = CInt(1024.0f * scale)
Dim pixel As Integer
For i As Integer = 0 To pixels.Length - 1
pixel = pixels(i)
r = pixel And 255
g = (pixel >> 8) And 255
b = (pixel >> 16) And 255
'brightness calculation
'shift right by 10 <=> divide by 1024
r = (r * mult) >> 10
g = (g * mult) >> 10
b = (b * mult) >> 10
'clamp to between 0 and 255
If r < 0 Then r = 0
If g < 0 Then g = 0
If b < 0 Then b = 0
r = (r And 255)
g = (g And 255)
b = (b And 255)
pixels(i) = r Or (g << 8) Or (b << 16) Or &HFF000000
Next
End Sub
您可能会注意到我使用了一个小技巧来避免在循环中进行浮点数学运算。这大大提高了性能。
当你完成后,你当然需要清理一点......
addr = IntPtr.Zero
If handle.IsAllocated Then
handle.Free()
handle = Nothing
End If
bitmap.Dispose()
bitmap = Nothing
pixels = Nothing
我在这里忽略了 alpha 组件,但您也可以随意使用它。我以这种方式组合了很多位图编辑工具。它比 Bitmap.LockBits() 更快、更可靠,最重要的是,它需要零内存复制来开始编辑您的位图。