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进行比较
}转载请注明出处。