c#使用指针在特定点设置像素
c# set pixel at specific point using pointers
我想在特定点设置一个像素,但不使用慢 SetPixel()
方法。
以常规方式,我所要做的就是例如:bmp.SetPixel(120, 53, Color.Red);
但现在当我使用 LockBits
和指针时,似乎我必须通过所有图像边界并且无法在特定位置设置像素。
这是我的代码
private unsafe void ChangePX(Bitmap bmp)
{
bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
IntPtr scan0 = bmData.Scan0;
int stride = bmData.Stride;
int nWidth = bmp.Width;
int nHeight = bmp.Height;
for(int y = 0; y < nHeight; y++)
{
byte* p = (byte*)scan0.ToPointer();
p += y * stride;
for (int x = 0; x < nWidth; x++)
{
if (x==120 &&y==53)
{//found the position.
p[0]=255;
p[1]=255;
p[2]=255;
p[3]=1;
}
p += 4;
}
bmp.UnlockBits(bmData);
}
正如你在这里看到的,我正在循环浏览图像以找到特定位置,但我想直接设置它而不循环。
但是我 不想 使用经典的 SetPixel
方法,因为我必须在很多点上设置像素。
任何帮助,将不胜感激。
位图中的每一行都在末尾填充,因此下一行从 4 字节边界开始。 bmData.Stride
包含这样一个填充行的大小。
位图还包含 header 信息,例如像素格式和图像大小(未填充)。 bmData.Scan0
包含像素数据第一个字节的地址。
所以考虑到每一行都是 bmData.Stride
字节宽,行 y
开始于:
bmData.Scan0 + (y * bmData.Stride)
假定每个像素存储在 4 个字节中,因此要找到行 y
中第 x
列的像素数据的第一个字节,您将它乘以 4:
bmData.Scan0 + (y * bmData.Stride) + (x * 4)
然后你可以直接指向那个地址,如果你想:
byte* p = (byte*)bmData.Scan0 + (y * bmData.Stride) + (x * 4);
好吧,您可以 直接寻址像素。给定维度和步长(假设你总是每个像素有 4 个字节),一个像素的地址是:
byte* p = (byte*)scan0.ToPointer();
p += (y * stride) + (x * 4);
为什么?
每行包含 stride
字节,因此要到达行 y
,您需要添加 y * stride
字节。 x 方向上的每个像素有 4 个字节,因此如果您添加 4 * x
,则您位于当前行中的像素 x
。
我想在特定点设置一个像素,但不使用慢 SetPixel()
方法。
以常规方式,我所要做的就是例如:bmp.SetPixel(120, 53, Color.Red);
但现在当我使用 LockBits
和指针时,似乎我必须通过所有图像边界并且无法在特定位置设置像素。
这是我的代码
private unsafe void ChangePX(Bitmap bmp)
{
bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
IntPtr scan0 = bmData.Scan0;
int stride = bmData.Stride;
int nWidth = bmp.Width;
int nHeight = bmp.Height;
for(int y = 0; y < nHeight; y++)
{
byte* p = (byte*)scan0.ToPointer();
p += y * stride;
for (int x = 0; x < nWidth; x++)
{
if (x==120 &&y==53)
{//found the position.
p[0]=255;
p[1]=255;
p[2]=255;
p[3]=1;
}
p += 4;
}
bmp.UnlockBits(bmData);
}
正如你在这里看到的,我正在循环浏览图像以找到特定位置,但我想直接设置它而不循环。
但是我 不想 使用经典的 SetPixel
方法,因为我必须在很多点上设置像素。
任何帮助,将不胜感激。
位图中的每一行都在末尾填充,因此下一行从 4 字节边界开始。 bmData.Stride
包含这样一个填充行的大小。
位图还包含 header 信息,例如像素格式和图像大小(未填充)。 bmData.Scan0
包含像素数据第一个字节的地址。
所以考虑到每一行都是 bmData.Stride
字节宽,行 y
开始于:
bmData.Scan0 + (y * bmData.Stride)
假定每个像素存储在 4 个字节中,因此要找到行 y
中第 x
列的像素数据的第一个字节,您将它乘以 4:
bmData.Scan0 + (y * bmData.Stride) + (x * 4)
然后你可以直接指向那个地址,如果你想:
byte* p = (byte*)bmData.Scan0 + (y * bmData.Stride) + (x * 4);
好吧,您可以 直接寻址像素。给定维度和步长(假设你总是每个像素有 4 个字节),一个像素的地址是:
byte* p = (byte*)scan0.ToPointer();
p += (y * stride) + (x * 4);
为什么?
每行包含 stride
字节,因此要到达行 y
,您需要添加 y * stride
字节。 x 方向上的每个像素有 4 个字节,因此如果您添加 4 * x
,则您位于当前行中的像素 x
。