为什么我会遇到“尝试读取或写下受保护的内存”错误.”在C#中调整图像大小后



我正在使用phash来计算大型图像数据库的哈希值。这些图像具有很高的分辨率,因此我需要调整它们以快速计算哈希。

但是,当我调整图像大小时,phash程序会引发错误。如果我不调整大小,则PHASH程序可以正常工作。

我的调整大小代码如下。

public void ResizeImage(string ImagePath, int width, int height, string newPath)
    {
        Bitmap b = new Bitmap(width, height);
        using (Graphics g = Graphics.FromImage((Image)b))
        {
            FileStream fs = new FileStream(ImagePath, FileMode.Open);
            Image img = Image.FromStream(fs);
            g.DrawImage(img, 0, 0, width, height);
            fs.Close();
        }
        b.Save(newPath);
        b.Dispose();
    }

我收到的错误是"试图读取或写下受保护的内存"。

phash代码如下:

 ph_dct_imagehash(imagePath, ref hash);

上面的功能调用C 程序,并将该图像的哈希值返回。当图像未通过编程大小调整大小时,它可以正常工作。如果我使用MS涂料调整图像大小,则还可以正常工作。

您不需要FileStream即可打开图像,您只能使用Bitmap myBmp = Bitmap.FromFile("path");

尝试删除文件流。

可以在ph_dct_imagehash的呼叫中找到问题。这调用了非托管代码,显然在托管领域和未管理的领域之间的互动存在错误。

问题中的代码与问题无关。解决方案将是通过使用ph_dct_imagehash查找和解决问题。

我们无法提供有关如何执行此操作的任何详细信息,因为您没有提供ph_dct_imagehash上的详细信息。

这就是我能够解决答案的方式。

public void ResizeImage(string ImagePath, int width, int height, string newPath)
{
    Bitmap b = new Bitmap(width, height);
    using (Graphics g = Graphics.FromImage((Image)b))
    {
        FileStream fs = new FileStream(ImagePath, FileMode.Open);
        Image img = Image.FromStream(fs);
        g.CompositingQuality = CompositingQuality.HighSpeed;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.CompositingMode = CompositingMode.SourceCopy;
        g.DrawImage(img, 0, 0, width, height);
        fs.Close();
    }
    b.Save(newPath);
    b.Dispose();
}

我知道调整大小功能而不是ph_dct_imagehash函数存在一些问题。

发生类似的错误,几乎完全相同 - 从现有的错误创建一个新的位图。差异是我们的作物是一种农作物,而不是您的安全gdip系列,我们的例外是与您的同一类中不同的.NET方法:system.safing.safenativemethods.gdip.gdipdrawimagerectrecti。

>

我们做的与您几乎相同的事情(尽管我们裁剪而不是调整大小,但要复制一个位图)。另外,我们需要在内存中的位图,以便无法处理最终图像,但否则它与您的原始示例相同。

我们的解决方案不同。即使我们的错误阶段发生了错误,但我们还是使用了一个提供了裁剪的位图的第三方库。

要测试这是Windows问题还是库的问题,请写了一种新方法,将原始数据(3通道BGR BYTE数据)转换为BMP。这解决了错误。

奇怪的是,我们有现有的代码,该代码在其他地方使用了库的位图转换器……这里的区别在于,作为单个处理运行的一部分,相同的图像数据被转换为位图两次。如果将其转换为一次,并将手柄缓存/重复使用,而不是在串联两次创建它……这也解决了问题。

如果您使用的是第三方代码,即使堆栈跟踪显示为.NET。

,也可能是罪魁祸首。

最新更新