小编典典

比较两个相等大小的位图以确定它们是否相同的最快方法是什么?

c#

我正在尝试编写一个函数来确定两个相等大小的位图是否相同。我现在拥有的函数只是简单地一次比较每个位图中的一个像素,在第一个不相等的像素处返回false。

虽然这可行,并且对小位图也很好,但是在生产中,我将在紧凑的循环中以及在较大的图像上使用它,因此我需要一种更好的方法。有人有什么建议吗?

顺便说一下,我使用的语言是C#,是的,我已经在使用.LockBits方法。=)

编辑 :我已经编码给出的一些建议的实现,这是基准。设置:两个相同(最坏情况)的位图,大小为100x100,每个迭代10,000次。结果如下:

CompareByInts (Marc Gravell) :   1107ms
CompareByMD5  (Skilldrick)   :   4222ms
CompareByMask (GrayWizardX)  :    949ms

在CompareByInts和CompareByMask中,我使用指针直接访问内存。在MD5方法中,我使用Marshal.Copy检索字节数组,并将其作为参数传递给MD5.ComputeHash。CompareByMask仅稍快一点,但是鉴于上下文,我认为任何改进都是有用的。

谢谢大家。=)

编辑2 :忘记打开优化-这样做使GrayWizardX的答案更加有力:

CompareByInts   (Marc Gravell) :    944ms
CompareByMD5    (Skilldrick)   :   4275ms
CompareByMask   (GrayWizardX)  :    630ms
CompareByMemCmp (Erik)         :    105ms

有趣的是,MD5方法根本没有改善。

编辑3 :发表我的答案(MemCmp),这使其他方法无效。O


阅读 280

收藏
2020-05-19

共1个答案

小编典典

编辑8-31-12:根据以下Joey的评论,请注意您比较的位图的格式。它们可能在跨步中包含填充,这些填充使位图不相等,尽管在像素方向上是等效的。有关更多详细信息,请参见此问题


阅读有关比较字节数组的问题的答案后,产生了MUCH FASTER方法:使用P /
Invoke和msvcrt中的memcmp API调用。这是代码:

[DllImport("msvcrt.dll")]
private static extern int memcmp(IntPtr b1, IntPtr b2, long count);

public static bool CompareMemCmp(Bitmap b1, Bitmap b2)
{
    if ((b1 == null) != (b2 == null)) return false;
    if (b1.Size != b2.Size) return false;

    var bd1 = b1.LockBits(new Rectangle(new Point(0, 0), b1.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    var bd2 = b2.LockBits(new Rectangle(new Point(0, 0), b2.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

    try
    {
        IntPtr bd1scan0 = bd1.Scan0;
        IntPtr bd2scan0 = bd2.Scan0;

        int stride = bd1.Stride;
        int len = stride * b1.Height;

        return memcmp(bd1scan0, bd2scan0, len) == 0;
    }
    finally
    {
        b1.UnlockBits(bd1);
        b2.UnlockBits(bd2);
    }
}
2020-05-19