You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中BufferedImage加载竖版图片宽高被交换问题求助

竖版图片读取后宽高被交换的原因及解决方案

你遇到的问题核心是竖版图片的EXIF方向元数据未被处理:
很多手机或相机拍摄竖图时,会将图片以横版像素格式存储,同时在EXIF元数据中写入Orientation(方向)标签(比如顺时针旋转90度),用于告诉显示设备正确的展示方向。但ImageIO.read()方法只会读取图片的原始像素宽高,不会自动根据EXIF的方向信息调整视觉上的宽高,导致你获取到的是像素层面的原始尺寸,而非实际显示的宽高。

解决思路

读取图片的EXIF方向标签,根据标签值修正宽高,或者直接将图片旋转到正确方向后再获取宽高。

方法1:使用第三方库简化处理(推荐)

原生JDK处理EXIF元数据非常繁琐,推荐使用Apache Commons Imaging(原Sanselan)库,它能轻松读取EXIF信息并自动修正图片方向。

  1. 引入Maven依赖:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-imaging</artifactId>
    <version>1.0-alpha3</version>
</dependency>
  1. 代码示例:
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.imaging.Imaging;
import java.io.File;

public class ImageOrientationFix {
    public static void main(String[] args) throws Exception {
        File imgFile = new File("your-image-path.jpg");
        
        // 读取包含EXIF方向的图片信息
        ImageInfo imageInfo = Imaging.getImageInfo(imgFile);
        int orientation = imageInfo.getOrientation();
        
        // 根据方向标签修正宽高
        int pixelWidth = imageInfo.getWidth();
        int pixelHeight = imageInfo.getHeight();
        int actualWidth, actualHeight;
        
        // 方向标签对应的宽高转换规则
        switch (orientation) {
            // 顺时针/逆时针90度相关方向,宽高互换
            case 5:
            case 6:
            case 7:
            case 8:
                actualWidth = pixelHeight;
                actualHeight = pixelWidth;
                break;
            // 其他方向宽高不变
            default:
                actualWidth = pixelWidth;
                actualHeight = pixelHeight;
                break;
        }
        
        System.out.println("视觉实际宽:" + actualWidth + ",视觉实际高:" + actualHeight);
        
        // 若需要直接获取修正方向后的图片,可使用以下代码
        // BufferedImage correctedImage = Imaging.getBufferedImage(imgFile);
        // int correctedWidth = correctedImage.getWidth();
        // int correctedHeight = correctedImage.getHeight();
    }
}

方法2:原生JDK读取EXIF方向(不推荐,繁琐)

如果不想引入第三方库,可通过JDK的IIOMetadata解析EXIF的Orientation标签,但仅支持JPEG等部分格式,代码复杂度高:

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.util.Iterator;

public class NativeExifOrientationReader {
    public static int getOrientation(File imageFile) throws Exception {
        try (ImageInputStream stream = ImageIO.createImageInputStream(imageFile)) {
            Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
            if (!readers.hasNext()) {
                return 1; // 默认正常方向
            }
            
            ImageReader reader = readers.next();
            try {
                reader.setInput(stream);
                IIOMetadata metadata = reader.getImageMetadata(0);
                String exifFormat = "javax_imageio_jpeg_image_1.0";
                
                if (metadata.containsMetadata(exifFormat)) {
                    IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(exifFormat);
                    IIOMetadataNode exifNode = (IIOMetadataNode) root.getElementsByTagName("exif").item(0);
                    if (exifNode != null) {
                        IIOMetadataNode ifdNode = (IIOMetadataNode) exifNode.getElementsByTagName("ExifIFD").item(0);
                        if (ifdNode != null) {
                            for (int i = 0; i < ifdNode.getLength(); i++) {
                                IIOMetadataNode entryNode = (IIOMetadataNode) ifdNode.item(i);
                                if ("Orientation".equals(entryNode.getAttribute("tagname"))) {
                                    return Integer.parseInt(entryNode.getAttribute("value"));
                                }
                            }
                        }
                    }
                }
            } finally {
                reader.dispose();
            }
            return 1;
        }
    }

    public static void main(String[] args) throws Exception {
        File imgFile = new File("your-image-path.jpg");
        int orientation = getOrientation(imgFile);
        
        BufferedImage srcImage = ImageIO.read(imgFile);
        int pixelWidth = srcImage.getWidth();
        int pixelHeight = srcImage.getHeight();
        
        int actualWidth, actualHeight;
        switch (orientation) {
            case 5:
            case 6:
            case 7:
            case 8:
                actualWidth = pixelHeight;
                actualHeight = pixelWidth;
                break;
            default:
                actualWidth = pixelWidth;
                actualHeight = pixelHeight;
                break;
        }
        
        System.out.println("视觉实际宽:" + actualWidth + ",视觉实际高:" + actualHeight);
    }
}

内容的提问来源于stack exchange,提问作者user20519169

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 16:55:19