title: Memory friendly image hash
body: <p>I'm downloading pictures of unknown size from the internet and check, if the image was changed compared to the image I downloaded the last time.</p>
  
  <p>For doing this, I calculate an image hash and remember that hash.</p>
  
  <pre><code>String currentContactHash = 
      ImageFunctions.getPictureMd5Hash(bitmapTmp, false, errorContactHash);
  String currentInputHash = 
      ImageFunctions.getPictureMd5Hash(bitmapToUse, true, errorInputHash);
  </code></pre>
  
  <p>This sometimes fails because of an <code>OutOfMemoryError</code>... I can't control the size of the image from the web, but I need a hash of it.</p>
  
  <p>Here are my <code>ImageFunctions</code>:</p>
  
  <pre><code>public static byte[] convertImageToByteArray(Bitmap bitmap, boolean compress)
  {
      if (compress)
      {
          ByteArrayOutputStream stream = new ByteArrayOutputStream();
          bitmap.compress(CompressFormat.JPEG, 100, stream);
          return stream.toByteArray();
      }
      else
      {
          int bytes = ImageTools.getByteCount(bitmap);
          ByteBuffer buffer = ByteBuffer.allocate(bytes);
          bitmap.copyPixelsToBuffer(buffer);
          return buffer.array();
      }
  }
  
  public static String getPictureMd5Hash(Bitmap bitmap, boolean compress, BooleanHolder error)
  {
      error.set(false);
      try
      {
          return getInternalPictureMd5Hash(bitmap, compress);
      }
      catch (OutOfMemoryError e)
      {
          error.set(true);
          return null;
      }
  }
  
  private static String getInternalPictureMd5Hash(Bitmap bitmap, boolean compress) throws OutOfMemoryError
  {
      if (bitmap == null)
          return null;
  
      byte[] bitmapBytes = convertImageToByteArray(bitmap, compress);
  
      String s;
      try
      {
          s = new String(bitmapBytes, "UTF-8");
      }
      catch (UnsupportedEncodingException e)
      {
          L.e(Updater.class, e);
          return null;
      }
  
      MessageDigest m = null;
  
      try
      {
          m = MessageDigest.getInstance("MD5");
      }
      catch (NoSuchAlgorithmException e)
      {
          L.e(Updater.class, e);
      }
  
      m.update(s.getBytes(), 0, s.length());
      return calcHash(m);
  }
  
  private static String calcHash(MessageDigest m)
  {
      return new BigInteger(1, m.digest()).toString(16);
  }
  </code></pre>
  
  <p>Does anyone have an improvement suggestion for that?</p>