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日 留念");