Eri*_*bes 38 c# comparison bitmap
我正在尝试编写一个函数来确定两个相等大小的位图是否相同.我现在的功能只是在每个位图中一次比较一个像素,在第一个不相等的像素处返回false.
虽然这可行,并且适用于小位图,但在生产中我将在紧密循环和更大的图像中使用它,所以我需要一种更好的方法.有没有人有任何建议?
我使用的语言就是C# - 是的,我已经在使用.LockBits方法了.=)
编辑:我编写了一些给出的建议的实现,这里是基准测试.设置:两个相同(最坏情况)的位图,大小为100x100,每个迭代次数为10,000次.结果如下:
CompareByInts (Marc Gravell) : 1107ms
CompareByMD5 (Skilldrick) : 4222ms
CompareByMask (GrayWizardX) : 949ms
Run Code Online (Sandbox Code Playgroud)
在CompareByInts和CompareByMask中,我使用指针直接访问内存; 在MD5方法中,我使用Marshal.Copy来检索字节数组并将其作为参数传递给MD5.ComputeHash.CompareByMask只是稍快一点,但考虑到上下文,我认为任何改进都是有用的.
感谢大家.=)
编辑2:忘了打开优化 - 这样做可以让GrayWizardX的答案更加强大:
CompareByInts (Marc Gravell) : 944ms
CompareByMD5 (Skilldrick) : 4275ms
CompareByMask (GrayWizardX) : 630ms
CompareByMemCmp (Erik) : 105ms
Run Code Online (Sandbox Code Playgroud)
有趣的是,MD5方法根本没有改进.
编辑3:发布了我的答案(MemCmp),它将其他方法从水中吹走.OO
Eri*_*bes 34
编辑8-31-12:根据Joey的评论,请注意您比较的位图格式.它们可能在步幅上包含填充,使得位图不相等,尽管它们在像素方面是等效的.有关详细信息,请参阅此问题.
阅读有关比较字节数组的问题的答案已经产生了一个更快的方法:使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您正在尝试确定它们是否100%相等,则可以反转一个并将其添加到另一个,如果它们为零则相同.使用不安全的代码扩展它,一次取64位作为一个长的数字,并以这种方式进行数学计算,任何差异都可能导致立即失败.
如果图像不是100%相同(比较png到jpeg),或者如果你不是在寻找100%匹配,那么你还有更多的工作要做.
祝好运.
好吧,你正在使用.LockBits
,所以大概你使用的是不安全的代码.而不是将每一行origin(Scan0 + y * Stride
)视为a byte*
,考虑将其视为int*
; int
算术很快,你只需做1/4的工作.而对于ARGB中的图像,您可能仍在以像素为单位进行讨论,使数学变得简单.