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

2023-12-21

背景:我正在为消息程序编写相机应用程序。我无法随时将捕获的图像保存到永久磁盘。相机必须支持所有方向。我的实现是熟悉的 Surfaceview 示例。我使用 Display 类来检测方向并相应地旋转相机。在 takePicture jpeg 回调中,我从 byte[] 构造了一个位图,以解决我遇到的一些宽高比问题:相机 API:跨设备问题 https://stackoverflow.com/questions/12736881/android-camera-api-cross-device-nightmare

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

Android为此提供了一个解析器http://developer.android.com/reference/android/media/ExifInterface.html http://developer.android.com/reference/android/media/ExifInterface.html但不幸的是它有一个接受文件的构造函数...我没有也不想要。直觉上我可以为字节数组编写一个构造函数,但是考虑到它们对本机代码的调用,这似乎真的很痛苦http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2.1_r1/android/media/ExifInterface.java 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 标头 数据原样或者是通过 BitmapFactory.decode(...) / 的路径 BitmapFactory.compress(...) 以某种方式添加它?

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

编辑 2012 年 10 月 18 日

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

注意较新版本元数据提取器 https://drewnoakes/code/exif/无需修改即可直接在 Android 上工作,并且可通过 Maven 获取。

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


从图像中读取元数据/EXIFbyte[](对...有用Camera.takePicture() http://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback,%20android.hardware.Camera.PictureCallback)) using 版本2.9.1 of the Java中的元数据提取库 http://www.drewnoakes.com/code/exif/ by 德鲁·诺克斯 https://stackoverflow.com/users/24874/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 http://sylvana.net/jpegcrop/exif_orientation.html, here http://www.impulseadventure.com/photo/exif-orientation.html, here http://developer.android.com/reference/android/media/ExifInterface.html or here http://beradrian.wordpress.com/2008/11/14/rotate-exif-images/.


要根据位图的 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
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从图片回调中读取android jpeg EXIF元数据 的相关文章

  • 改造Android基本且简单的问题

    我的服务器返回简单的 Json 结果 如下所示 message Upload Success 我正在尝试将结果放入改造模型类中 public class MyResponse SerializedName message String me
  • splitByWholeSeparatorPreserveAllTokens 和 split 之间的区别

    有什么区别StringUtils splitByWholeSeparatorPreserveAllTokens and String split With splitByWholeSeparatorPreserveAllTokens 我们可
  • Android apk 调试模式工作正常,但发布模式给出太多警告

    我正在尝试从 eclipse 获取签名的 APK 我有一个可调试的 apk 版本 运行良好 现在发布时 当我尝试使用 Eclipse ADT 进行编译和签名时 我收到很多警告 其中大部分是can t find superclass or i
  • JavaPreparedStatementUTF-8字符问题

    我有一份准备好的声明 PreparedStatement st 在我的代码中 我尝试使用 st setString 方法 st setString 1 userName userName 的值为 ak a setString 方法将 ak
  • java中main的返回类型

    我想知道为什么java中main方法只有void返回类型 public static void main String args 为什么main方法除了void之外没有其他返回类型 Thanks 简短的回答是 因为这就是语言规范 http
  • AIX:IBM Java:java.net.SocketException:连接超时:可能是由于地址无效

    当尝试与我们的服务器建立 SSL 连接时 我们在 IBM AIX 上经常看到以下异常 java net SocketException Socket closed at com sun net ssl internal ssl SSLSoc
  • 如何加快 jar 签名者的速度?

    我使用 ant 来签署我的 jars 以进行网络启动部署 Ant signjar 在 Web 启动签名时非常慢 如何加快签名过程 我找到了一种可能的解决方案 早些时候 在构建脚本 ant signjar 中 按顺序调用所有 jar 我们使用
  • 协程和 Firebase:如何实现类似 Javascript 的 Promise.all()

    在 Javascript 中 您可以同时启动两个 或更多 异步任务 等待它们完成 然后执行某些操作 继续 const firstReturn secondReturn await Promise all firstPromise secon
  • Ubuntu 的打包 - Web 应用程序

    Web 应用程序没有与 C 或类似文件不同的 make 文件 但是 它需要放置在特定的目录中 例如 var www 我是 Linux 打包新手 所以我的问题是 如何将我的应用程序打包到 deb 中 以便在安装时将其放入 etc myprog
  • 使用java读取Excel工作表的单列

    我有一张 Excel 表格 我想编写一个方法 该方法将参数作为要读取的列号 并返回一个由该列中的所有数据组成的数组 然后将该列元素放置在 xml 工作表中 我怎样才能编写一个方法来做到这一点 使用 Apache POI 您可以在他们的使用页
  • Apache HttpClient 执行时会在所有 HTTP 5XX 错误上抛出 IOException 吗?

    The Apache HttpClient 文档 http hc apache org httpcomponents client ga httpclient apidocs org apache http client HttpClien
  • 在Java中使用==而不是equals来比较不可变对象可以吗

    考虑调用静态工厂方法 valueOf 的两个 Integer 类型的引用 如下所示 Integer a Integer valueOf 10 Integer b Integer valueOf 10 考虑到Integer是不可变的 使用 而
  • 使用 Mockitos 传递参数化输入

    我正在使用 Mockito 进行单元测试 我想知道是否可以使用 Junit 测试中的方式发送参数化输入参数 e g InjectMocks MockClass mockClass new MockClass Test public void
  • 在Java程序中计算zip文件的md5哈希值

    我有一个 zip 文件 在我的 Java 代码中我想计算 zip 文件的 md5 哈希值 有没有我可以用于此目的的 java 库 一些例子将非常感激 谢谢 几周前我通过这篇文章做到了这一点 http www javalobby org ja
  • Google App Engine数据存储区字符串编码问题

    你好 我正在使用 Google App Engine 进行一个项目 并且需要存储一些字符串 我正在使用 Java 和JDOHelper getPersistenceManagerFactory transactions optional 在
  • Exif 方向标签返回 0

    我正在开发一个自定义相机应用程序 我面临以下问题 当我尝试使用检索方向时ExifInterface 它总是返回 0 ORIENTATION UNDEFINED 这使我无法将图像旋转到正确的状态 从而无法正确显示 我使用示例代码来设置相机旋转
  • 从 SQL 语句中检索元数据(表名)

    我使用的是 Visual Studio 2008 我创建了一个 Winforms 应用程序 并且尝试从 SQL 语句中提取表名 con new SqlConnection connString String queryString Sele
  • Web服务连接超时和请求超时之间的区别

    WebClientTestService service new WebClientTestService int connectionTimeOutInMs 5000 Map
  • 如何用 XML 制作双渐变(类似 iphone)

    如何使用 XML 制作这种可绘制渐变 我可以做一个从颜色 A 到颜色 B 的简单渐变 但我不知道如何在同一个可绘制对象中组合两个渐变 我终于找到了一个带有图层列表的解决方案 这对我来说已经足够好了
  • Java applet 是否会违反同源策略

    我需要请求一些东西并从其他域获取信息 我知道由于同源政策 javascript 无法做到这一点 我的另一个选择是通过我的服务器发出代理请求 我不希望请求来自我的服务器的 IP 也不想为我的服务器创建额外的负载 并且希望客户端这样做 是否可以

随机推荐