Как в Bitmap оставить только необходимые цвета пикселей, а остальные превратить, например, в чёрный цвет?
Конечно, хотелось бы решение пошустрей.
Самый простой вариант - через GetPixel и SetPixel, но будет работать довольно медленно.
Лучше использовать Scan0 и преобразовать картинку в массив intов, соответствующих цвету каждого пикселя - для этого подходит формат PixelFormat.Format32bppArgb - в нём цвета представлены 4 байтами и в intе тоже 4 байта.
Ниже код обработки на VB.NET, его можно легко переписать на C#.
Этот код заменяет один цвет на другой, но позволяет при сравнении игнорировать альфа-канал (и сохранять его при замене). Если нужно какое-либо ещё условие, то надо заменить соответствующее сравнение и присваивание.
Public Shared Sub ReplaceColor(ByVal Bmp As Bitmap, ByVal OldColor As Color, ByVal NewColor As Color, Optional ByVal IgnoreAlpha As Boolean = False)
Dim BmpData As BitmapData = Bmp.LockBits(New Rectangle(Nothing, Bmp.Size), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
Dim ArgbData(BmpData.Stride * BmpData.Height / 4 - 1) As Integer
Dim Mask As Integer = If(IgnoreAlpha, (1 << 24) - 1, -1), NotMask As Integer = Not Mask
Dim OldVal As Integer = ((((((CInt(OldColor.A) << 8) Or OldColor.R) << 8) Or OldColor.G) << 8) Or OldColor.B) And Mask
Dim NewVal As Integer = ((((((CInt(NewColor.A) << 8) Or NewColor.R) << 8) Or NewColor.G) << 8) Or NewColor.B) And Mask
Marshal.Copy(BmpData.Scan0, ArgbData, 0, ArgbData.Length)
For Q As Integer = 0 To ArgbData.Length - 1
If (ArgbData(Q) And Mask) = OldVal Then ArgbData(Q) = (ArgbData(Q) And NotMask) Or NewVal
Next Q
Marshal.Copy(ArgbData, 0, BmpData.Scan0, ArgbData.Length)
Bmp.UnlockBits(BmpData)
End Sub
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости