【问题标题】:Android compute hash of a bitmapAndroid 计算位图的哈希值
【发布时间】:2012-06-20 20:57:21
【问题描述】:

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

我发现了这个:

Compute SHA256 Hash in Android/Java and C#

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

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

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

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

【问题讨论】:

  • 您的问题非常令人困惑:您是否希望两个具有相同“内部图片”和不同名称的位图产生相同的哈希?为什么您已经找到的不是适合您的解决方案?是的 Bitmaps.hashCode() 返回一个整数,它有什么问题(如果不强制使用 SHA)?如果您想获得有意义的答案,请重新表述您的问题
  • 我在解析网站时收到不同的位图(验证码),通常是具有不同名称的相同图片。可能是我误解了 Bitmap.hashCode(),它为对象生成哈希,而不是为位图内容生成哈希? // 编辑问题

标签: android hash bitmap


【解决方案1】:

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

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

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

HTH

【讨论】:

    【解决方案2】:

    这里是计算位图哈希的更原生方式,使用Arrays.hashCodebitmap.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);
    }
    

    【讨论】:

      【解决方案3】:

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

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

      比接受的答案快近 100 倍

      【讨论】:

      • 总是返回 1
      【解决方案4】:

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

      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 像素散列一次

      【讨论】:

        【解决方案5】:

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

        fun getUniqueBitmapFileName(bitmap: Bitmap): String {
            val buffer = ByteBuffer.allocate(bitmap.getByteCount())
            bitmap.copyPixelsToBuffer(buffer)
            return Arrays.hashCode(buffer.array()).toString()
        }
        

        【讨论】:

          猜你喜欢
          • 2014-04-01
          • 2016-06-23
          • 1970-01-01
          • 2019-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-18
          • 1970-01-01
          相关资源
          最近更新 更多