我正在尝试编写一个函数来确定两个相等大小的位图是否相同。我现在拥有的函数只是简单地一次比较每个位图中的一个像素,在第一个不相等的像素处返回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
编辑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); } }