图片上传,有时会遇到三星手机传上来的是竖拍的照片,需要单独处理
- 增加POM依赖
<!-- 图片旋转处理 https://mvnrepository.com/artifact/com.drewnoakes/metadata-extractor -->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.7.0</version>
</dependency>
- 代码实现
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 图片旋转处理
* https://blog.csdn.net/qq_43501821/article/details/132296979
* @author xxx
*/
@Slf4j
public class ImageRotate {
public static void main(String[] args) {
java.util.List<String> list = new ArrayList<String>();
Arrays.asList("20240914_101154.jpg", "IMG_3926.jpeg", "IMG_5226.jpeg", "IMG_6418.jpeg", "88a93450-231b-4778-bf41-99c6f2e50544.png").forEach(name -> {
list.add(name);
});
String filePath = "/Users/xx/Downloads/";
for (String fileName : list) {
// 读取图片文件
File imageFile = new File(filePath + fileName);
try {
String fullName = filePath + fileName;
int index = fullName.lastIndexOf(".");
String targetImgPath = fullName.substring(0, fullName.lastIndexOf(".")) + "_rotate." + getFileExtension(fileName);
String[] filename = fileName.split("\\.");
File targetFile = File.createTempFile(filename[0], filename[1]);
boolean bCorrect = correctImg(imageFile, targetFile); // new File(targetImgPath)
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 获取文件扩展名
* @param fileName 文件名
* @return 文件扩展名
*/
public static String getFileExtension(String fileName) {
if (fileName == null || fileName.isEmpty()) {
return "";
}
int lastIndexOfDot = fileName.lastIndexOf(".");
if (lastIndexOfDot >= 0 && lastIndexOfDot < fileName.length() - 1) {
return fileName.substring(lastIndexOfDot + 1);
} else {
return "";
}
}
/**
* 纠正图片旋转
*
* @param srcFile 原始图片
* @param targetImgFile 目标图片地址
* @return 是否需要纠正成功, true: 需要纠正, false: 无需纠正
*
*/
public static boolean correctImg(File srcFile, File targetImgFile) throws Exception {
FileOutputStream fos = null;
try {
// 1.获取纠正
RectifyDirection rotateAngle = getRectifyDirection(srcFile);
// 2.无需纠正直接返回
if (rotateAngle == null) {
return false;
}
// 原始图片缓存
BufferedImage srcImg = ImageIO.read(srcFile);
// 原始宽度
int imgWidth = srcImg.getWidth();
// 原始高度
int imgHeight = srcImg.getHeight();
// 3.如果不是垂直的就代表他们的宽高需要互换
if (rotateAngle.angel != 180) {
int temp = imgWidth;
imgWidth = imgHeight;
imgHeight = temp;
}
// 中心点位置
double centerWidth = ((double) imgWidth) / 2;
double centerHeight = ((double) imgHeight) / 2;
// 图片缓存
BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
// 旋转对应角度
Graphics2D g = targetImg.createGraphics();
// 4.以中心点位置 向左旋转
g.rotate(Math.toRadians(rotateAngle.angel), centerWidth, centerHeight);
// 5.旋转后图片的宽高就又替换了。
// 6.这里就需要找到替换后原有的宽高与现有的宽高,从这个坐标开始绘制图片
int x = (imgWidth - srcImg.getWidth()) / 2;
int y = (imgHeight - srcImg.getHeight()) / 2;
g.drawImage(srcImg, x, y, null);
g.dispose();
// 7.是否需要水平翻转
if (rotateAngle.isMirror) {
BufferedImage tempImage = new BufferedImage(targetImg.getWidth(), targetImg.getHeight(), BufferedImage.TYPE_INT_RGB);
g = tempImage.createGraphics();
// 使用 AffineTransform 进行水平翻转
AffineTransform transform = new AffineTransform();
// 8.平移现在图片的宽度后
transform.translate(targetImg.getWidth(), 0);
// 9. 缩放
// 因为横坐标缩放是-1,所以是水平翻转
// 翻转过程见水平翻转图片
transform.scale(-1, 1);
g.setTransform(transform);
g.drawImage(targetImg, 0, 0, null);
g.dispose();
targetImg = tempImage;
}
// 输出图片
fos = new FileOutputStream(targetImgFile);
String formatName = getFormatName(srcFile);
ImageIO.write(targetImg, formatName, fos);
log.info("图片纠正成功:" + targetImgFile.getAbsolutePath());
} catch (Exception e) {
log.warn("图片纠正失败:" + targetImgFile.getName(), e);
return false;
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return true;
}
/**
* 获取纠正方向
*
* @param file
* @return
* @throws Exception
*/
public static RectifyDirection getRectifyDirection(File file) throws Exception {
// 1.获取图片的元数据
Metadata metadata = ImageMetadataReader.readMetadata(file);
// 2.图片元数据处理那种方向
int orientation = 0;
for (Directory directory : metadata.getDirectories()) {
// 3.只需要TAG_ORIENTATION的数据即可。
if (directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
for (Tag tag : directory.getTags()) {
System.out.println(tag);
}
}
}
// 4.根据不同的orientation创建不同的处理方式
switch (orientation) {
case 2:
return new RectifyDirection(0, true);
case 3:
return new RectifyDirection(180, false);
case 4:
return new RectifyDirection(180, true);
case 5:
return new RectifyDirection(90, true);
case 6:
return new RectifyDirection(90, false);
case 7:
return new RectifyDirection(270, true);
case 8:
return new RectifyDirection(270, false);
default:
return null;
}
}
static class RectifyDirection {
/**
* 角度
*/
public int angel;
/**
* 是否镜像
*/
public boolean isMirror;
public RectifyDirection(int angel, boolean isMirror) {
this.angel = angel;
this.isMirror = isMirror;
}
}
/**
* 获取图片格式
*
* @param file
* @return
*/
private static String getFormatName(File file) {
try {
ImageInputStream iis = ImageIO.createImageInputStream(file);
ImageReader reader = ImageIO.getImageReaders(iis).next();
reader.setInput(iis);
String format = reader.getFormatName();
iis.close();
return format;
} catch (IOException e) {
e.printStackTrace();
}
String srcImgPath = file.getName();
return srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1);
}
}```