在 C# 中修改像素的最快方法是什么
What is the fastest way to modify pixels in C#
我想将位图中的指定像素更改为透明。
方法如下:
Bitmap bt = new Bitmap(Mybitmap);
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, Mybitmap.Width, Mybitmap.Height);
BitmapData bmpdata = bt.LockBits(rect, ImageLockMode.ReadWrite, bt.PixelFormat);
IntPtr ptr = bmpdata.Scan0;
int bytes = Math.Abs(bmpdata.Stride) * bt.Height;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(ptr, rgbValues, 0, bytes);
int len = rgbValues.Length;
for (int i = 0; i < len; i += 4)
{
//Some colors are already stored in this SpecificColor1ist, and pixels with the same color will be changed to transparent
foreach (var item in SpecificColor1ist)
{
if ((rgbValues[i]==item.B)&&(rgbValues[i+1] == item.G)&&(rgbValues[i+2] == item.R))
{
rgbValues[i + 3] = (byte)0;
}
}
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bt.UnlockBits(bmpdata);
return bt;
但是速度太慢了。有什么办法让它更快吗?不安全的代码也是可以接受的。
- 你有一个指向像素数据数组的指针,为什么不使用它
Scan0
(你需要将你的方法设置为不安全的,并在项目的构建选项中适当地设置它)
- 您可以确保您的像素格式是 32 位。
- 您可以使用 int
一次性比较您的 rbg 值
- 使用 HashSet 进行更快的查找
- 使用 按位
&
清除 apha-channel
例子
var colorHash = SpecificColor1ist
.Select(x => x.ToArgb())
.ToHashSet();
...
var data = bt.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
var length = (int*)data.Scan0 + Mybitmap.Height * Mybitmap.Width;
for (var p = (int*)data.Scan0; p < length; p++)
if(colorHash .Contains(*p))
*p = (*p & 0xFFFFFF) // i think sets the alpha to 0
...
我想将位图中的指定像素更改为透明。 方法如下:
Bitmap bt = new Bitmap(Mybitmap);
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, Mybitmap.Width, Mybitmap.Height);
BitmapData bmpdata = bt.LockBits(rect, ImageLockMode.ReadWrite, bt.PixelFormat);
IntPtr ptr = bmpdata.Scan0;
int bytes = Math.Abs(bmpdata.Stride) * bt.Height;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(ptr, rgbValues, 0, bytes);
int len = rgbValues.Length;
for (int i = 0; i < len; i += 4)
{
//Some colors are already stored in this SpecificColor1ist, and pixels with the same color will be changed to transparent
foreach (var item in SpecificColor1ist)
{
if ((rgbValues[i]==item.B)&&(rgbValues[i+1] == item.G)&&(rgbValues[i+2] == item.R))
{
rgbValues[i + 3] = (byte)0;
}
}
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bt.UnlockBits(bmpdata);
return bt;
但是速度太慢了。有什么办法让它更快吗?不安全的代码也是可以接受的。
- 你有一个指向像素数据数组的指针,为什么不使用它
Scan0
(你需要将你的方法设置为不安全的,并在项目的构建选项中适当地设置它) - 您可以确保您的像素格式是 32 位。
- 您可以使用 int 一次性比较您的 rbg 值
- 使用 HashSet 进行更快的查找
- 使用 按位
&
清除 apha-channel
例子
var colorHash = SpecificColor1ist
.Select(x => x.ToArgb())
.ToHashSet();
...
var data = bt.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
var length = (int*)data.Scan0 + Mybitmap.Height * Mybitmap.Width;
for (var p = (int*)data.Scan0; p < length; p++)
if(colorHash .Contains(*p))
*p = (*p & 0xFFFFFF) // i think sets the alpha to 0
...