我有这个功能,可以从位图:
创建一个区域Public Shared Function GetRegion(ByVal sender As Bitmap, ByVal transperancyKey As Color, ByVal tolerance As Integer) As Region
' Stores all the rectangles for the region.
Using path As New GraphicsPath()
' Scan the image
For x As Integer = 0 To (sender.Width - 1)
For y As Integer = 0 To (sender.Height - 1)
If Not ColorsMatch(sender.GetPixel(x, y), transperancyKey, tolerance) Then
path.AddRectangle(New Rectangle(x, y, 1, 1))
End If
Next
Next
Return New Region(path)
End Using
End Function
Public Shared Function ColorsMatch(ByVal color1 As Color, ByVal color2 As Color, ByVal tolerance As Integer) As Boolean
If (tolerance < 0) Then
tolerance = 0
End If
Return Math.Abs(color1.R - color2.R) <= tolerance AndAlso
Math.Abs(color1.G - color2.G) <= tolerance AndAlso
Math.Abs(color1.B - color2.B) <= tolerance
End Function
我希望使用Bitmap.LockBits
代替Bitmap.GetPixel
来提高效果。
目前我所拥有的是以下不完整的代码。我试图以与原始函数相同(有效)的方式迭代像素/颜色有点困惑。
Public Shared Function GetRegion(ByVal sender As Bitmap, ByVal transperancyKey As Color, ByVal tolerance As Integer) As Region
' Stores all the rectangles for the region.
Using path As New GraphicsPath()
' Lock the bitmap's bits.
Dim rect As New Rectangle(0, 0, sender.Width, sender.Height)
Dim bmpData As BitmapData = sender.LockBits(rect, ImageLockMode.ReadWrite, sender.PixelFormat)
' Get the address of the first line.
Dim ptr As IntPtr = bmpData.Scan0
' Declare an array to hold the bytes of the bitmap.
' Assume PixelFormat.Format32bppArgb (4 bytes per pixel)
Dim bytes As Integer = Math.Abs(bmpData.Stride) * sender.Height
' Note that I'm not sure whether the above is the proper calculation for that assumption.
Dim rgbValues(bytes - 1) As Byte
' Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, bytes)
' Scan the image
For x As Integer = 0 To (sender.Width - 1)
For y As Integer = 0 To (sender.Height - 1)
' ...
Next
Next
' Unlock the bits.
bmp.UnlockBits(bmpData)
Return New Region(path)
End Using
End Function
我该怎么做?。
答案 0 :(得分:1)
这样的事情应该可以解决问题。我一次只锁定一个像素行,以避免使用大量位图的大量内存,这使得逻辑很容易理解。
Public Shared Function GetRegion(ByVal bm As Bitmap, ByVal transperancyKey As Color, ByVal tolerance As Integer) As Region
Using path As New GraphicsPath()
Dim rect As New Rectangle(0, 0, bm.Width, 1) ' one row high
Dim pixelData As Int32() = New Int32(0 To bm.Width - 1) {}
For row As Integer = 0 To (bm.Height - 1)
' get the bitmap data as 32bppArgb so that we can read Int32 values
' this does not need to match the bm.PixelFormat
Dim bmData As BitmapData = bm.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)
' copy the pixel data for this row
Marshal.Copy(bmData.Scan0, pixelData, 0, pixelData.Length)
bm.UnlockBits(bmData)
For col As Integer = 0 To (bm.Width - 1)
Dim px As Color = Color.FromArgb(pixelData(col))
' do something with this pixel color
Next col
rect.Offset(0, 1) ' offset to select next row
Next row
Return New Region(path)
End Using
End Function