在沒有任何事情之前,我會注意到我接受了C#或VB.Net解決方案。用Lockbits替換圖像的顏色
我有這樣的老代碼,我試圖重構避免使用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
因此,使用閱讀的是投票的解決方案here後LockBits
的做法,我想代碼適應我的需要,使用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
我有兩個擴展方法的問題,首先是,如果像素格式不是Format24bppRgb
作爲原始示例,然後全部出錯,在循環中引發IndexOutOfRange
異常,我想這是因爲我正在讀取3個字節( RGB)而不是4(ARGB),但我不知道如何適應它可以傳遞給函數的任何源像素格式。
Secondlly的是,如果我使用Format24bppRgb
爲原來的C#示例,顏色變爲黑色。
請注意,我不知道,如果在C#中的問題給出的原始的解決方案,我聯繫是錯誤的,因爲按他們的意見似乎是錯誤的某種方式。
這是我想要使用它的方式:
' 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
所以我添加了1,4,8,24和32 bpp像素格式的示例。當然,您也可以計算15/16/64和其他格式的顏色。我在這裏使用了不安全的方法,但是您可以使用'Marshal.Copy'通過使用託管數組來複制數據。 – taffer