java - 从图片回调中读取 android jpeg EXIF 元数据

标签 java android jpeg exif

背景:我正在为信使程序编写相机应用程序。我无法随时将捕获的图像保存到永久磁盘。相机必须支持所有方向。我的实现是熟悉的 Surfaceview 示例。我使用 Display 类来检测方向并相应地旋转相机。在 takePicture jpeg 回调中,我从 byte[] 构造了一个位图,以解决我遇到的一些纵横比问题:Camera API: Cross device issues

问题描述:在某些设备上,在 ROTATION_270(设备顺时针旋转 90 度)拍摄的构造位图颠倒了。到目前为止,它似乎是三星。我只能假设相机可能是以其他方式焊接的,或者有什么影响,但这既不存在也不存在。虽然我可以检查位图是否横向,但我无法从逻辑上检查它是否按维度倒置,因此我需要访问 EXIF 数据。

Android 为这个 http://developer.android.com/reference/android/media/ExifInterface.html 提供了一个解析器。但不幸的是,它有一个接受文件的构造函数......我没有也不想要。直观地说,我可以为字节数组编写一个构造函数,但考虑到他们调用 native 代码http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2.1_r1/android/media/ExifInterface.java,这似乎真的很痛苦。

我的问题分为两部分:

  1. 有谁知道 byte[] 数组是否包含完整的 EXIF jpeg header 数据原样或通过 BitmapFactory.decode(...)/的路径 BitmapFactory.compress(...) 以某种方式添加?

  2. 如果此 EXIF 数据存在于字节数组中,我该如何解析 以可靠的方式提供方向信息?

编辑 2012 年 10 月 18 日

pcans 下面的回答涉及我问题的第 2 部分。正如我在他的回答下面的评论中指出的那样,如果您想使用该解析器,您必须将源代码合并到您的项目中。该链接的 SO 帖子中提到的更改已在此处进行并重新发布:https://github.com/strangecargo/metadata-extractor

NOTE newer versions of metadata-extractor work directly on Android without modification, and are available via Maven.

但是,对于第 1 部分,当我使用从 takePicture 获得的字节数组运行它时,我从解析器返回 0 个标签。我开始担心字节数组没有我需要的数据。我将继续对此进行研究,但欢迎任何进一步的见解。

最佳答案

使用Camera.takePicture()2.9.1版从图像byte[](对metadata extraction library in Java有用)读取元数据/EXIF由 Drew Noakes :

try
{
    // Extract metadata.
    Metadata metadata = ImageMetadataReader.readMetadata(new BufferedInputStream(new ByteArrayInputStream(imageData)), imageData.length);

    // Log each directory.
    for(Directory directory : metadata.getDirectories())
    {
        Log.d("LOG", "Directory: " + directory.getName());

        // Log all errors.
        for(String error : directory.getErrors())
        {
            Log.d("LOG", "> error: " + error);
        }

        // Log all tags.
        for(Tag tag : directory.getTags())
        {
            Log.d("LOG", "> tag: " + tag.getTagName() + " = " + tag.getDescription());
        }
    }
}
catch(Exception e)
{
    // TODO: handle exception
}

要读取图像的 EXIF 方向(不是缩略图的方向):

try
{
    // Get the EXIF orientation.
    final ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
    if(exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION))
    {
        final int exifOrientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);

        /* Work on exifOrientation */
    }
    else
    {
        /* Not found */
    }
}
catch(Exception e)
{
    // TODO: handle exception
}

方向是从 1 到 8。见 here , here , herehere .


根据 EXIF 方向转换位图:

try
{
    final Matrix bitmapMatrix = new Matrix();
    switch(exifOrientation)
    {
        case 1:                                                                                     break;  // top left
        case 2:                                                 bitmapMatrix.postScale(-1, 1);      break;  // top right
        case 3:         bitmapMatrix.postRotate(180);                                               break;  // bottom right
        case 4:         bitmapMatrix.postRotate(180);           bitmapMatrix.postScale(-1, 1);      break;  // bottom left
        case 5:         bitmapMatrix.postRotate(90);            bitmapMatrix.postScale(-1, 1);      break;  // left top
        case 6:         bitmapMatrix.postRotate(90);                                                break;  // right top
        case 7:         bitmapMatrix.postRotate(270);           bitmapMatrix.postScale(-1, 1);      break;  // right bottom
        case 8:         bitmapMatrix.postRotate(270);                                               break;  // left bottom
        default:                                                                                    break;  // Unknown
    }

    // Create new bitmap.
    final Bitmap transformedBitmap = Bitmap.createBitmap(imageBitmap, 0, 0, imageBitmap.getWidth(), imageBitmap.getHeight(), bitmapMatrix, false);
}
catch(Exception e)
{
    // TODO: handle exception
}

关于java - 从图片回调中读取 android jpeg EXIF 元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12944123/

相关文章:

android - 减少 Android 替代绘图资源

android - 为什么使用 float 而不是 double 不会提高 Android 性能?

Android fragment 更改标题

imagemagick - webp 格式比 JPEG 更有效吗?

java - 如何使用 JAVA 将带有 alpha 的 PNG 转换为保留颜色的 JPEG

java - 如何使用泛型在 Java 中创建通用方法?

Java Selenium + 2Captcha + 提交表单

java - 同一项目中的多个 android-support-v4 版本

java - hibernate 的命名查询有问题

html - 为什么某些 jpeg 图片无法在旧 iOS 版本的 iPhone 中加载?