ImageIO.read() 是否考虑了 EXIF 方向元数据?

Does ImageIO.read() take EXIF orientation metadata into account?

在 JPEG 图像中,有时会包含 EXIF 元数据,它会告诉图像应该以什么方向显示。

问题是,Java 的 ImageIO.read() 在读取 JPEG 图像时是否考虑了 EXIF,并自动应用转换。

更具体地说,如果我使用 Java 的 ImageIO 将带有 EXIF 的 JPEG 图像转换为 PNG 图像,PNG 图像的方向是否正确?或者下面的代码是否会在不考虑 EXIF 方向指令的情况下生成 PNG 图像?

private byte[] convertToPng(byte[] imageFileAsByteArray) {
    ByteArrayInputStream bis = new ByteArrayInputStream(imageFileAsByteArray);
    BufferedImage bi = ImageIO.read(bis);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(bi, "png", bos);

    return bos.toByteArray();
}

不幸的是,简短的回答是否定的; ImageIO.read(..)(默认情况下)不考虑 Exif Orientation 标签。您的 PNG 不会相应地旋转。


但是,所有 ImageIO.read(..) 在内部所做的就是为输入查找合适的 ImageReader 插件,并将读取委托给它。虽然 JRE 捆绑插件不考虑 Exif,但可以在第三方 ImageReader 中添加对它的支持。不幸的是,我不知道有没有这样做,但我正在考虑在将来添加 Exif orientation support to the TwelveMonkeys ImageIO JPEGImageReader

同时,您必须通过读取元数据和旋转来自己应用旋转。可以使用 ImageIO JPEG metadata or some third-party library. I think both the mentioned metadata-extractor or TwelveMonkeys ImageIO 获取方向标签的值,可用于此目的。 JAI ImageIO(使用 TIFF 元数据)可能也可以做到这一点。

如果使用 ImageIO JPEG 元数据,请注意:

Note that an application wishing to interpret Exif metadata given a metadata tree structure in the javax_imageio_jpeg_image_1.0 format must check for an unknown marker segment with a tag indicating an APP1 marker and containing data identifying it as an Exif marker segment.