Java读取图片exif信息实现图片方向自动纠正
2021/4/13 20:25:54
本文主要是介绍Java读取图片exif信息实现图片方向自动纠正,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
起因
一个对试卷进行OCR识别需求,需要实现一个功能,一个章节下的题目图片需要上下拼接合成一张大图,起初写了一个工具实现图片的合并,程序一直很稳定的运行着,有一反馈合成的图片方向不对,起初怀疑是本身图片方向有问题,但是用windows图片查看器打开图片方向是正常“显示”的
定位
exif信息
查阅相关资料,图片信息中有个exif标准,exif信息如下:
图虫exif信息查看器:https://exif.tuchong.com/
关注IFD0节点方向,Rotate 270 CW,意思图片需要顺时针旋转270°方向正常,windows默认的图片查看器已经帮我们自动旋转展示了,我们在手机横排或者扫描仪、数码相机输出的图片通常包含此类信息,但是我们java读取的是图片的真实方向,所以在生成图片方向自然也就不对了
代码
添加依赖
<dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-extractor</artifactId> <version>2.15.0</version> </dependency>
自旋转代码
旋转图片
private static void rotateImage(List<String> 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<String> 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信息实现图片方向自动纠正的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解