package com.klp.utils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Base64; /** * 图片处理工具类 * * @author klp * @date 2025-01-27 */ @Slf4j @Component public class ImageProcessingUtils { /** * 将图片URL转换为Base64 Data URI * * @param imageUrl 图片URL * @param maxDimension 最大尺寸 * @param quality 图片质量 * @return Base64 Data URI */ public String imageUrlToDataUri(String imageUrl, int maxDimension, int quality) { try { // 下载图片 BufferedImage originalImage = downloadImage(imageUrl); if (originalImage == null) { throw new RuntimeException("无法下载图片: " + imageUrl); } // 调整图片尺寸 BufferedImage resizedImage = resizeImage(originalImage, maxDimension); // 转换为Base64 String base64 = imageToBase64(resizedImage, quality); return "data:image/jpeg;base64," + base64; } catch (Exception e) { log.error("图片转换失败: {}", e.getMessage(), e); throw new RuntimeException("图片转换失败: " + e.getMessage()); } } /** * 下载图片 * * @param imageUrl 图片URL * @return BufferedImage对象 */ private BufferedImage downloadImage(String imageUrl) { try { URL url = new URL(imageUrl); try (InputStream inputStream = url.openStream()) { return ImageIO.read(inputStream); } } catch (IOException e) { log.error("下载图片失败: {}", e.getMessage(), e); return null; } } /** * 调整图片尺寸 * * @param originalImage 原始图片 * @param maxDimension 最大尺寸 * @return 调整后的图片 */ private BufferedImage resizeImage(BufferedImage originalImage, int maxDimension) { int originalWidth = originalImage.getWidth(); int originalHeight = originalImage.getHeight(); // 计算新的尺寸 int newWidth, newHeight; if (originalWidth > originalHeight) { newWidth = Math.min(originalWidth, maxDimension); newHeight = (int) ((double) originalHeight * newWidth / originalWidth); } else { newHeight = Math.min(originalHeight, maxDimension); newWidth = (int) ((double) originalWidth * newHeight / originalHeight); } // 创建新图片 BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = resizedImage.createGraphics(); // 设置渲染质量 g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 绘制调整后的图片 g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null); g2d.dispose(); return resizedImage; } /** * 将图片转换为Base64字符串 * * @param image 图片对象 * @param quality 图片质量 * @return Base64字符串 */ private String imageToBase64(BufferedImage image, int quality) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // 使用JPEG格式输出 ImageIO.write(image, "JPEG", baos); byte[] imageBytes = baos.toByteArray(); return Base64.getEncoder().encodeToString(imageBytes); } catch (IOException e) { log.error("图片转Base64失败: {}", e.getMessage(), e); throw new RuntimeException("图片转Base64失败: " + e.getMessage()); } } /** * 验证图片URL是否有效 * * @param imageUrl 图片URL * @return 是否有效 */ public boolean isValidImageUrl(String imageUrl) { try { URL url = new URL(imageUrl); String protocol = url.getProtocol(); return "http".equals(protocol) || "https".equals(protocol); } catch (Exception e) { log.warn("无效的图片URL: {}", imageUrl); return false; } } }