C# 如何避免;“噪音”;在不安全代码中设置图像像素时

C# 如何避免;“噪音”;在不安全代码中设置图像像素时,c#,winforms,image-processing,unsafe,C#,Winforms,Image Processing,Unsafe,我在C#winforms项目中使用“不安全”代码创建(然后修改)位图。大约每30毫秒进行一次。我遇到的问题是,“噪声”或随机像素有时会出现在生成的位图中,我没有特别更改任何内容 例如,我创建了一个100x100的位图。使用BitmapData和LockBits,我遍历位图并将某些像素更改为特定颜色。然后我解锁位,并设置一个picturebox来使用图像。我设置的所有像素都是正确的,但我没有专门设置的像素有时看起来是随机颜色 如果我设置每个像素,噪声就会消失。但是,出于性能原因,我只希望设置最小数

我在C#winforms项目中使用“不安全”代码创建(然后修改)位图。大约每30毫秒进行一次。我遇到的问题是,“噪声”或随机像素有时会出现在生成的位图中,我没有特别更改任何内容

例如,我创建了一个100x100的位图。使用
BitmapData
LockBits
,我遍历位图并将某些像素更改为特定颜色。然后我
解锁位
,并设置一个picturebox来使用图像。我设置的所有像素都是正确的,但我没有专门设置的像素有时看起来是随机颜色

如果我设置每个像素,噪声就会消失。但是,出于性能原因,我只希望设置最小数量

有人能解释为什么会这样吗

下面是一些示例代码:

// Create new output bitmap
Bitmap Output_Bitmap = new Bitmap(100, 100);

// Lock the output bitmap's bits
Rectangle Output_Rectangle = new Rectangle(
    0,
    0,
    Output_Bitmap.Width,
    Output_Bitmap.Height);
BitmapData Output_Data = Output_Bitmap.LockBits(
    Output_Rectangle,
    ImageLockMode.WriteOnly,
    PixelFormat.Format32bppRgb);

const int PixelSize = 4;
unsafe
{
    for (int y = 0; y < Output_Bitmap.Height; y++)
    {
        for (int x = 0; x < Output_Bitmap.Width/2; x++)
        {
            Byte* Output_Row = (Byte*)Output_Data.Scan0 + y * Output_Data.Stride;
            Output_Row[(x * PixelSize) + 2] = 255;
            Output_Row[(x * PixelSize) + 1] = 0;
            Output_Row[(x * PixelSize) + 0] = 0;
        }
    }
}

// Unlock the bits
Output_Bitmap.UnlockBits(Output_Data);

// Set picturebox to use bitmap
pbOutput.Image = Output_Bitmap;
//创建新的输出位图
位图输出\位图=新位图(100100);
//锁定输出位图的位
矩形输出\u矩形=新矩形(
0,
0,
输出位图宽度,
输出(位图高度);
BitmapData输出\ U数据=输出\位图.LockBits(
输出_矩形,
ImageLockMode.WriteOnly,
PixelFormat.Format32bppRgb);
const int PixelSize=4;
不安全的
{
对于(int y=0;y

在本例中,我仅设置图像的左半部分(内部for循环的宽度为/2)。右半部分将在黑色背景上有随机噪声。

这有点推测,因为我不知道这些类的实现细节,但我有一个猜测

调用
新位图(100100)
时,表示位图像素的内存区域未初始化,因此包含分配前这些内存位置中的任何随机垃圾。第一次写入位图时,只需设置位置的子集,其他位置则显示随机内存垃圾


如果是这种情况,则必须确保在第一次更新时写入新
位图中的每个像素。后续更新只需更新更改的像素。

您需要在位图上创建一个图形对象,并在创建位图后调用
graphics.Clear()
,以避免位图内存处于未定义状态


您还应该从使用
Format32bppRgb
更改为
Format32PbppRgb
,因为您没有设置alpha字节。或者切换到24 bpp格式。

在创建输出位图之后,我还尝试了使用(Graphics g=Graphics.FromImage(Output\u Bitmap))g.FillRectangle(brush.Black,0,0,Output\u Bitmap.Width,Output\u Bitmap.Height)快速
但出现了相同的结果。@JYelton,这可能不起作用,因为您稍后会要求特定的像素格式,我可以想象,如果它与默认值不同,则需要新的分配?我现在运行两个循环;一个用于将所有像素设置为黑色,另一个用于设置特定像素。它似乎工作得很好,尽管很明显它的性能受到了影响@道格,我来看看你链接的零内存方法,它可能会取代第一个循环。谢谢。@ JYelton——你可以考虑的另一个优化是只在你要更新的区域上调用<代码> Loopss<代码>(但是更新你锁定的整个区域)。我怀疑当内存被编组到设备上下文或从设备上下文中编组时,问题实际上会发生,通过锁定最小的可能区域,您将节省大量内存。位图对象没有方法
.Clear()
。但是,如果在位图对象上创建图形对象并调用graphics.Clear(color.black),则为True您应该能够清除位图。另外,您的意思是
Format32bppPArgb
而不是
Format32PbppRgb
?使用24bpp可能更好一些,因为我不需要alpha。谢谢你的建议。但是,闪烁/随机像素仍然存在。