C# 使用图像掩码函数中的BitmapData访问冲突

C# 使用图像掩码函数中的BitmapData访问冲突,c#,pointers,access-violation,bitmapdata,unsafe,C#,Pointers,Access Violation,Bitmapdata,Unsafe,我编写了此函数的一个版本,它将灰度位图作为掩码和源位图,并使用SetPixel和GetPixel输出一个带有掩码的位图,但速度非常慢,因此我尝试使用BitmapData和指针算法编写一个,但我遇到访问冲突,我不确定原因 当写入结果位图中的像素时,我得到了一个AccessViolationException——我认为这是由不正确的索引引起的,但我看不出哪里出了问题 public static Bitmap ApplyAlphaMask2(Bitmap source, Bitmap mask) {

我编写了此函数的一个版本,它将灰度位图作为掩码和源位图,并使用
SetPixel
GetPixel
输出一个带有掩码的位图,但速度非常慢,因此我尝试使用BitmapData和指针算法编写一个,但我遇到访问冲突,我不确定原因

当写入结果位图中的像素时,我得到了一个
AccessViolationException
——我认为这是由不正确的索引引起的,但我看不出哪里出了问题

public static Bitmap ApplyAlphaMask2(Bitmap source, Bitmap mask)
{
    if (source.Size != mask.Size)
    {
        throw new NotImplementedException("Applying a mask of a different size to the source image is not yet implemented");
    }
    Bitmap result = new Bitmap(source.Width, source.Height);
    unsafe
    {
        BitmapData source_data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        BitmapData mask_data = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        BitmapData result_data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        for(int column = 0; column < source.Height; column++)
        {
            Int32* source_column_ptr = (Int32*)source_data.Scan0 + (column * Math.Abs(source_data.Stride));
            Int32* mask_column_ptr = (Int32*)mask_data.Scan0 + (column * Math.Abs(mask_data.Stride));
            Int32* result_column_ptr = (Int32*)result_data.Scan0 + (column * Math.Abs(mask_data.Stride));
            for (int row = 0; row < source.Width; row++)
            {
                Color source_color = Color.FromArgb(source_column_ptr[row]);
                Color mask_color = Color.FromArgb(mask_column_ptr[row]);
                Int32* result_pixel_ptr = &result_column_ptr[row];
                Color result_color = Color.FromArgb((int)(255.0f * mask_color.GetBrightness()), source_color);
                *result_pixel_ptr = result_color.ToArgb(); //Access violation!
            }
        }
        source.UnlockBits(source_data);
        mask.UnlockBits(mask_data);
        result.UnlockBits(result_data);
    }
    return result;
}
public静态位图ApplyAlphaMask2(位图源,位图掩码)
{
if(source.Size!=mask.Size)
{
抛出新的NotImplementedException(“尚未实现对源图像应用不同大小的掩码”);
}
位图结果=新位图(source.Width、source.Height);
不安全的
{
BitmapData source_data=source.LockBits(新矩形(0,0,source.Width,source.Height),ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb);
BitmapData mask_data=mask.LockBits(新矩形(0,0,mask.Width,mask.Height),ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb);
BitmapData result_data=result.LockBits(新矩形(0,0,result.Width,result.Height),ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb);
for(int column=0;column
任何帮助都将不胜感激


编辑:这并不总是发生在同一列上,尽管行始终显示为0,顺便说一下,您的变量名是错误的…需要交换它们
尝试以下修改未测试

    public static Bitmap ApplyAlphaMask2(Bitmap source, Bitmap mask)
    {
        int x, y;
        Color mask_color;

        if (source.Size != mask.Size)
        {
            throw new NotImplementedException("Applying a mask of a different size to the source image is not yet implemented");
        }
        Bitmap result = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb);
        BitmapData source_data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        BitmapData mask_data = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        BitmapData result_data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
        unsafe
        {
            Int32* source_line_ptr = (Int32*)source_data.Scan0;
            Int32* mask_line_ptr = (Int32*)mask_data.Scan0;
            Int32* result_line_ptr = (Int32*)result_data.Scan0;
            for (y = 0; y < source.Height; y++)
            {
                for (x = 0; x < source.Width; x++)
                {
                    mask_color = Color.FromArgb(mask_line_ptr[x]);
                    result_line_ptr[x] = ((int)(mask_color.GetBrightness() * 255.0f) << 24) | (source_line_ptr[x] & 0xFFFFFF);
                }
                source_line_ptr += source_data.Stride;
                mask_line_ptr += mask_data.Stride;
                result_line_ptr += result_data.Stride;
            }
            source.UnlockBits(source_data);
            mask.UnlockBits(mask_data);
            result.UnlockBits(result_data);
        }
        return result;
    }
public静态位图ApplyAlphaMask2(位图源,位图掩码)
{
int x,y;
彩色掩模;
if(source.Size!=mask.Size)
{
抛出新的NotImplementedException(“尚未实现对源图像应用不同大小的掩码”);
}
位图结果=新位图(source.Width、source.Height、PixelFormat.Format32bppArgb);
BitmapData source_data=source.LockBits(新矩形(0,0,source.Width,source.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
BitmapData mask_data=mask.LockBits(新矩形(0,0,mask.Width,mask.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
BitmapData result_data=result.LockBits(新矩形(0,0,result.Width,result.Height)、ImageLockMode.WriteOnly、PixelFormat.Format32bppArgb);
不安全的
{
Int32*源线ptr=(Int32*)源数据.Scan0;
Int32*屏蔽线ptr=(Int32*)屏蔽数据.Scan0;
Int32*结果线ptr=(Int32*)结果数据.Scan0;
对于(y=0;y结果线ptr[x]=((int)(mask_color.GetBrightness()*255.0f)您正在使用
mask_data.Stride
两次(复制-粘贴错误)

为什么在步幅上使用
Math.Abs
?步幅是负数吗?这可能意味着图像从下到上编码,获取Abs值会破坏此信息。
编辑:问题在这里:

(Int32*)source_data.Scan0 + (column * Math.Abs(source_data.Stride))
您将
(column*Math.Abs(source\u data.Stride))
添加到
int*
中,这意味着您将获得所需偏移量的4倍。您可能打算:

(Int32*)((byte*)source_data.Scan0 + (column * Math.Abs(source_data.Stride)))

只是命名不正确。关于这个问题,实际的代码是正确的。@usr我刚才说的是关于列和行的混淆。这不是一个编程错误,只是一个误解(所以
…\u column\u ptr
名称在概念上也是错误的)。设置结果指针时仍然会出现访问冲突:/I使用Math.Abs只是因为此msdn页面上的示例显示了它的使用情况:另外,从
mask\u data.Stride
更改为
result\u data.Stride
没有帮助:/I步幅是否为负值?请检查所有3个步幅。尝试不使用Abs。示例仅对所有步幅使用Abs定位空格,而不是“导航”现有缓冲区。@文档包含以下句子:“跨距是一行像素(扫描线)的宽度,四舍五入到四字节边界。如果跨距为正,则位图为自上而下。如果跨距为负,则位图为自底向上。”。这似乎就是问题所在-位图是自下而上的。我修复了复制/粘贴错误,并删除了Abs,但仍然出现访问冲突:/@Ell我终于发现了错误。我已编辑了我的帖子。