diff --git a/src/main/java/com/ycwl/basic/image/watermark/enums/ImageWatermarkOperatorEnum.java b/src/main/java/com/ycwl/basic/image/watermark/enums/ImageWatermarkOperatorEnum.java index eea6983..7759356 100644 --- a/src/main/java/com/ycwl/basic/image/watermark/enums/ImageWatermarkOperatorEnum.java +++ b/src/main/java/com/ycwl/basic/image/watermark/enums/ImageWatermarkOperatorEnum.java @@ -4,14 +4,16 @@ import lombok.Getter; @Getter public enum ImageWatermarkOperatorEnum { - WATERMARK("defW"), - LEICA("leica"), - NORMAL("normal"); + WATERMARK("defW", "jpg"), + LEICA("leica", "png"), + NORMAL("normal", "png"); private final String type; + private final String preferFileType; - ImageWatermarkOperatorEnum(String type) { + ImageWatermarkOperatorEnum(String type, String preferFileType) { this.type = type; + this.preferFileType = preferFileType; } public static ImageWatermarkOperatorEnum getByCode(String type) { diff --git a/src/main/java/com/ycwl/basic/image/watermark/operator/DefaultImageWatermarkOperator.java b/src/main/java/com/ycwl/basic/image/watermark/operator/DefaultImageWatermarkOperator.java index 3a1e3a6..8d1e807 100644 --- a/src/main/java/com/ycwl/basic/image/watermark/operator/DefaultImageWatermarkOperator.java +++ b/src/main/java/com/ycwl/basic/image/watermark/operator/DefaultImageWatermarkOperator.java @@ -5,6 +5,9 @@ import com.ycwl.basic.image.watermark.exception.ImageWatermarkException; import lombok.extern.slf4j.Slf4j; import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -34,12 +37,39 @@ public class DefaultImageWatermarkOperator implements IOperator { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); g2d.drawImage(watermarkImage, 0, 0, baseImage.getWidth(), baseImage.getHeight(), null); + String fileName = info.getWatermarkedFile().getName(); + String formatName = "jpg"; // 默认格式为 jpg + if (fileName.endsWith(".png")) { + formatName = "png"; + } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) { + formatName = "jpg"; + } + ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next(); + ImageOutputStream ios; try { - ImageIO.write(newImage, "jpg", info.getWatermarkedFile()); + ios = ImageIO.createImageOutputStream(info.getWatermarkedFile()); + } catch (IOException e) { + throw new ImageWatermarkException("图片保存失败,目标文件无法写入"); + } + writer.setOutput(ios); + try { + // 使用 ImageWriter 设置写入质量 + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + if (writeParam.canWriteCompressed()) { + writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + writeParam.setCompressionQuality(0.8f); // 设置写入质量为 80% + } + writer.write(null, new javax.imageio.IIOImage(newImage, null, null), writeParam); } catch (IOException e) { throw new ImageWatermarkException("图片保存失败"); - } finally { + } + finally { g2d.dispose(); + try { + ios.close(); + } catch (IOException ignore) { + } + writer.dispose(); } return info.getWatermarkedFile(); } diff --git a/src/main/java/com/ycwl/basic/image/watermark/operator/LeicaWatermarkOperator.java b/src/main/java/com/ycwl/basic/image/watermark/operator/LeicaWatermarkOperator.java index 869d345..3857bed 100644 --- a/src/main/java/com/ycwl/basic/image/watermark/operator/LeicaWatermarkOperator.java +++ b/src/main/java/com/ycwl/basic/image/watermark/operator/LeicaWatermarkOperator.java @@ -5,6 +5,9 @@ import com.ycwl.basic.image.watermark.exception.ImageWatermarkException; import lombok.extern.slf4j.Slf4j; import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -110,12 +113,39 @@ public class LeicaWatermarkOperator implements IOperator { g2d.setFont(datetimeFont); g2d.setColor(datetimeColor); g2d.drawString(info.getDatetimeLine(), newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), EXTRA_BORDER_PX + baseImage.getHeight() + + OFFSET_Y + scenicLineHeight + dtLineHeight + dtLineHeight * FONT_GLOBAL_OFFSET_PERCENT); + String fileName = info.getWatermarkedFile().getName(); + String formatName = "jpg"; // 默认格式为 jpg + if (fileName.endsWith(".png")) { + formatName = "png"; + } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) { + formatName = "jpg"; + } + ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next(); + ImageOutputStream ios; try { - ImageIO.write(newImage, "png", info.getWatermarkedFile()); + ios = ImageIO.createImageOutputStream(info.getWatermarkedFile()); + } catch (IOException e) { + throw new ImageWatermarkException("图片保存失败,目标文件无法写入"); + } + writer.setOutput(ios); + try { + // 使用 ImageWriter 设置写入质量 + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + if (writeParam.canWriteCompressed()) { + writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + writeParam.setCompressionQuality(0.95f); // 设置写入质量为 95% + } + writer.write(null, new javax.imageio.IIOImage(newImage, null, null), writeParam); } catch (IOException e) { throw new ImageWatermarkException("图片保存失败"); - } finally { + } + finally { g2d.dispose(); + try { + ios.close(); + } catch (IOException ignore) { + } + writer.dispose(); } return info.getWatermarkedFile(); } diff --git a/src/main/java/com/ycwl/basic/image/watermark/operator/NormalWatermarkOperator.java b/src/main/java/com/ycwl/basic/image/watermark/operator/NormalWatermarkOperator.java index 36bdf85..ca4bc71 100644 --- a/src/main/java/com/ycwl/basic/image/watermark/operator/NormalWatermarkOperator.java +++ b/src/main/java/com/ycwl/basic/image/watermark/operator/NormalWatermarkOperator.java @@ -5,6 +5,9 @@ import com.ycwl.basic.image.watermark.exception.ImageWatermarkException; import lombok.extern.slf4j.Slf4j; import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -86,12 +89,39 @@ public class NormalWatermarkOperator implements IOperator { g2d.setFont(datetimeFont); g2d.setColor(datetimeColor); g2d.drawString(info.getDatetimeLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, offsetY + scenicLineHeight + dtLineHeight + FONT_GLOBAL_OFFSET_PERCENT * dtLineHeight); + String fileName = info.getWatermarkedFile().getName(); + String formatName = "jpg"; // 默认格式为 jpg + if (fileName.endsWith(".png")) { + formatName = "png"; + } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) { + formatName = "jpg"; + } + ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next(); + ImageOutputStream ios; try { - ImageIO.write(newImage, "png", info.getWatermarkedFile()); + ios = ImageIO.createImageOutputStream(info.getWatermarkedFile()); + } catch (IOException e) { + throw new ImageWatermarkException("图片保存失败,目标文件无法写入"); + } + writer.setOutput(ios); + try { + // 使用 ImageWriter 设置写入质量 + ImageWriteParam writeParam = writer.getDefaultWriteParam(); + if (writeParam.canWriteCompressed()) { + writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + writeParam.setCompressionQuality(0.95f); // 设置写入质量为 95% + } + writer.write(null, new javax.imageio.IIOImage(newImage, null, null), writeParam); } catch (IOException e) { throw new ImageWatermarkException("图片保存失败"); - } finally { + } + finally { g2d.dispose(); + try { + ios.close(); + } catch (IOException ignore) { + } + writer.dispose(); } return info.getWatermarkedFile(); } diff --git a/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java b/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java index 1d9f6a3..63101f6 100644 --- a/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/impl/mobile/GoodsServiceImpl.java @@ -505,7 +505,7 @@ public class GoodsServiceImpl implements GoodsService { } else { // 生成 File dstFile = new File(item.getGoodsId() + ".jpg"); - File watermarkedFile = new File(item.getGoodsId() + "_" + ImageWatermarkOperatorEnum.WATERMARK.getType() + ".png"); + File watermarkedFile = new File(item.getGoodsId() + "_" + ImageWatermarkOperatorEnum.WATERMARK.getType() + "." + ImageWatermarkOperatorEnum.WATERMARK.getPreferFileType()); try { HttpUtil.downloadFile(item.getUrl().replace("oss.zhentuai.com", "frametour-assets.oss-cn-shanghai-internal.aliyuncs.com"), dstFile); } catch (Exception e) { @@ -613,7 +613,7 @@ public class GoodsServiceImpl implements GoodsService { } else { // 生成 File dstFile = new File(item.getGoodsId() + ".jpg"); - File watermarkedFile = new File(item.getGoodsId() + "_" + type.getType() + ".png"); + File watermarkedFile = new File(item.getGoodsId() + "_" + type.getType() + "." + type.getPreferFileType()); try { HttpUtil.downloadFile(item.getUrl().replace("oss.zhentuai.com", "frametour-assets.oss-cn-shanghai-internal.aliyuncs.com"), dstFile); } catch (Exception e) {