为什么在访问WriteableBitmap Image 中的像素时出现AccessViolationException?
Why AccessViolationException occurs when accessing pixels in WriteableBitmap Image?
我有一个从相机到 WPF 图像的视频流。我试图在显示之前逐个像素地访问 WritableBitMap 图像。作为测试,我试图将整个图像设置为白色或黑色。但是,在这两种情况下,我都会收到 AccessViolationException 错误。
我查看了其他帖子,似乎这个错误非常广泛,并非针对我的情况。我似乎不知道为什么我没有得到这个工作。
那么在我的案例中,使用像素的最佳方式是什么?或者为什么这不起作用?感谢任何帮助
private async void UpdateMasterCameraPreview(IdsFrame frame)
{
if (masterImage != null)
frame.Image.CopyTo(masterImage);
else
masterImage = frame.Image.ToWriteableBitmap();
//BitmapImage temp = ConvertWriteableBitmapToBitmapImage(masterImage);
WriteableBitmap temp = masterImage;
// Here I get the exception, on every pixel access
for (int y = 0; y < temp.PixelHeight; y++)
for (int x = 0; x < temp.PixelWidth; x++)
temp.SetPixel(x, y, 255);
masterImage = temp;
masterImage.Lock();
masterImage.AddDirtyRect(new Int32Rect(0, 0, masterImage.PixelWidth, masterImage.PixelHeight));
masterImage.Unlock();
if (OnMasterFrameCaptured != null)
OnMasterFrameCaptured(this, new CameraFrameCapturedArgs(CameraType.Master, masterImage));
}
你已经交换了 X 和 Y,i 代表高度,j 代表宽度,那么你应该像这样调用 SetPixel:
temp.SetPixel(j, i, 255);
在这种情况下,最好为变量使用有意义的名称,例如 X 和 Y。
我最终使用了 this post 的答案。我现在可以编辑任何 WriteableBitmap 图像的原始像素数据,然后再将其发送到 WPF 中的图像控件。下面是我实际使用的,但在这里我只是在一个条件下将每一帧转换为某种透明度:
public void ConvertImage(ref WriteableBitmap Wbmp)
{
int width = Wbmp.PixelWidth;
int height = Wbmp.PixelHeight;
int stride = Wbmp.BackBufferStride;
int bytesPerPixel = (Wbmp.Format.BitsPerPixel + 7) / 8;
unsafe
{
byte* pImgData = (byte*)Wbmp.BackBuffer;
// set alpha to transparent for any pixel with red < 0x88 and invert others
int cRowStart = 0;
int cColStart = 0;
for (int row = 0; row < height; row++)
{
cColStart = cRowStart;
for (int col = 0; col < width; col++)
{
byte* bPixel = pImgData + cColStart;
UInt32* iPixel = (UInt32*)bPixel;
if (bPixel[2 /* bgRa */] < 0x44)
{
// set to 50% transparent
bPixel[3 /* bgrA */] = 0x7f;
}
else
{
// invert but maintain alpha
*iPixel = *iPixel ^ 0x00ffffff;
}
cColStart += bytesPerPixel;
}
cRowStart += stride;
}
}
}
而使用的套路是这样的:
masterImage.Lock();
ConvertImage(ref masterImage);
masterImage.AddDirtyRect(new Int32Rect(0, 0, masterImage.PixelWidth, masterImage.PixelHeight));
masterImage.Unlock();
我有一个从相机到 WPF 图像的视频流。我试图在显示之前逐个像素地访问 WritableBitMap 图像。作为测试,我试图将整个图像设置为白色或黑色。但是,在这两种情况下,我都会收到 AccessViolationException 错误。
我查看了其他帖子,似乎这个错误非常广泛,并非针对我的情况。我似乎不知道为什么我没有得到这个工作。
那么在我的案例中,使用像素的最佳方式是什么?或者为什么这不起作用?感谢任何帮助
private async void UpdateMasterCameraPreview(IdsFrame frame)
{
if (masterImage != null)
frame.Image.CopyTo(masterImage);
else
masterImage = frame.Image.ToWriteableBitmap();
//BitmapImage temp = ConvertWriteableBitmapToBitmapImage(masterImage);
WriteableBitmap temp = masterImage;
// Here I get the exception, on every pixel access
for (int y = 0; y < temp.PixelHeight; y++)
for (int x = 0; x < temp.PixelWidth; x++)
temp.SetPixel(x, y, 255);
masterImage = temp;
masterImage.Lock();
masterImage.AddDirtyRect(new Int32Rect(0, 0, masterImage.PixelWidth, masterImage.PixelHeight));
masterImage.Unlock();
if (OnMasterFrameCaptured != null)
OnMasterFrameCaptured(this, new CameraFrameCapturedArgs(CameraType.Master, masterImage));
}
你已经交换了 X 和 Y,i 代表高度,j 代表宽度,那么你应该像这样调用 SetPixel:
temp.SetPixel(j, i, 255);
在这种情况下,最好为变量使用有意义的名称,例如 X 和 Y。
我最终使用了 this post 的答案。我现在可以编辑任何 WriteableBitmap 图像的原始像素数据,然后再将其发送到 WPF 中的图像控件。下面是我实际使用的,但在这里我只是在一个条件下将每一帧转换为某种透明度:
public void ConvertImage(ref WriteableBitmap Wbmp)
{
int width = Wbmp.PixelWidth;
int height = Wbmp.PixelHeight;
int stride = Wbmp.BackBufferStride;
int bytesPerPixel = (Wbmp.Format.BitsPerPixel + 7) / 8;
unsafe
{
byte* pImgData = (byte*)Wbmp.BackBuffer;
// set alpha to transparent for any pixel with red < 0x88 and invert others
int cRowStart = 0;
int cColStart = 0;
for (int row = 0; row < height; row++)
{
cColStart = cRowStart;
for (int col = 0; col < width; col++)
{
byte* bPixel = pImgData + cColStart;
UInt32* iPixel = (UInt32*)bPixel;
if (bPixel[2 /* bgRa */] < 0x44)
{
// set to 50% transparent
bPixel[3 /* bgrA */] = 0x7f;
}
else
{
// invert but maintain alpha
*iPixel = *iPixel ^ 0x00ffffff;
}
cColStart += bytesPerPixel;
}
cRowStart += stride;
}
}
}
而使用的套路是这样的:
masterImage.Lock();
ConvertImage(ref masterImage);
masterImage.AddDirtyRect(new Int32Rect(0, 0, masterImage.PixelWidth, masterImage.PixelHeight));
masterImage.Unlock();