|
@@ -1,5 +1,12 @@
|
|
package org.springblade.business.utils;
|
|
package org.springblade.business.utils;
|
|
|
|
|
|
|
|
+import com.drew.imaging.ImageMetadataReader;
|
|
|
|
+import com.drew.imaging.ImageProcessingException;
|
|
|
|
+import com.drew.metadata.Directory;
|
|
|
|
+import com.drew.metadata.Metadata;
|
|
|
|
+import com.drew.metadata.MetadataException;
|
|
|
|
+import com.drew.metadata.exif.ExifIFD0Directory;
|
|
|
|
+import com.drew.metadata.exif.ExifSubIFDDirectory;
|
|
import com.itextpdf.text.Document;
|
|
import com.itextpdf.text.Document;
|
|
import com.itextpdf.text.pdf.PdfCopy;
|
|
import com.itextpdf.text.pdf.PdfCopy;
|
|
import com.itextpdf.text.pdf.PdfReader;
|
|
import com.itextpdf.text.pdf.PdfReader;
|
|
@@ -11,14 +18,21 @@ import org.springblade.common.utils.CommonUtil;
|
|
import org.springblade.common.vo.DataVO;
|
|
import org.springblade.common.vo.DataVO;
|
|
import org.springblade.core.tool.utils.IoUtil;
|
|
import org.springblade.core.tool.utils.IoUtil;
|
|
|
|
|
|
|
|
+import javax.imageio.IIOImage;
|
|
import javax.imageio.ImageIO;
|
|
import javax.imageio.ImageIO;
|
|
|
|
+import javax.imageio.ImageWriteParam;
|
|
|
|
+import javax.imageio.ImageWriter;
|
|
|
|
+import javax.imageio.stream.ImageOutputStream;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import java.awt.*;
|
|
import java.awt.*;
|
|
import java.awt.Color;
|
|
import java.awt.Color;
|
|
|
|
+import java.awt.geom.AffineTransform;
|
|
|
|
+import java.awt.image.AffineTransformOp;
|
|
import java.awt.image.BufferedImage;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.*;
|
|
import java.io.*;
|
|
import java.net.URLEncoder;
|
|
import java.net.URLEncoder;
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
|
+import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Matcher;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipEntry;
|
|
@@ -100,21 +114,89 @@ public class FileUtils {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 压缩图片
|
|
|
|
|
|
+ * 图片缩放、压缩、旋转处理
|
|
|
|
+ * @param imageData
|
|
|
|
+ * @return
|
|
|
|
+ * @throws IOException
|
|
|
|
+ * @throws ImageProcessingException
|
|
|
|
+ * @throws MetadataException
|
|
*/
|
|
*/
|
|
- public static byte[] resizeImage(byte[] srcImgData, float reduceMultiple) throws IOException {
|
|
|
|
- BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
|
|
|
|
- int width = (int) (bi.getWidth() * reduceMultiple);
|
|
|
|
- int height = (int) (bi.getHeight() * reduceMultiple);
|
|
|
|
- Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
|
|
|
|
- BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
|
|
|
- Graphics g = tag.getGraphics();
|
|
|
|
- g.setColor(Color.RED);
|
|
|
|
- g.drawImage(image, 0, 0, null);
|
|
|
|
- g.dispose();
|
|
|
|
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
|
|
|
- ImageIO.write(tag, "JPEG", bOut);
|
|
|
|
- return bOut.toByteArray();
|
|
|
|
|
|
+ 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();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -126,7 +208,7 @@ public class FileUtils {
|
|
*/
|
|
*/
|
|
public static void imageOrientation(Sheet sheet, ClientAnchor anchor, DataVO dataVO) {
|
|
public static void imageOrientation(Sheet sheet, ClientAnchor anchor, DataVO dataVO) {
|
|
// 设置图片距左边和上边的偏移量
|
|
// 设置图片距左边和上边的偏移量
|
|
- anchor.setDx1(Units.pixelToEMU(5));
|
|
|
|
|
|
+ anchor.setDx1(Units.pixelToEMU(-90));
|
|
anchor.setDy1(Units.pixelToEMU(5));
|
|
anchor.setDy1(Units.pixelToEMU(5));
|
|
// 设置图片右下角所在单元格的行列号与左上角一致
|
|
// 设置图片右下角所在单元格的行列号与左上角一致
|
|
anchor.setCol2(anchor.getCol1());
|
|
anchor.setCol2(anchor.getCol1());
|
|
@@ -146,6 +228,9 @@ public class FileUtils {
|
|
int dy = Units.pointsToPixel(sheet.getRow(anchor.getRow2()).getHeightInPoints()) - 5;
|
|
int dy = Units.pointsToPixel(sheet.getRow(anchor.getRow2()).getHeightInPoints()) - 5;
|
|
anchor.setDx2(Units.pixelToEMU(dx));
|
|
anchor.setDx2(Units.pixelToEMU(dx));
|
|
anchor.setDy2(Units.pixelToEMU(dy));
|
|
anchor.setDy2(Units.pixelToEMU(dy));
|
|
|
|
+
|
|
|
|
+ // 禁止旋转
|
|
|
|
+ anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|