From 1eb527574ba07fc2c0d4654a38ac6a1cccd7cd82 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 22 Jul 2025 00:18:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E5=AD=97=E6=A0=B9=E6=8D=AE=E8=87=AA?= =?UTF-8?q?=E7=94=9F=E5=81=8F=E7=A7=BB=E9=87=8F=E5=AE=9A=E4=BD=8D=EF=BC=8C?= =?UTF-8?q?=E7=A1=AE=E4=BF=9D=E5=B1=85=E4=B8=AD=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../operator/LeicaWatermarkOperator.java | 23 ++++++++++++++++--- .../operator/NormalWatermarkOperator.java | 16 +++++++++++-- .../operator/WatermarkOperatorTest.java | 2 +- 3 files changed, 35 insertions(+), 6 deletions(-) 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 8118c55..402ad7c 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 @@ -107,13 +107,30 @@ public class LeicaWatermarkOperator implements IOperator { int dtLineHeight = datetimeFontMetrics.getHeight(); int scenicLineWidth = scenicFontMetrics.stringWidth(info.getScenicLine()); int datetimeLineWidth = scenicFontMetrics.stringWidth(info.getDatetimeLine()); - g2d.drawImage(qrcodeImage, newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - newQrcodeWidth - QRCODE_OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), EXTRA_BORDER_PX + baseImage.getHeight() + OFFSET_Y - QRCODE_OFFSET_Y, newQrcodeWidth, newQrcodeHeight, null); + // 计算二维码的位置 + int qrcodeX = newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - newQrcodeWidth - QRCODE_OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth); + int qrcodeY = EXTRA_BORDER_PX + baseImage.getHeight() + OFFSET_Y - QRCODE_OFFSET_Y; + + g2d.drawImage(qrcodeImage, qrcodeX, qrcodeY, newQrcodeWidth, newQrcodeHeight, null); + + // 计算文字与二维码垂直居中对齐的Y坐标 + int qrcodeTop = qrcodeY; + int qrcodeBottom = qrcodeTop + newQrcodeHeight; + int qrcodeCenter = (qrcodeTop + qrcodeBottom) / 2; + + // 两行文字的总高度 + int totalTextHeight = scenicLineHeight + dtLineHeight; + + // 计算第一行文字的Y坐标(基线位置),使两行文字整体垂直居中于二维码 + int textStartY = qrcodeCenter - totalTextHeight / 2 + scenicFontMetrics.getAscent(); + g2d.setFont(scenicFont); g2d.setColor(scenicColor); - g2d.drawString(info.getScenicLine(), newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), EXTRA_BORDER_PX + baseImage.getHeight() + OFFSET_Y + scenicLineHeight + scenicLineHeight * FONT_GLOBAL_OFFSET_PERCENT); + g2d.drawString(info.getScenicLine(), newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), textStartY); + 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); + g2d.drawString(info.getDatetimeLine(), newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), textStartY + scenicLineHeight); String fileName = info.getWatermarkedFile().getName(); String formatName = "jpg"; // 默认格式为 jpg if (fileName.endsWith(".png")) { 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 1c295f6..026eb85 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 @@ -89,12 +89,24 @@ public class NormalWatermarkOperator implements IOperator { g2d.setClip(circle); g2d.drawImage(qrcodeImage, offsetX, offsetY + QRCODE_OFFSET_Y, newQrcodeWidth, newQrcodeHeight, null); g2d.setClip(originalClip); + // 计算文字与二维码垂直居中对齐的Y坐标 + int qrcodeTop = offsetY + QRCODE_OFFSET_Y; + int qrcodeBottom = qrcodeTop + newQrcodeHeight; + int qrcodeCenter = (qrcodeTop + qrcodeBottom) / 2; + + // 两行文字的总高度 + int totalTextHeight = scenicLineHeight + dtLineHeight; + + // 计算第一行文字的Y坐标(基线位置),使两行文字整体垂直居中于二维码 + int textStartY = qrcodeCenter - totalTextHeight / 2 + scenicFontMetrics.getAscent(); + g2d.setFont(scenicFont); g2d.setColor(scenicColor); - g2d.drawString(info.getScenicLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, offsetY + scenicLineHeight + FONT_GLOBAL_OFFSET_PERCENT * scenicLineHeight); + g2d.drawString(info.getScenicLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, textStartY); + g2d.setFont(datetimeFont); g2d.setColor(datetimeColor); - g2d.drawString(info.getDatetimeLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, offsetY + scenicLineHeight + dtLineHeight + FONT_GLOBAL_OFFSET_PERCENT * dtLineHeight); + g2d.drawString(info.getDatetimeLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, textStartY + scenicLineHeight); String fileName = info.getWatermarkedFile().getName(); String formatName = "jpg"; // 默认格式为 jpg if (fileName.endsWith(".png")) { diff --git a/src/test/java/com/ycwl/basic/image/watermark/operator/WatermarkOperatorTest.java b/src/test/java/com/ycwl/basic/image/watermark/operator/WatermarkOperatorTest.java index 32d1e1a..19c1237 100644 --- a/src/test/java/com/ycwl/basic/image/watermark/operator/WatermarkOperatorTest.java +++ b/src/test/java/com/ycwl/basic/image/watermark/operator/WatermarkOperatorTest.java @@ -16,7 +16,7 @@ public class WatermarkOperatorTest { @Test public void testProcess() throws Exception { WatermarkInfo info = new WatermarkInfo(); - info.setOriginalFile(new File("e2d32de7-6e85-4e07-b42f-477347073539.jpg")); + info.setOriginalFile(new File("38e1285c-84d0-464a-810d-053e9502e257.jpg")); info.setQrcodeFile(new File("cxzh_t.jpg")); info.setScenicLine("川西竹海一日游!"); info.setDatetimeLine("2XXX年XX月XX日 留念");