为什么还不使用LockBits着色acolor中的像素?

时间:2014-09-27 08:16:56

标签: c# .net winforms

我在List pointtocolor上进行循环,包含超过50000像素的坐标,然后我试图在Bitmap bmpBackClouds上为它们着色。

我第一次尝试使用该行:

if ((int)p + (int)(x + y) < bD.Stride * bD.Height)

然而它从未介入,从未做过p[1] = p[2] = (byte)255;行。 所以现在我没有使用这个IF而且它正在做所有的线路。 但最终我得到了与原始相同的Bitmap,因为它没有任何颜色。

float x, y;
bD = bmpBackClouds.LockBits(
    new System.Drawing.Rectangle(0, 0, bmpBackClouds.Width, bmpBackClouds.Height),
    System.Drawing.Imaging.ImageLockMode.ReadWrite,
    System.Drawing.Imaging.PixelFormat.Format32bppArgb);
IntPtr s0 = bD.Scan0;

unsafe
{
    byte* p;
    byte* pBU = (byte*)(void*)s0;

    for (int i = 0; i < pointtocolor.Count; i++)
    {
        p = (byte*)(void*)s0;
        x = pointtocolor[i].X * (float)currentFactor;
        y = pointtocolor[i].Y * (float)currentFactor;
        if ((int)x >= bmpBackClouds.Width || (int)y >= bmpBackClouds.Height)
        {
            continue;
        }
        x = (int)(y * (float)bD.Stride);
        y = (int)(x * 4F);
        p += (int)(x + y);
        if ((int)p + (int)(x + y) < bD.Stride * bD.Height)
        {
            if (x + y > 3)
                p -= (p - pBU) % 4;
            p[1] = p[2] = (byte)255;
            p[0] = (byte)0;
            p[3] = (byte)255;
        } 
    }
}
bmpBackClouds.UnlockBits(bD);

这是不安全的代码部分:

不安全                     {                         byte * p;                         byte * pBU =(byte *)(void *)s0;

                    for (int i = 0; i < pointtocolor.Count; i++)
                    {
                        //set pointer to the beggining 
                        p = (byte*)(void*)s0;
                        x = pointtocolor[i].X * (float)currentFactor;
                        y = pointtocolor[i].Y * (float)currentFactor;
                        //check if point is inside bmp 
                        if ((int)x >= bmpBackClouds.Width || (int)y >= bmpBackClouds.Height)
                        {
                            continue;
                        }
                        //Add offset where the point is. The formula: position = Y * stride + X * 4 
                        x = (int)(y * (float)bD.Stride);
                        y = (int)(x * 4F);

                        p += (int)(x + y);
                        //here check, whether the pointer's at a correct position
                        if (x + y > 3)
                            p -= (p - pBU) % 4;

                        //set yellow color 
                        p[1] = p[2] = (byte)255;
                        p[0] = (byte)0;
                        p[3] = (byte)255;
                    }
                }

汉斯的解决方案正在运作我只是有一个小的例子,我在硬盘上的图像被涂上了正确的形状,但是相反或反转不确定如何调用它应该是什么:

opposite

在左边的屏幕截图中,我在har盘上找到了我用LockBits写的位图。 在右侧,它是我的程序和一个用红色绘制的矩形,这个矩形应该是位图上的彩色区域。但是在Bitmap上,我看到这个矩形但看起来却相反或相反。

问题是LockBits代码是否有问题?或者它看起来更像我的其他代码?

1 个答案:

答案 0 :(得分:0)

(p - pBU)%4 始终为零。差异总是4的倍数,因为每个像素有4字节的信息。 p指针从pBU指向的开头到4的倍数。如果要测试点是否在矩形中,请执行以下操作:

GraphicsPath gp = new GraphicsPath();
gp.AddRectangle(new RectangleF(?, ?, ?, ?)); //fill the values of your rectangle

for (int i = 0; i < pointtocolor.Count; i++)
{
    if(gp.IsVisible (pointtocolor[i].X * (float)currentFactor, pointtocolor[i].Y * (float)currentFactor) 
    {
        //is inside
    }
}

修改

扫描位图并使用 bD.Stride 使用 int 指针查看宽度时出错是因为stride给出了颜色字节数 像素数

int *p;
p = (int*)(void*)s0;
//x, y the position coordinates
p += y * bD.Stride + x * 4; //wrong

byte *p;
p = (byte*)(void*)s0;
//x, y the position coordinates
p += y * bD.Stride + x * 4; //correct

错误在这里

x = (int)(y * (float)bD.Stride);
y = (int)(x * 4F);

您正在使用之前的x来设置y!

正确的代码是:

float fx, fy;
int x, y;
bD = bmpBackClouds.LockBits(
new System.Drawing.Rectangle(0, 0, bmpBackClouds.Width, bmpBackClouds.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
IntPtr s0 = bD.Scan0;

unsafe
{
    byte* p;
    //byte* pBU = (byte*)(void*)s0;

    for (int i = 0; i < pointtocolor.Count; i++)
    {
        p = (byte*)(void*)s0;
        fx = pointtocolor[i].X * (float)currentFactor;
        fy = pointtocolor[i].Y * (float)currentFactor;
        if ((int)fx >= bmpBackClouds.Width || (int)fy >= bmpBackClouds.Height)
        {
            continue;
        }
        x = (int)fy * bD.Stride;
        y = (int)fx * 4;
        p += (x + y);

        p[1] = p[2] = (byte)255;
        p[0] = (byte)0;
        p[3] = (byte)255;
    }
}
bmpBackClouds.UnlockBits(bD);

瓦尔特