c#使用指针在特定点设置像素

本文关键字:设置 像素 指针 | 更新日期: 2023-09-27 18:05:29

我想在特定点设置一个像素,但不使用慢速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方法,因为我必须在许多点上设置像素。任何帮助都会很感激。

c#使用指针在特定点设置像素

位图中的每一行都在末尾填充,因此下一行从4字节边界开始。bmData.Stride包含这样一个填充行的大小。

位图还包含标题信息,例如像素格式和图像的大小(未填充)。bmData.Scan0包含像素数据的第一个字节的地址。

所以考虑到每一行是bmData.Stride字节宽,行y开始于:

bmData.Scan0 + (y * bmData.Stride) 

假定每个像素存储在4个字节中,因此要找到yx列的像素数据的第一个字节,请将其乘以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像素处。