Java读取图片exif信息实现图片方向自动纠正

起因

一个对试卷进行OCR识别需求,需要实现一个功能,一个章节下的题目图片需要上下拼接合成一张大图,起初写了一个工具实现图片的合并,程序一直很稳定的运行着,有一反馈合成的图片方向不对,起初怀疑是本身图片方向有问题,但是用windows图片查看器打开图片方向是正常“显示”的

定位

exif信息

查阅相关资料,图片信息中有个exif标准,exif信息如下:

Java读取图片exif信息实现图片方向自动纠正_第1张图片
image

图虫exif信息查看器:https://exif.tuchong.com/
关注IFD0节点方向,Rotate 270 CW,意思图片需要顺时针旋转270°方向正常,windows默认的图片查看器已经帮我们自动旋转展示了,我们在手机横排或者扫描仪、数码相机输出的图片通常包含此类信息,但是我们java读取的是图片的真实方向,所以在生成图片方向自然也就不对了

代码

添加依赖


com.drewnoakes
metadata-extractor
2.15.0

自旋转代码

旋转图片

private static void rotateImage(List stringList) {
stringList.forEach(s -> {
File file = new File(s);
try {
Metadata metadata = ImageMetadataReader.readMetadata(file);
StringBuilder description = new StringBuilder();
metadata.getDirectories().forEach(directory -> {
directory.getTags().forEach(tag -> {
if (tag.getTagType() == ExifDirectoryBase.TAG_ORIENTATION) {
description.append(tag.getDescription().replaceAll(" ", ""));
}
});
});
if (description.length() > 0) {
int rotateIndex = description.indexOf("Rotate");
int cwIndex = description.indexOf("CW");
if (rotateIndex >= 0 && cwIndex > 0 && rotateIndex < cwIndex) {
int angel = Integer.valueOf(description.substring(rotateIndex + 6, cwIndex));
log.info("============图片方向纠正,顺时针旋转{}°,图片路径:{}===========", angel, s);
BufferedImage oldImage = ImageIO.read(file);
BufferedImage newImage = RotateImage.Rotate(oldImage, angel);
ImageIO.write(newImage, "jpg", file);
newImage.getGraphics().dispose();
oldImage.getGraphics().dispose();
}
}
} catch (ImageProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

});

}

图片旋转工具类

import java.awt.*;
import java.awt.image.BufferedImage;

public class RotateImage {
/** * 对图片进行旋转 * * @param src 被旋转图片 * @param angel 旋转角度 * @return 旋转后的图片 */
public static BufferedImage Rotate(Image src, int angel) {
int srcWidth = src.getWidth(null);
int srcHeight = src.getHeight(null);
// 计算旋转后图片的尺寸
Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
srcWidth, srcHeight)), angel);
BufferedImage res = null;
res = new BufferedImage(rect_des.width, rect_des.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = res.createGraphics();
// 进行转换
g2.translate((rect_des.width - srcWidth) / 2,
(rect_des.height - srcHeight) / 2);
g2.rotate(Math.toRadians(angel), srcWidth / 2, srcHeight / 2);

    g2.drawImage(src, null, null);
    return res;
}

/**  * 计算旋转后的图片  *  * @param src   被旋转的图片  * @param angel 旋转角度  * @return 旋转后的图片  */
public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
    // 如果旋转的角度大于90度做相应的转换
    if (angel >= 90) {
        if (angel / 90 % 2 == 1) {
            int temp = src.height;
            src.height = src.width;
            src.width = temp;
        }
        angel = angel % 90;
    }

    double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
    double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
    double angelAlpha = (Math.PI - Math.toRadians(angel)) / 2;
    double angelDeltaWidth = Math.atan((double) src.height / src.width);
    double angelDeltaHeight = Math.atan((double) src.width / src.height);

    int lenDeltaWidth = (int) (len * Math.cos(Math.PI - angelAlpha
        - angelDeltaWidth));
    int lenDeltaHeight = (int) (len * Math.cos(Math.PI - angelAlpha
        - angelDeltaHeight));
    int desWidth = src.width + lenDeltaWidth * 2;
    int desHeight = src.height + lenDeltaHeight * 2;
    return new Rectangle(new Dimension(desWidth, desHeight));
}

}

测试代码

public static void main(String[] args) throws ImageProcessingException, IOException {
File file = new File("D:\temp\error_direction");
List stringList = Arrays.asList(file.listFiles()).stream().map(File::getAbsolutePath).collect(Collectors.toList());
rotateImage(stringList);
}

控制台日志如下:

18:52:40.066 [main] INFO ============图片方向纠正,顺时针旋转270°,图片路径:D:\temp\error_direction\185.jpg=========== 18:52:40.879 [main] INFO ============图片方向纠正,顺时针旋转90°,图片路径:D:\temp\error_direction\186.jpg===========

至此,我们原始图片的方向被纠正了,我们再来看下纠正之后的图片的exif信息,发现旋转信息已经没有了

Java读取图片exif信息实现图片方向自动纠正_第2张图片
image

你可能感兴趣的:(Java读取图片exif信息实现图片方向自动纠正)