6

我想计算不同位图的 SHA1 哈希(不强制使用 SHA)。问题是有些位图(验证码)基本相同,但名称经常更改。

我发现了这个:

在 Android/Java 和 C# 中计算 SHA256 哈希

但这不是我想要的解决方案。

Bitmap.hashCode(),只生成一个 Integer,当我正确时

返回此对象的整数哈希代码。根据约定,equals(Object) 返回 true 的任何两个对象都必须返回相同的哈希码值。这意味着 Object 的子类通常会覆盖这两种方法或都不覆盖任何方法。

我不想要对象的哈希码,我想要位图内容的哈希码。谢谢!

4

5 回答 5

7

在 Android 3.1 或更高版本(API 级别 12)中,Bitmap调用了一个方法,sameAs()该方法将比较像素并返回两者是否代表相同的图像。它在本机代码中执行此操作,因此速度相对较快。

如果您必须以较低的 API 级别为目标,则必须编写一个方法来迭代两个对象的每个像素并查看它们是否匹配。如果在 Java 代码中完成,这将是一个非常密集的过程,因此您可以考虑使用 NDK 编写一个小例程,您可以从应用程序调用该例程以在本机代码中进行比较(NDK 中有位图 API,因此您可以轻松获取像素缓冲区)。

如果您选择在 Java 中这样做,getPixels()它将帮助您获取可以在两个图像之间进行比较的像素数据数组。

高温高压

于 2012-06-20T21:49:15.447 回答
2

这是计算位图哈希的更本地方法,使用Arrays.hashCode, 和bitmap.getPixels

int hash(Bitmap bitmap){
   int[] buffer = new int[bitmap.getWidth(), bitmap.getHeight()];
   bitmap.getPixels(buffer, 0, 0, 0, 0, bitmap.getWidth(), bitmap.getHeight());
   return Arrays.hashCode(buffer);
}
于 2019-04-09T18:49:01.597 回答
2

迄今为止我在 kotlin 中找到的最快的解决方案:

fun Bitmap.hash(): Int {
    val buffer: ByteBuffer = ByteBuffer.allocate(this.height * this.rowBytes)
    this.copyPixelsToBuffer(buffer)
    return buffer.hashCode()
}

比公认的答案快近 100 倍

于 2020-04-03T10:17:18.140 回答
1

您可以尝试仅使用位图中的像素来编写自己的函数:

public long hashBitmap(Bitmap bmp){
  long hash = 31 //or a higher prime at your choice
  for(int x = 0; x < bmp.getWidth(); x++){
    for (int y = 0; y < bmp.getHeight(); y++){
      hash *= (bmp.getPixel(x,y) + 31);
    }
  }
  return hash;
}

如果只是比较两个图像,您可以优化此例程以每秒或 x 像素散列一次

于 2012-06-20T21:50:57.683 回答
1

类似的问题,这对我有用(解决了为特定位图获取新名称的问题,因此我可以检查它是否已经存储):

fun getUniqueBitmapFileName(bitmap: Bitmap): String {
    val buffer = ByteBuffer.allocate(bitmap.getByteCount())
    bitmap.copyPixelsToBuffer(buffer)
    return Arrays.hashCode(buffer.array()).toString()
}
于 2021-08-24T10:17:58.613 回答