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