内存友好的图像哈希

时间:2014-11-14 08:48:51

标签: android image hash bitmap

我从互联网上下载未知尺寸的照片并检查,如果图像与我上次下载的图像相比发生了变化。

为此,我计算一个图像哈希并记住该哈希值。

String currentContactHash = 
    ImageFunctions.getPictureMd5Hash(bitmapTmp, false, errorContactHash);
String currentInputHash = 
    ImageFunctions.getPictureMd5Hash(bitmapToUse, true, errorInputHash);

由于OutOfMemoryError,这有时会失败...我无法控制网络图片的大小,但我需要哈希值。

以下是我的ImageFunctions

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

有人对此有改进建议吗?

1 个答案:

答案 0 :(得分:1)

为什么要尝试获取解码图像数据的哈希?出于您的目的,压缩格式数据的哈希将很好,并且生成起来要快得多,因为它处理的数据少得多。

我猜你正在将图像数据缓存到文件中(尽管缓存到数据库也可以)。从那里你可以将数据作为输入流返回,此时生成摘要的标准代码可以为你提供服务:

MessageDigest digester = MessageDigest.getInstance("MD5");
byte[] bytes = new byte[8192];
int byteCount;
while ((byteCount = in.read(bytes)) > 0) {
  digester.update(bytes, 0, byteCount);
}
byte[] digest = digester.digest();