7

I want to compute a SHA1 hash of different bitmaps (SHA isn't forced). The problem is that there are some bitmaps (captchas) wich are basicly the same, but the name changes often.

I've found this:

Compute SHA256 Hash in Android/Java and C#

But it isn't the soloution i wanted.

The Bitmap.hashCode(), generates only a Integer, and when im right

Returns an integer hash code for this object. By contract, any two objects for which equals(Object) returns true must return the same hash code value. This means that subclasses of Object usually override both methods or neither method.

I dont't want a hash code of the object, i want the hashcode of the bitmap content. Thanx!

Community
  • 1
  • 1
MemLeak
  • 4,456
  • 4
  • 45
  • 84
  • your question is very confusing: do you expect two Bitmaps with the same 'Picture inside' and different names to result in the same hash? Why is what you already found not the right solution for you? Yes Bitmaps.hashCode() returns an integer, whats wrong with it (if SHA isn't forced)? Please rephrase your question, if you want to get a meaningful answer – Rafael T Jun 20 '12 at 21:30
  • I reciev different bitmaps (captchas) from parsing a website, often the same pictures with different names. May be i've missunderstood Bitmap.hashCode(), it generates a hash for the Object, and not for the Bitmap content? // edited question – MemLeak Jun 20 '12 at 21:36

5 Answers5

8

In Android 3.1 or later (API Level 12) there is a method on Bitmap called sameAs() which will compare the pixels and return if the two represent the same image. It does this in native code so it is relatively fast.

If you must target a lower API level, you must write a method that iterates over each pixel of the two objects and see if they match. This will be a very intensive process if done in Java code, so you may consider writing a small routine using the NDK that you can call from your application to do the comparison in native code (there are Bitmap APIs in the NDK so you can easily get at the pixel buffers).

If you opt to do so in Java, getPixels() will assist you in obtaining arrays of the pixel data that you can compare between the two images.

HTH

devunwired
  • 62,780
  • 12
  • 127
  • 139
3

The fastest solution I have found so far in kotlin:

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

nearly 100x faster than the accepted answer

xiaoyu
  • 2,369
  • 2
  • 13
  • 15
2

Here is a more native way for computing Bitmap hash, using Arrays.hashCode, and 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);
}
Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
1

You could try to write your own function using only the Pixel from the Bitmap:

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;
}

if its only about comparing two images you could optimise this routine to hash just every second or x pixel

Rafael T
  • 15,401
  • 15
  • 83
  • 144
1

Similar problem and this worked for me (solved problem with getting a new name for a specific bitmap, so I could check if it was already stored):

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