Compare commits

...

2 Commits

Author SHA1 Message Date
0d4754eef9 Merge remote-tracking branch 'origin/master'
All checks were successful
Build and Push to Target Registry / 构建并推送镜像到目标仓库 (push) Successful in 6m51s
2025-08-24 16:58:14 +08:00
dad6666107 feat(ImageUtil): 添加图片压缩方向处理功能 2025-08-24 16:58:03 +08:00
2 changed files with 134 additions and 5 deletions

View File

@@ -140,6 +140,12 @@
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>

View File

@@ -1,17 +1,21 @@
package org.dromara.sis.sdk.e8.utils;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.MetadataException;
import com.drew.metadata.exif.ExifIFD0Directory;
import org.springframework.stereotype.Component;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
/**
* @author lsm
@@ -22,7 +26,8 @@ import java.io.IOException;
public class ImageUtil {
public byte[] compressImageToRequirements(byte[] imageData) throws IOException {
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageData));
// 读取图片并处理方向
BufferedImage image = readAndFixOrientation(imageData);
// 第一步调整分辨率不超过1000x1000
if (image.getWidth() > 1000 || image.getHeight() > 1000) {
@@ -91,6 +96,124 @@ public class ImageUtil {
return resizedImage;
}
/**
* 读取图片并处理 EXIF 方向信息
*/
private BufferedImage readAndFixOrientation(byte[] imageData) throws IOException {
try {
// 使用 metadata-extractor 读取 EXIF 方向信息
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
int orientation = 1; // 默认正常方向
if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
}
// 读取图片
ImageInputStream input = ImageIO.createImageInputStream(new ByteArrayInputStream(imageData));
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (!readers.hasNext()) {
throw new IOException("No ImageReader found for image data");
}
ImageReader reader = readers.next();
reader.setInput(input);
BufferedImage image = reader.read(0);
reader.dispose();
// 根据方向信息旋转图片
return rotateImageAccordingToOrientation(image, orientation);
} catch (ImageProcessingException e) {
throw new IOException("Failed to process image metadata", e);
} catch (MetadataException e) {
throw new RuntimeException(e);
}
}
/**
* 根据方向信息旋转图片
*/
private BufferedImage rotateImageAccordingToOrientation(BufferedImage image, int orientation) {
int width = image.getWidth();
int height = image.getHeight();
return switch (orientation) {
case 1 -> // 正常
image;
case 2 -> // 水平翻转
flipImage(image, true, false);
case 3 -> // 旋转180度
rotateImage(image, 180);
case 4 -> // 垂直翻转
flipImage(image, false, true);
case 5 -> {
image = flipImage(image, true, false);
yield rotateImage(image, 270);
}
case 6 -> // 旋转90度
rotateImage(image, 90);
case 7 -> {
image = flipImage(image, true, false);
yield rotateImage(image, 90);
}
case 8 -> // 旋转270度
rotateImage(image, 270);
default -> image;
};
}
/**
* 旋转图片
*/
private BufferedImage rotateImage(BufferedImage image, double degrees) {
double radians = Math.toRadians(degrees);
double sin = Math.abs(Math.sin(radians));
double cos = Math.abs(Math.cos(radians));
int width = image.getWidth();
int height = image.getHeight();
int newWidth = (int) Math.floor(width * cos + height * sin);
int newHeight = (int) Math.floor(height * cos + width * sin);
BufferedImage rotated = new BufferedImage(newWidth, newHeight, image.getType());
Graphics2D g = rotated.createGraphics();
g.translate((newWidth - width) / 2, (newHeight - height) / 2);
g.rotate(Math.toRadians(degrees), width / 2.0, height / 2.0);
g.drawRenderedImage(image, null);
g.dispose();
return rotated;
}
/**
* 翻转图片
*/
private BufferedImage flipImage(BufferedImage image, boolean horizontal, boolean vertical) {
int width = image.getWidth();
int height = image.getHeight();
BufferedImage flipped = new BufferedImage(width, height, image.getType());
Graphics2D g = flipped.createGraphics();
if (horizontal && vertical) {
g.drawImage(image, width, height, -width, -height, null);
} else if (horizontal) {
g.drawImage(image, width, 0, -width, height, null);
} else if (vertical) {
g.drawImage(image, 0, height, width, -height, null);
} else {
g.drawImage(image, 0, 0, null);
}
g.dispose();
return flipped;
}
private byte[] compressWithQuality(BufferedImage image, float quality) throws IOException {
// 获取JPEG编码器
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();