|
@@ -1,21 +1,35 @@
|
|
|
package org.springblade.common.utils;
|
|
|
|
|
|
import cn.hutool.core.io.FileUtil;
|
|
|
+import com.drew.imaging.ImageMetadataReader;
|
|
|
+import com.drew.imaging.ImageProcessingException;
|
|
|
+import com.drew.metadata.Metadata;
|
|
|
+import com.drew.metadata.exif.ExifIFD0Directory;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
+import javax.imageio.IIOImage;
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+import javax.imageio.ImageWriteParam;
|
|
|
+import javax.imageio.ImageWriter;
|
|
|
+import java.awt.*;
|
|
|
+import java.awt.geom.AffineTransform;
|
|
|
+import java.awt.image.AffineTransformOp;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
import java.io.*;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.net.HttpURLConnection;
|
|
|
import java.net.URL;
|
|
|
import java.net.URLConnection;
|
|
|
import java.util.*;
|
|
|
+import java.util.List;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.util.stream.Stream;
|
|
|
import java.util.zip.ZipEntry;
|
|
|
import java.util.zip.ZipOutputStream;
|
|
|
+import com.drew.metadata.MetadataException;
|
|
|
|
|
|
/**
|
|
|
* 通用工具类
|
|
@@ -322,4 +336,92 @@ public class CommonUtil {
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 图片缩放、压缩、旋转处理
|
|
|
+ * @param imageData
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ * @throws ImageProcessingException
|
|
|
+ * @throws MetadataException
|
|
|
+ */
|
|
|
+ public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException {
|
|
|
+ // 读取原始图像(处理旋转问题)
|
|
|
+ Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
|
|
|
+ if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
|
|
|
+ ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
|
|
|
+ if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
|
|
|
+ // 获取 Orientation 标签的值
|
|
|
+ int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
|
|
|
+ // 需要旋转图片
|
|
|
+ BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
|
|
|
+ AffineTransform transform = new AffineTransform();
|
|
|
+ if (orientation == 6) {
|
|
|
+ transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
|
|
|
+ } else if (orientation == 8) {
|
|
|
+ transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
|
|
|
+ }
|
|
|
+ AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
|
|
|
+ originalImage = op.filter(originalImage, null);
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
+ ImageIO.write(originalImage, "jpg", baos);
|
|
|
+ imageData = baos.toByteArray();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 缩放图像
|
|
|
+ String formatName = "JPEG";
|
|
|
+ ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
|
|
|
+ BufferedImage originalImage = ImageIO.read(bais);
|
|
|
+ long sizeLimit = 366912; //358KB
|
|
|
+ int width = 768;
|
|
|
+ int height = 1024;
|
|
|
+ Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
|
|
|
+ BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
|
|
+ resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
|
|
|
+
|
|
|
+ // 压缩图像
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
+ ImageIO.write(resizedImage, formatName, baos);
|
|
|
+
|
|
|
+ if (baos.size() <= sizeLimit) {
|
|
|
+ // 图片大小已经小于等于目标大小,直接返回原始数据
|
|
|
+ return baos.toByteArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ float quality = 0.9f; // 初始化压缩质量
|
|
|
+ int retries = 10; // 最多尝试 10 次
|
|
|
+
|
|
|
+ while (baos.size() > sizeLimit && retries > 0) {
|
|
|
+ // 压缩图像并重新计算压缩质量
|
|
|
+ byte[] data = baos.toByteArray();
|
|
|
+ bais = new ByteArrayInputStream(data);
|
|
|
+ BufferedImage compressedImage = ImageIO.read(bais);
|
|
|
+ baos.reset();
|
|
|
+
|
|
|
+ ImageWriter writer = null;
|
|
|
+ Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
|
|
|
+ if (writers.hasNext()) {
|
|
|
+ writer = writers.next();
|
|
|
+ } else {
|
|
|
+ throw new IllegalArgumentException("Unsupported image format: " + formatName);
|
|
|
+ }
|
|
|
+
|
|
|
+ ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
|
|
+ writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
|
|
+ writeParam.setCompressionQuality(quality);
|
|
|
+
|
|
|
+ writer.setOutput(ImageIO.createImageOutputStream(baos));
|
|
|
+ writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
|
|
|
+ writer.dispose();
|
|
|
+
|
|
|
+ float ratio = sizeLimit * 1.0f / baos.size();
|
|
|
+ quality *= Math.sqrt(ratio);
|
|
|
+ retries--;
|
|
|
+ }
|
|
|
+
|
|
|
+ return baos.toByteArray();
|
|
|
+ }
|
|
|
+
|
|
|
}
|