C# 比较两个Image对象是否相同
方法思路
基础检查:先检查空引用和图像尺寸
像素格式验证:确保两个图像的像素格式相同
内存锁定:使用
LockBits
直接访问内存数据提升效率逐行像素比较:考虑内存对齐的步幅(Stride)差异,逐行比较有效像素数据
实现代码
using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; public class ImageComparer { public static bool AreImagesEqual(Image image1, Image image2) { // 处理空引用情况 if (image1 == null || image2 == null) return image1 == image2; // 快速尺寸检查 if (image1.Size != image2.Size) return false; // 转换为Bitmap以便操作 using (Bitmap bmp1 = new Bitmap(image1)) using (Bitmap bmp2 = new Bitmap(image2)) { // 检查像素格式 if (bmp1.PixelFormat != bmp2.PixelFormat) return false; // 获取像素格式信息 int bitsPerPixel = Image.GetPixelFormatSize(bmp1.PixelFormat); if (bitsPerPixel != Image.GetPixelFormatSize(bmp2.PixelFormat)) return false; int bytesPerPixel = (bitsPerPixel + 7) / 8; // 向上取整 int width = bmp1.Width; int height = bmp1.Height; // 锁定位图内存区域 Rectangle rect = new Rectangle(0, 0, width, height); BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat); BitmapData bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp2.PixelFormat); try { // 计算每行有效字节数 int effectiveBytesPerRow = width * bytesPerPixel; int stride1 = Math.Abs(bmpData1.Stride); int stride2 = Math.Abs(bmpData2.Stride); // 准备行数据缓冲区 byte[] row1 = new byte[effectiveBytesPerRow]; byte[] row2 = new byte[effectiveBytesPerRow]; IntPtr ptr1 = bmpData1.Scan0; IntPtr ptr2 = bmpData2.Scan0; // 逐行比较 for (int y = 0; y < height; y++) { Marshal.Copy(ptr1, row1, 0, effectiveBytesPerRow); Marshal.Copy(ptr2, row2, 0, effectiveBytesPerRow); if (!AreByteArraysEqual(row1, row2)) return false; ptr1 = IntPtr.Add(ptr1, stride1); ptr2 = IntPtr.Add(ptr2, stride2); } return true; } finally { bmp1.UnlockBits(bmpData1); bmp2.UnlockBits(bmpData2); } } } private static bool AreByteArraysEqual(byte[] a1, byte[] a2) { if (a1.Length != a2.Length) return false; for (int i = 0; i < a1.Length; i++) { if (a1[i] != a2[i]) return false; } return true; } }
使用示例
Image img1 = Image.FromFile("image1.png"); Image img2 = Image.FromFile("image2.jpg"); bool isEqual = ImageComparer.AreImagesEqual(img1, img2); Console.WriteLine($"图像是否相同: {isEqual}");
注意事项
像素格式要求:要求两个图像必须具有相同的像素格式(如Format24bppRgb、Format32bppArgb等)
性能考虑:大尺寸图片比较可能较慢,建议在后台线程执行
资源释放:
using
语句确保Bitmap对象正确释放,避免内存泄漏特殊格式:不支持带调色板的索引格式(如Format8bppIndexed)
图像来源:支持不同来源的图片(文件/内存/流),但必须能转换为Bitmap
如果需要处理不同格式的图像,建议先进行标准化转换:
using (Bitmap standardized = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(standardized)) { g.DrawImage(source, 0, 0); } // 使用standardized进行比较 }
转载请注明出处。