feat(printer): 优化拼图打印偏移处理逻辑

- 添加白边框并向上偏移内容以避免打印机偏移
- 替换原有的单纯向上偏移方法
- 弃用 shiftImageUp 方法,新增 addBorderAndShiftUp 方法
- 更新临时文件命名及清理逻辑
- 修改日志记录内容以反映新的处理方式
This commit is contained in:
2025-11-22 00:07:18 +08:00
parent 18bf51487d
commit 9278d4479f
3 changed files with 143 additions and 17 deletions

View File

@@ -471,16 +471,18 @@ public class FaceServiceImpl implements FaceService {
sfpContent.setTemplateCoverUrl(template.getCoverImage());
sfpContent.setGoodsType(3);
sfpContent.setSort(0);
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getScenicId(), face.getMemberId(), faceId, 5, records.getFirst().getTemplateId());
if (optionalRecord.isPresent()) {
IsBuyRespVO isBuyRespVO = orderBiz.isBuy(face.getScenicId(), face.getMemberId(), faceId, 5, optionalRecord.get().getTemplateId());
if (isBuyRespVO.isBuy()) {
sfpContent.setIsBuy(1);
} else {
sfpContent.setIsBuy(0);
}
}
PriceCalculationRequest calculationRequest = new PriceCalculationRequest();
ProductItem productItem = new ProductItem();
productItem.setProductType(ProductType.PHOTO_LOG);
productItem.setProductId(records.getFirst().getTemplateId().toString());
productItem.setProductId(template.getId().toString());
productItem.setPurchaseCount(1);
productItem.setScenicId(face.getScenicId().toString());
calculationRequest.setProducts(Collections.singletonList(productItem));

View File

@@ -864,19 +864,19 @@ public class PrinterServiceImpl implements PrinterService {
log.error("获取景区配置失败,使用原始照片进行打印。景区ID: {}, 照片ID: {}", item.getScenicId(), item.getId(), e);
}
} else if (item.getSourceId() != null && item.getSourceId() == 0) {
// 拼图:向上移动40像素以避免打印机偏移
// 拼图:添加白边框并向上偏移以避免打印机偏移
try {
// 生成唯一的处理标识符,避免多线程环境下的文件冲突
String processId = item.getId() + "_" + UUID.randomUUID().toString();
File originalFile = new File("puzzle_" + processId + ".png");
File shiftedFile = new File("puzzle_" + processId + "_shifted.png");
File processedFile = new File("puzzle_" + processId + "_processed.png");
try {
// 下载原图
HttpUtil.downloadFile(item.getCropUrl(), originalFile);
// 向上偏移40像素
ImageUtils.shiftImageUp(originalFile, shiftedFile, 40);
// 添加白边框(左右20px,上下30px)并向上偏移15px
ImageUtils.addBorderAndShiftUp(originalFile, processedFile, 20, 30, 15);
// 上传处理后的图片
IStorageAdapter adapter;
@@ -892,21 +892,21 @@ public class PrinterServiceImpl implements PrinterService {
adapter = StorageFactory.use("assets-ext");
}
String shiftedUrl = adapter.uploadFile(null, shiftedFile, StorageConstant.PHOTO_WATERMARKED_PATH, shiftedFile.getName());
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, shiftedFile.getName());
String processedUrl = adapter.uploadFile(null, processedFile, StorageConstant.PHOTO_WATERMARKED_PATH, processedFile.getName());
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, processedFile.getName());
printUrl = shiftedUrl;
log.info("拼图照片向上偏移40像素成功,照片ID: {}, 新URL: {}", item.getId(), shiftedUrl);
printUrl = processedUrl;
log.info("拼图照片添加白边框并向上偏移成功,照片ID: {}, 新URL: {}", item.getId(), processedUrl);
} catch (Exception e) {
log.error("拼图照片向上偏移处理失败,使用原始照片进行打印。照片ID: {}", item.getId(), e);
log.error("拼图照片处理失败,使用原始照片进行打印。照片ID: {}", item.getId(), e);
} finally {
// 清理临时文件
if (originalFile != null && originalFile.exists()) {
originalFile.delete();
}
if (shiftedFile != null && shiftedFile.exists()) {
shiftedFile.delete();
if (processedFile != null && processedFile.exists()) {
processedFile.delete();
}
}
} catch (Exception e) {

View File

@@ -448,6 +448,130 @@ public class ImageUtils {
return cropped;
}
/**
* 为图片添加白边框并向上偏移内容
* 用于拼图打印场景,避免打印机偏移问题
*
* @param sourceFile 源图片文件
* @param targetFile 目标图片文件
* @param horizontalBorder 左右白边框宽度(像素)
* @param verticalBorder 上下白边框高度(像素)
* @param upwardShift 内容向上偏移的像素数
* @throws IOException 读取或写入文件失败
*/
public static void addBorderAndShiftUp(File sourceFile, File targetFile,
int horizontalBorder, int verticalBorder, int upwardShift) throws IOException {
BufferedImage sourceImage = null;
BufferedImage resultImage = null;
try {
sourceImage = ImageIO.read(sourceFile);
if (sourceImage == null) {
throw new IOException("无法读取图片文件: " + sourceFile.getPath());
}
int srcWidth = sourceImage.getWidth();
int srcHeight = sourceImage.getHeight();
// 计算新图片尺寸(原图 + 左右边框 + 上下边框)
int newWidth = srcWidth + horizontalBorder * 2;
int newHeight = srcHeight + verticalBorder * 2;
// 创建新图片
resultImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = resultImage.createGraphics();
try {
// 填充白色背景
g2d.setColor(java.awt.Color.WHITE);
g2d.fillRect(0, 0, newWidth, newHeight);
// 绘制原图到新图中
// 原图应该绘制在: x=horizontalBorder, y=verticalBorder-upwardShift 的位置
// 这样图片内容会向上偏移upwardShift像素
int drawX = horizontalBorder;
int drawY = verticalBorder - upwardShift;
g2d.drawImage(sourceImage, drawX, drawY, null);
log.info("图片添加白边框并向上偏移: 原始尺寸={}x{}, 边框=(左右{}px,上下{}px), 向上偏移={}px, 结果尺寸={}x{}",
srcWidth, srcHeight, horizontalBorder, verticalBorder, upwardShift, newWidth, newHeight);
} finally {
g2d.dispose();
}
// 保存处理后的图片
ImageIO.write(resultImage, "png", targetFile);
} finally {
if (sourceImage != null) {
sourceImage.flush();
}
if (resultImage != null) {
resultImage.flush();
}
}
}
/**
* 向上偏移图片以避免打印机偏移问题
* 舍弃顶部指定像素,整体向上移动,并在底部补充白底
*
* @param sourceFile 源图片文件
* @param targetFile 目标图片文件
* @param offsetPixels 向上偏移的像素数(舍弃顶部的像素数,底部补充相同像素的白底)
* @throws IOException 读取或写入文件失败
* @deprecated 使用 addBorderAndShiftUp 代替
*/
@Deprecated
public static void shiftImageUp(File sourceFile, File targetFile, int offsetPixels) throws IOException {
BufferedImage sourceImage = null;
BufferedImage shiftedImage = null;
try {
sourceImage = ImageIO.read(sourceFile);
if (sourceImage == null) {
throw new IOException("无法读取图片文件: " + sourceFile.getPath());
}
int width = sourceImage.getWidth();
int height = sourceImage.getHeight();
if (offsetPixels <= 0 || offsetPixels >= height) {
throw new IllegalArgumentException("偏移像素必须大于0且小于图片高度,当前值: " + offsetPixels + ", 图片高度: " + height);
}
// 创建新图片,保持原始宽度和高度
shiftedImage = new BufferedImage(width, height, sourceImage.getType());
Graphics2D g2d = shiftedImage.createGraphics();
try {
// 先填充白色背景
g2d.setColor(java.awt.Color.WHITE);
g2d.fillRect(0, 0, width, height);
// 从源图的offsetPixels位置开始截取到底部,绘制到目标图的顶部
// 源图: 从(0, offsetPixels)到(width, height)的区域
// 目标图: 绘制到(0, 0)到(width, height-offsetPixels)的区域
g2d.drawImage(sourceImage, 0, 0, width, height - offsetPixels,
0, offsetPixels, width, height, null);
// 底部的offsetPixels像素保持白色(已通过fillRect填充)
} finally {
g2d.dispose();
}
// 保存处理后的图片
ImageIO.write(shiftedImage, "png", targetFile);
log.info("图片向上偏移成功,原始尺寸: {}x{}, 偏移: {}px, 结果尺寸: {}x{} (底部补充{}px白底)",
width, height, offsetPixels, width, height, offsetPixels);
} finally {
if (sourceImage != null) {
sourceImage.flush();
}
if (shiftedImage != null) {
shiftedImage.flush();
}
}
}
/**
* 裁切策略内部类
*/