日常开发中,会遇到对图片的处理,但是有时候用Java的ioimage是不能读取到图片的旋转信息的,所以下述工具类提供了图片旋转信息读取能力。
package com.zx.test.common.utils;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
/**
* 图像处理工具类
*
* @author
* Create on 2023/9/11
*/
@Slf4j
public class ImageUtils {
/**
* 图片翻转时,计算图片翻转到正常显示需旋转角度
*/
public static int getRotateAngleForPhoto(InputStream inputStream) {
int angel = 0;
try {
//核心对象操作对象
Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
//获取所有不同类型的Directory,如ExifSubIFDDirectory, ExifInteropDirectory, ExifThumbnailDirectory等,这些类均为ExifDirectoryBase extends Directory子类
//分别遍历每一个Directory,根据Directory的Tags就可以读取到相应的信息
int orientation = 0;
Iterable<Directory> iterable = metadata.getDirectories();
for (Iterator<Directory> iter = iterable.iterator(); iter.hasNext(); ) {
Directory dr = iter.next();
if (dr.getString(ExifIFD0Directory.TAG_ORIENTATION) != null) {
orientation = dr.getInt(ExifIFD0Directory.TAG_ORIENTATION);
}
/*Collection<Tag> tags = dr.getTags();
for (Tag tag : tags) {
System.out.println(tag.getTagName() + ": " + tag.getDescription());
}*/
}
if (orientation == 0 || orientation == 1) {
angel = 360;
} else if (orientation == 3) {
angel = 180;
} else if (orientation == 6) {
angel = 90;
} else if (orientation == 8) {
angel = 270;
}
} catch (Exception e) {
e.printStackTrace();
}
return angel;
}
/**
* 旋转图片
*/
public static BufferedImage rotateImage(BufferedImage bufferedImage, int angel) {
if (bufferedImage == null) {
return null;
}
if (angel < 0) {
// 将负数角度,纠正为正数角度
angel = angel + 360;
}
log.info("图片需要旋转:{}度数", angel);
int imageWidth = bufferedImage.getWidth(null);
int imageHeight = bufferedImage.getHeight(null);
// 计算重新绘制图片的尺寸
Rectangle rectangle = calculatorRotatedSize(new Rectangle(new Dimension(imageWidth, imageHeight)), angel);
// 获取原始图片的透明度
int type = bufferedImage.getColorModel().getTransparency();
BufferedImage newImage = null;
newImage = new BufferedImage(rectangle.width, rectangle.height, type);
Graphics2D graphics = newImage.createGraphics();
// 平移位置
graphics.translate((rectangle.width - imageWidth) / 2, (rectangle.height - imageHeight) / 2);
// 旋转角度
graphics.rotate(Math.toRadians(angel), imageWidth / 2, imageHeight / 2);
// 绘图
graphics.drawImage(bufferedImage, null, null);
return newImage;
}
/**
* 计算旋转后的尺寸
*
* @param src
* @param angel
* @return
*/
private static Rectangle calculatorRotatedSize(Rectangle src, int angel) {
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 angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
double angel_dalta_width = Math.atan((double) src.height / src.width);
double angel_dalta_height = Math.atan((double) src.width / src.height);
int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
int des_width = src.width + len_dalta_width * 2;
int des_height = src.height + len_dalta_height * 2;
return new java.awt.Rectangle(new Dimension(des_width, des_height));
}
}