feat(image): 实现源图片超分辨率增强流水线

- 引入Pipeline模式重构图片处理流程
- 新增SourcePhotoUpdateStage用于上传并更新源图片URL
- 扩展PhotoProcessContext支持超分场景配置
- 增加SOURCE_PHOTO_SUPER_RESOLUTION枚举值
- 修改各Stage判断逻辑适配新的图片类型系统
- 调整SourceService接口支持File类型参数
- 优化超分处理日志记录和异常处理机制
This commit is contained in:
2025-11-25 19:17:55 +08:00
parent bcebe5defe
commit 7b18d7c2af
17 changed files with 491 additions and 60 deletions

View File

@@ -6,6 +6,7 @@ import com.ycwl.basic.model.pc.source.req.SourceReqQuery;
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.utils.ApiResponse;
import java.io.File;
import java.util.List;
/**
@@ -21,5 +22,5 @@ public interface SourceService {
ApiResponse<Integer> update(SourceEntity source);
ApiResponse cutVideo(Long id);
String uploadAndUpdateUrl(Long id, org.springframework.web.multipart.MultipartFile file);
String uploadAndUpdateUrl(Long id, File file);
}

View File

@@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.ycwl.basic.storage.StorageFactory;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
@@ -216,14 +217,14 @@ public class SourceServiceImpl implements SourceService {
}
@Override
public String uploadAndUpdateUrl(Long id, MultipartFile file) {
public String uploadAndUpdateUrl(Long id, File file) {
SourceRespVO source = sourceMapper.getById(id);
if (source == null) {
throw new BaseException("该素材不存在");
}
try {
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(source.getScenicId());
String uploadedUrl = adapter.uploadFile(file, PHOTO_PATH, id + "_q_.jpg");
String uploadedUrl = adapter.uploadFile("image/jpeg", file, PHOTO_PATH, id + "_q_.jpg");
SourceEntity sourceUpd = new SourceEntity();
sourceUpd.setId(id);

View File

@@ -8,6 +8,7 @@ import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
import com.ycwl.basic.image.pipeline.core.Pipeline;
import com.ycwl.basic.image.pipeline.core.PipelineBuilder;
import com.ycwl.basic.image.pipeline.enums.ImageSource;
import com.ycwl.basic.image.pipeline.enums.ImageType;
import com.ycwl.basic.image.pipeline.enums.PipelineScene;
import com.ycwl.basic.image.pipeline.stages.CleanupStage;
import com.ycwl.basic.image.pipeline.stages.ConditionalRotateStage;
@@ -776,7 +777,7 @@ public class PrinterServiceImpl implements PrinterService {
private String processPhotoWithPipeline(MemberPrintResp item, Long scenicId, File qrCodeFile) {
PrinterOrderItem orderItem = PrinterOrderItem.fromMemberPrintResp(item);
PhotoProcessContext context = new PhotoProcessContext(orderItem, scenicId);
PhotoProcessContext context = PhotoProcessContext.fromPrinterOrderItem(orderItem, scenicId);
context.setQrcodeFile(qrCodeFile);
try {
@@ -799,13 +800,13 @@ public class PrinterServiceImpl implements PrinterService {
context.setSource(ImageSource.UNKNOWN);
}
if (context.isNormalPhoto()) {
if (context.getImageType() == ImageType.NORMAL_PHOTO) {
prepareNormalPhotoContext(context);
} else if (context.isPuzzle()) {
} else if (context.getImageType() == ImageType.PUZZLE) {
prepareStorageAdapter(context);
}
Pipeline<PhotoProcessContext> pipeline = context.isPuzzle()
Pipeline<PhotoProcessContext> pipeline = context.getImageType() == ImageType.PUZZLE
? createPuzzlePipeline()
: createNormalPhotoPipeline();
@@ -814,7 +815,7 @@ public class PrinterServiceImpl implements PrinterService {
if (success && context.getResultUrl() != null) {
log.info("照片处理成功: photoId={}, type={}, url={}",
item.getId(),
context.isPuzzle() ? "拼图" : "普通照片",
context.getImageType() == ImageType.PUZZLE ? "拼图" : "普通照片",
context.getResultUrl());
return context.getResultUrl();
} else {