【发布时间】:2016-02-07 07:41:18
【问题描述】:
首先,我会注意我接受 C# 或 VB.Net 解决方案。
我有这段旧代码,我正在尝试重构它以避免使用GetPixel/SetPixel 方法的不良习惯和性能低效:
<Extension>
Public Function ChangeColor(ByVal sender As Image,
ByVal oldColor As Color,
ByVal newColor As Color) As Image
Dim bmp As New Bitmap(sender.Width, sender.Height, sender.PixelFormat)
Dim x As Integer = 0
Dim y As Integer = 0
While (x < bmp.Width)
y = 0
While y < bmp.Height
If DirectCast(sender, Bitmap).GetPixel(x, y) = oldColor Then
bmp.SetPixel(x, y, newColor)
End If
Math.Max(Threading.Interlocked.Increment(y), y - 1)
End While
Math.Max(Threading.Interlocked.Increment(x), x - 1)
End While
Return bmp
End Function
因此,在阅读了使用 LockBits 方法的投票最多的解决方案 here 之后,我正在尝试根据我的需要调整代码,使用 Color 作为参数而不是字节序列(因为本质上是一样的):
<Extension>
Public Function ChangeColor(ByVal sender As Image,
ByVal oldColor As Color,
ByVal newColor As Color) As Image
Dim bmp As Bitmap = DirectCast(sender.Clone, Bitmap)
' Lock the bitmap's bits.
Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim bmpData As BitmapData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat)
' Get the address of the first line.
Dim ptr As IntPtr = bmpData.Scan0
' Declare an array to hold the bytes of the bitmap.
Dim numBytes As Integer = (bmpData.Stride * bmp.Height)
Dim rgbValues As Byte() = New Byte(numBytes - 1) {}
' Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, numBytes)
' Manipulate the bitmap.
For i As Integer = 0 To rgbValues.Length - 1 Step 3
If (Color.FromArgb(rgbValues(i), rgbValues(i + 1), rgbValues(i + 2)) = oldColor) Then
rgbValues(i) = newColor.R
rgbValues(i + 1) = newColor.G
rgbValues(i + 2) = newColor.B
End If
Next i
' Copy the RGB values back to the bitmap.
Marshal.Copy(rgbValues, 0, ptr, numBytes)
' Unlock the bits.
bmp.UnlockBits(bmpData)
Return bmp
End Function
我的扩展方法有两个问题,首先是如果pixelformat不是Format24bppRgb作为原始示例那么一切都会出错,循环中抛出IndexOutOfRange异常,我想这是因为我读取 3 个字节 (RGB) 而不是 4 个 (ARGB),但我不确定如何将其调整为可以传递给函数的任何源像素格式。
其次,如果我使用 Format24bppRgb 作为原始 C# 示例,颜色将变为黑色。
请注意,我不确定我链接的 C# 问题中给出的原始解决方案是否错误,因为根据他们的 cmets 似乎在某些方面是错误的。
这是我尝试使用它的方式:
' This function creates a bitmap of a solid color.
Dim srcImg As Bitmap = ImageUtil.CreateSolidcolorBitmap(New Size(256, 256), Color.Red)
Dim modImg As Image = srcImg.ChangeColor(Color.Red, Color.Blue)
PictureBox1.BackgroundImage = srcImg
PictureBox2.BackgroundImage = modImg
【问题讨论】:
标签: c# .net vb.net image-processing bitmap