Asp.net中如何比较两幅图片是否相同

lsd123 2008-12-30 12:42:45
Asp.net中如何比较两幅图片是否相同?
...全文
836 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
zjybushiren88888 2008-12-31
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 winner2050 的回复:]
md5 加密两个图片,比较得到的字符串是否一致。

现在测试软件和光盘等文件是否为官方发布的为篡改的,基本都是用MD5,SA1识别。
[/Quote]
真不错的idea
treesky 2008-12-31
  • 打赏
  • 举报
回复
转换成base64比较
Adechen 2008-12-31
  • 打赏
  • 举报
回复
把图片二进制序列化后再比较,个人看来可行
lsd123 2008-12-31
  • 打赏
  • 举报
回复
.
lsd123 2008-12-31
  • 打赏
  • 举报
回复
恩,
第一,我是考虑效率的问题,担心频繁IO会影响效率,看了你的回复,我的担心没必要了
第二,我想学习下,如何去判断图片是否一样

谢谢楼上的关注和耐心的回复
代码改变世界 2008-12-31
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 lsd123 的回复:]
就是比较人的照片,
比如:
刚新增时添加一照片,
更新时我判断下,如果还是原来的,就不更新,否则相反
[/Quote]
有必要吗?每次都用新的替换掉原来的就行了。。。反正用户上传新的照片那肯定是新的才是用户认为要用的,无论是不是相同,替换肯定都没错。。。。楼主是不是考虑效率的问题(去判断这一过程程序消耗绝对不会比替换小)。。。其实就算判断出来图片中是不是同一内容(人物场景完全一样),但是新的图片它比老的清晰度高或别的什么原因,客户就是要新的啊你干嘛不给他更新?
winner2050 2008-12-30
  • 打赏
  • 举报
回复
md5 加密两个图片,比较得到的字符串是否一致。

现在测试软件和光盘等文件是否为官方发布的为篡改的,基本都是用MD5,SA1识别。
lsd123 2008-12-30
  • 打赏
  • 举报
回复
就是比较人的照片,
比如:
刚新增时添加一照片,
更新时我判断下,如果还是原来的,就不更新,否则相反
wuyq11 2008-12-30
  • 打赏
  • 举报
回复
通过把图片转化为二进制,再比较是否相同
龙宜坡 2008-12-30
  • 打赏
  • 举报
回复
路径?or图像相似性?
曾默 2008-12-30
  • 打赏
  • 举报
回复
说具体点吧
是说图片的文件属性相同
还是说图片上的画相同

前者应该好解决,后者的话估计不太好办了
yyq136 2008-12-30
  • 打赏
  • 举报
回复
图片不能比较吧
Teng_s2000 2008-12-30
  • 打赏
  • 举报
回复
不会,学习...
MAOGE1987 2008-12-30
  • 打赏
  • 举报
回复
MD5着么不能用呢??在电子商务里不是有用MD5加密成报文那样发送进行比较呢
nik_Amis 2008-12-30
  • 打赏
  • 举报
回复
MD5?也能这样用?孤陋寡闻了
MAOGE1987 2008-12-30
  • 打赏
  • 举报
回复
希望对楼主有用啊
MAOGE1987 2008-12-30
  • 打赏
  • 举报
回复
.net中的GDI+能非常方便的进行图象处理,但是并未直接提供进行图片比较的类或者方法,本文的目的是探讨如何进行图片比较。

首先要说明的是,进行比较的两幅图片必须具有相同的格式,并且最好是未经压缩的图片格式。否则,不能进行完全的相同性对比,只能做近似判断,比如各种颜色分量相差5%即认为一致。

在自己动手之前先GOOGLE一番,找到了下面两篇比较典型的文章:

(1)http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/msg/4c8beaa229c2cbd6

这篇文章使用Image.GetPixel方法获取每个像素点的Color,然后将各点组合成一个Hash值。关键代码段:

[CLSCompliant(false)]
public static uint GetBitmapHashValue(
Bitmap image)
{
uint result = 0xFFFFFFFF;


for (int x = 0; x < image.Width; x++)
for (int y = 0; y < image.Height; y++)
result =
BitmapHasher.CRCTable[
(result ^ image.GetPixel(x, y).ToArgb()) & 0xFF] ^
(result >> 8);


return result ^ 0xFFFFFFFF;
}

(2)http://topic.csdn.net/u/20080808/09/c92a057e-ebd0-438c-bc1d-64d0a78127f7.html

CSDN论坛的这个帖子有很多实现图片比较的思路,比如:

(a)比较直接用 memcmp , 10M以内的数据不会超过 1毫秒

当然你不能用 GetPix, GetPix非常慢, 应该直接取出内存块来比较,
图像压缩可以把前后两幅图像相减, 再找个压缩算法压缩相减的结果
另外一边只要加上这个结果就是新的图像
(b)将屏幕分成固定的若干小块,对其分别编号,分块比较,每次只传送发生改变的块
(c)请参考请他VNC开源项目。
它们通常是安装钩子监视屏幕区域的变化,然后压缩传送变化的图片区。
用判断图像变化的办法效率太低,很少被使用。
(d)保存上一张图片,抓到一张新图后,在内存中按块用memcmp比较,如果发现有不同,就发送此块,然后到客户端组装起来

由于本文只讨论图片比较,所有(c)中的安装系统钩子不考虑,其他几点无非就是用GetPixel按像素比较,或者得到图片的内存块然后比较内存块是否一致。

1.使用GetPixel得到各像素,然后逐个像素进行对比:

/// <summary>
/// 比较两幅图片是否一致
/// </summary>
/// <param name="bitmap1">图片1</param>
/// <param name="bitmap2">图片2</param>
/// <returns>如果两幅图片相同,返回0;如果图片1小于图片2,返回小于0的值;如果图片1大于图片2,返回大于0的值。</returns>
public static int BitmapCompare(Bitmap bitmap1, Bitmap bitmap2)
{
int result = 0; //假设两幅图片相同
if (bitmap1 == null || bitmap2 == null)
return -1;
if (bitmap1.Width == bitmap2.Width && bitmap1.Height == bitmap2.Height)
{
for (int i = 0; i < bitmap1.Width; i++)
{
for (int j = 0; j < bitmap1.Height; j++)
{
Color color1 = bitmap1.GetPixel(i, j);
Color color2 = bitmap2.GetPixel(i, j);
if (color1 != color2)
{
result = color1.ToArgb() - color2.ToArgb();
break;
}
}
if (result != 0)
break;
}
}
else if (bitmap1.Width != bitmap2.Width)
{
result = bitmap1.Width - bitmap2.Width;
}
else if (bitmap1.Height != bitmap2.Height)
{
result = bitmap1.Height - bitmap2.Height;
}
return result;
}



2.得到图片数据内存块,然后比较内存块是否一致:

用Bitmap.LockBits方法可以得到BitmapData(位图数据),BitmapData.Scan0指向了位图数据部分的基地址。BitmapData.Stride给出了图象中每行所占的字节数目,注意 BitmapData.Stride并不等于BitmapData.Width,原因如下:(1)BitmapData.Width是每行的像素数目,每个像素所占的字节数跟PixelFormat(像素格式)有关,可以是1、4、8、16、24、32、48、64等位数;(2)系统将图片数据行在内存中进行了对齐,每行所占字节数是4的倍数,且总是大于等于Width*BitsPerPixel/8。Marshal.Copy方法复制内存块到字节数组。

得到图片数据内存块的代码如下:

BitmapData bmd1 = bitmap1.LockBits(new Rectangle(0, 0, bitmap1.Width, bitmap1.Height), ImageLockMode.ReadOnly, bitmap1.PixelFormat); //得到图片数据对象
int bytes = bmd1.Stride * bitmap1.Height; //图片数据大小
byte[] buff1 = new byte[bytes]; //保存图片数据的字节数组
Marshal.Copy(bmd1.Scan0, buff1, 0, Marshal.SizeOf(typeof(byte)) * bytes); //复制图片数据块
//在这里对图片数据块执行操作
bitmap1.UnlockBits(bmd1); //解锁图片数据块

对内存块进行比较的方法有以下几种:

(1)C API函数memcmp,该函数的原型为:

int memcmp(const void *buf1,const void *buf2,size_t count);

PINVOKE引用方式为:

[DllImport("msvcrt.dll")]
private static extern IntPtr memcmp(byte[] b1, byte[] b2, IntPtr count);

(2)用Marshal.ReadByte方法读取内存中的字节,然后逐字节进行比较。

BitmapData bmd1 = bitmap1.LockBits(new Rectangle(0, 0, bitmap1.Width, bitmap1.Height), ImageLockMode.ReadOnly, bitmap1.PixelFormat);
IntPtr start1 = bmd1.Scan0;
int sizeOfByte = Marshal.SizeOf(typeof(byte));
for (int i = 0; i < sizeOfByte * bmd1.Stride * bitmap1.Height; i++)
{
byte b1 = Marshal.ReadByte(start1, i);

//在这里对字节进行操作,也可以用Marshal.WriteByte修改字节内容
}
bitmap1.UnlockBits(bmd1);

(3)自定义函数进行字节数组比较:

public static int MemoryCompare2(byte[] b1, byte[] b2)
{
int result = 0;
if (b1.Length != b2.Length)
result = b1.Length - b2.Length;
else
{
for (int i = 0; i < b1.Length; i++)
{
if (b1[i] != b2[i])
{
result = (int)(b1[i] - b2[i]);
break;
}
}
}
return result;
}

Jack2013tong 2008-12-30
  • 打赏
  • 举报
回复
把图片转到二进制流,再比较每个字节,如果相同就应该相同吧
不知上面的结论是否成立?
  • 打赏
  • 举报
回复
“比较两幅图片是否相同”实际上不同的人的概念歧义太大,一定要谨慎。如果是个程序员的脑袋来解释用户的脑袋,小心闹笑话。如果给10个人看两个图片有9个人都认为图片相同,程序员却说文件二进制不同,那么这就根本是无法调和的了。
加载更多回复(8)

62,074

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧