图像的EXIF方向信息(Orientation标签)
问题:
发现用代码处理有些图像(比如苹果手机拍的照片)时,代码里获取的宽和高是反过来的,为什么?
原因(by通义等ai):
iPhone 等设备拍摄的照片会嵌入 EXIF (Exchangeable Image File Format) 元数据,这些信息记录了照片的拍摄设备、时间、参数等,其中包含 Orientation 标签,指示照片的实际旋转角度,例如:
1:正常(0度)
3:旋转 180 度
6:旋转 90 度(顺时针)
8:旋转 270 度(顺时针,或 90 度逆时针)
大多数现代设备(如手机、电脑)在显示图片时会自动根据 EXIF 的旋转标记来调整图片的方向,因此用户看到的是“正确”的图片。
然而,当通过编程方式读取图片尺寸(如使用 BufferedImage.getWidth() 和 BufferedImage.getHeight())时,默认情况下只返回图片的原始尺寸,而不考虑旋转标记。
解决方案
为了正确获取图片的实际宽度和高度,需要处理 EXIF 旋转标记。
可以使用metadata-extractor,这是一个轻量级且易于使用的库,专门用于解析图像元数据:
Maven依赖:
<dependency><groupId>com.drewnoakes</groupId><artifactId>metadata-extractor</artifactId><version>2.18.0</version>
</dependency>
读取 EXIF 的 Orientation:
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;import java.io.File;@Slf4j
public class ImageTest {@Testvoid test0() {try {File imageFile = new File("C:\\Users\\25128\\Desktop\\90.JPG");Metadata metadata = ImageMetadataReader.readMetadata(imageFile);// 尝试从 EXIF 中读取 OrientationExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {int orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);System.out.println("Orientation: " + orientation);} else {System.out.println("No EXIF Orientation tag found.");}} catch (Exception e) {e.printStackTrace();}}}
运行结果:Orientation: 8