Sfoglia il codice sorgente

fix(image): 优化图片缩放处理逻辑

- 根据原图是否包含alpha通道选择合适的BufferedImage类型
- 添加渲染提示提高图片质量
- 实现RGB模式下透明区域的白色背景填充
- 完善图片格式识别和转换逻辑
- 添加JPEG格式的压缩参数配置
- 修复PhysicalPlayerItemActivation类多余的空行问题
fugui001 6 giorni fa
parent
commit
7e333d2b68

+ 70 - 12
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/service/impl/TournamentsServiceImpl.java

@@ -781,26 +781,51 @@ public class TournamentsServiceImpl implements ITournamentsService {
             height = (int) (height * scale);
         }
 
-        // ✅ 修复:使用 TYPE_INT_ARGB 支持透明通道
-        BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
-        Graphics2D g2d = scaledImage.createGraphics();
+        // 根据原图是否包含alpha通道选择合适的BufferedImage类型
+        BufferedImage scaledImage;
+        if (originalImage.getColorModel().hasAlpha()) {
+            // 如果原图有透明通道,使用ARGB
+            scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        } else {
+            // 如果原图无透明通道,使用RGB避免颜色空间问题
+            scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        }
 
-        // ✅ 修复:设置背景为白色(可选,根据需求)
-        g2d.setColor(Color.WHITE);
-        g2d.fillRect(0, 0, width, height);
+        Graphics2D g2d = scaledImage.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);
+
+        // 如果是RGB模式且原图有透明区域,绘制白色背景
+        if (scaledImage.getType() == BufferedImage.TYPE_INT_RGB) {
+            g2d.setColor(Color.WHITE);
+            g2d.fillRect(0, 0, width, height);
+        }
+
         g2d.drawImage(originalImage, 0, 0, width, height, null);
         g2d.dispose();
 
         // 转换为字节数组
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
-        // ✅ 修复:如果是PNG格式且原图有透明通道,保持PNG格式
-        String formatName = "jpg";
-        if (originalFile.getContentType() != null &&
-            originalFile.getContentType().contains("png")) {
-            formatName = "png";
+        // 根据原文件类型确定输出格式
+        String formatName = getFormatName(originalFile);
+
+        // 如果输出JPEG格式,确保使用RGB模式
+        if ("jpg".equalsIgnoreCase(formatName) || "jpeg".equalsIgnoreCase(formatName)) {
+            if (scaledImage.getType() != BufferedImage.TYPE_INT_RGB) {
+                // 创建新的RGB图像
+                BufferedImage rgbImage = new BufferedImage(scaledImage.getWidth(),
+                    scaledImage.getHeight(), BufferedImage.TYPE_INT_RGB);
+                Graphics2D rgbG2d = rgbImage.createGraphics();
+                rgbG2d.setColor(Color.WHITE);
+                rgbG2d.fillRect(0, 0, scaledImage.getWidth(), scaledImage.getHeight());
+                rgbG2d.drawImage(scaledImage, 0, 0, null);
+                rgbG2d.dispose();
+                scaledImage = rgbImage;
+            }
         }
 
         ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next();
@@ -808,7 +833,7 @@ public class TournamentsServiceImpl implements ITournamentsService {
         writer.setOutput(ios);
 
         ImageWriteParam param = writer.getDefaultWriteParam();
-        if (param.canWriteCompressed() && "jpg".equals(formatName)) {
+        if (param.canWriteCompressed() && ("jpg".equalsIgnoreCase(formatName) || "jpeg".equalsIgnoreCase(formatName))) {
             param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
             param.setCompressionQuality(0.7f);
         }
@@ -820,6 +845,39 @@ public class TournamentsServiceImpl implements ITournamentsService {
         return baos.toByteArray();
     }
 
+    /**
+     * 获取正确的图片格式名称
+     */
+    private String getFormatName(MultipartFile originalFile) {
+        String fileName = originalFile.getOriginalFilename();
+        if (fileName != null) {
+            String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
+            if ("jpg".equals(extension) || "jpeg".equals(extension)) {
+                return "jpg";
+            } else if ("png".equals(extension)) {
+                return "png";
+            } else if ("gif".equals(extension)) {
+                return "gif";
+            }
+        }
+
+        // 如果无法从文件名确定格式,根据content type判断
+        String contentType = originalFile.getContentType();
+        if (contentType != null) {
+            if (contentType.contains("jpeg") || contentType.contains("jpg")) {
+                return "jpg";
+            } else if (contentType.contains("png")) {
+                return "png";
+            } else if (contentType.contains("gif")) {
+                return "gif";
+            }
+        }
+
+        // 默认返回jpg
+        return "jpg";
+    }
+
+
     @Override
     public Boolean deleteTournament(Long id) {
         TournamentsVo tournamentsVo = baseMapper.selectVoByIdInfo(id);

+ 2 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/PhysicalPlayerItemActivation.java

@@ -92,4 +92,6 @@ public class PhysicalPlayerItemActivation extends BaseEntity {
      *  业务类型  user_split 用户拆包   web_action 后台激活
      */
     private String businessType;
+
+
 }