package com.ydtech.utils; import com.ydtech.exception.SystemException; import lombok.extern.slf4j.Slf4j; import net.coobird.thumbnailator.Thumbnails; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.nio.file.Files; /** * @author wenks * @version 0.0.2 * @description 文件压缩工具类 * @date 2023/4/11 10:27 */ @Slf4j public class ImageCompressionUtils { private ImageCompressionUtils() { throw new IllegalStateException("Utility class"); } private static final Integer ZERO = 0; private static final Integer ONE_ZERO_TWO_FOUR = 1024; private static final Integer NINE_ZERO_ZERO = 900; private static final Integer THREE_TWO_SEVEN_FIVE = 3275; private static final Integer TWO_ZERO_FOUR_SEVEN = 2047; private static final Double ZERO_EIGHT_FIVE = 0.85; private static final Double ZERO_SIX = 0.6; private static final Double ZERO_FOUR_FOUR = 0.44; private static final Double ZERO_FOUR = 0.4; /** * 压缩大小不变 * * @param inputStream 输入流 * @param suffix 文件后缀名 * @param path 路劲 * @return 字节 */ public static byte[] compressPic(InputStream inputStream, String suffix, String path) throws IOException { File temp = File.createTempFile("temp", suffix, new File(path)); try (FileOutputStream os = new FileOutputStream(temp);) { BufferedImage image = ImageIO.read(inputStream); int width = image.getWidth(); int height = image.getHeight(); BufferedImage bfImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); bfImage.getGraphics().drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); ImageIO.write(bfImage, suffix.replace(".", ""), os); } catch (IOException e) { e.printStackTrace(); } byte[] bytesByFile = getBytesByFile(temp); Files.delete(temp.getAbsoluteFile().toPath()); return bytesByFile; } /** * 文件转字节 * * @param file 文件 * @return 字节 */ public static byte[] getBytesByFile(File file) { try (FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream bos = new ByteArrayOutputStream(1000)) { byte[] b = new byte[1000]; int n; while ((n = fis.read(b)) != -1) { bos.write(b, 0, n); } return bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return new byte[0]; } /** * 根据指定大小压缩图片 * * @param imageBytes 源图片字节数组 * @param desFileSize 指定图片大小,单位kb * @return 压缩质量后的图片字节数组 */ public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) { if (imageBytes == null || imageBytes.length <= ZERO || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) { return imageBytes; } long srcSize = imageBytes.length; double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR); try { while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) { ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length); Thumbnails.of(inputStream) .scale(accuracy) .outputQuality(accuracy) .toOutputStream(outputStream); imageBytes = outputStream.toByteArray(); } log.info("图片原大小={}kb | 压缩后大小={}kb", srcSize / ONE_ZERO_TWO_FOUR, imageBytes.length / ONE_ZERO_TWO_FOUR); } catch (Exception e) { log.error("【图片压缩】msg=图片压缩失败!", e); throw new SystemException(e.toString()); } return imageBytes; } /** * 自动调节精度(经验数值) * * @param size 源图片大小 * @return 图片压缩质量比 */ private static double getAccuracy(long size) { double accuracy; if (size < NINE_ZERO_ZERO) { accuracy = ZERO_EIGHT_FIVE; } else if (size < TWO_ZERO_FOUR_SEVEN) { accuracy = ZERO_SIX; } else if (size < THREE_TWO_SEVEN_FIVE) { accuracy = ZERO_FOUR_FOUR; } else { accuracy = ZERO_FOUR; } return accuracy; } }