如何避免“噪音”在不安全代码中设置图像像素时
我正在 C# winforms 项目中使用“不安全”代码创建(然后更改)位图。每 30 毫秒左右执行一次。我遇到的问题是,“噪声”或随机像素有时会出现在生成的位图中,而我没有专门更改任何内容。
例如,我创建一个 100x100 的位图。使用 BitmapData
和 LockBits
,我迭代位图并将某些像素更改为特定颜色。然后我 UnlockBits
并设置一个图片框来使用该图像。我设置的所有像素都是正确的,但是我没有专门设置的像素有时看起来是随机的颜色。
如果我设置每个像素,噪音就会消失。但是,出于性能原因,我宁愿只设置最小数量。
谁能解释为什么这样做?
下面是一些示例代码:
// 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;
在此示例中,我仅设置图像的左半部分(内部 for 循环中的宽度/2)。右半部分将在黑色背景上产生随机噪声。
I am creating (then altering) a bitmap using "unsafe" code in a C# winforms project. This is done every 30ms or so. The problem I'm having is that "noise" or random pixels will show up sometimes in the resulting bitmap where I did not specifically change anything.
For example, I create a bitmap of 100x100. Using BitmapData
and LockBits
, I iterate through the bitmap and change certain pixels to a specific color. Then I UnlockBits
and set a picturebox to use the image. All of the pixels I set are correct, but pixels that I did not specifically set are sometimes seemingly random colors.
If I set every pixel, the noise disappears. However, for performance reasons, I would prefer only to set the minimum number.
Can anyone explain why it does this?
Here is some example code:
// 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;
In this example, I am only setting the left half of the image (Width/2 in the inner for loop). The right half will have random noise on an otherwise black background.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这有点推测,因为我不了解这些类的实现细节,但我有一个猜测。
当您调用
new Bitmap(100, 100)
时,表示位图像素的内存区域未初始化,因此包含在其被初始化之前这些内存位置中的任何随机垃圾。分配。第一次写入位图时,您仅设置位置的一个子集,其他位置则显示随机内存垃圾。如果是这种情况,那么您必须确保在第一次更新时写入新
位图
中的每个像素。后续更新只需要更新变化的像素即可。This is somewhat speculative, since I'm not privy to the implementation details of any of these classes, but I have a guess.
When you call
new Bitmap(100, 100)
, the memory region that represents the bitmap's pixels is uninitialized, and therefore contains whatever random garbage was in those memory locations before it was allocated. The first time that you write to the bitmap you then set a only a subset of the locations, and the others show the random memory garbage.If this is the case, then you must be sure to write to every pixel in the new
Bitmap
the first time you update it. Subsequent updates only need to update the changed pixels.您需要在位图上创建一个图形对象,并在创建位图后调用
Graphics.Clear()
以避免位图内存处于未定义状态。您还应该从使用
Format32bppRgb
更改为Format32PbppRgb
,因为您没有设置 alpha 字节。要么切换到 24 bpp 格式。You'll need to create a graphics object over the bitmap and place a
Graphics.Clear()
call after you create your bitmap to avoid undefined state of the bitmap memory.You should also change from using
Format32bppRgb
toFormat32PbppRgb
because you're not setting the alpha byte. Either that or switch to the 24 bpp format.