design detail 新增接口--编辑图层的位置、大小

This commit is contained in:
xupei
2023-09-29 13:59:38 +08:00
parent f026a9b929
commit b0095e26a7
17 changed files with 235 additions and 31 deletions

View File

@@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
@Api(tags = "design Detail模块")
@@ -68,5 +69,9 @@ public class DesignDetailController {
return response;
}
@ApiOperation(value = "编辑图层大小和位置")
@PostMapping("/editLayers")
public Response<ComposeLayersVO> editPositionAndScale(@Valid @RequestBody EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException {
return Response.success(designItemService.editLayersPositionAndScale(positionAndScaleVO));
}
}

View File

@@ -67,8 +67,6 @@ public class SysFile implements Serializable {
*/
private Date updateDate;
private Integer isCopy;
public SysFile() {
}

View File

@@ -71,6 +71,11 @@ public class TDesignPythonOutfitDetail implements Serializable {
*/
@ApiModelProperty(value = "位置")
private String position;
/**
* 图层缩放大小
*/
@ApiModelProperty(value = "图层缩放大小")
private String scale;
/**
* 用户ID
*/

View File

@@ -16,8 +16,7 @@ public class DesignSingleItemDTO {
@ApiModelProperty("生成item实际对应的类型 有:outwear,dress,blouse,skirt,trousers Shoes Hairstyle Earring")
private String type;
@NotBlank(message = "path cannot be empty!")
@ApiModelProperty("对应的图片的绝对路径")
@ApiModelProperty("对应的图片的minIO路径")
private String path;
@NotBlank(message = "color cannot be empty!")

View File

@@ -0,0 +1,21 @@
package com.ai.da.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel("编辑图层位置大小,合成图层")
public class ComposeLayersVO {
@ApiModelProperty("designItemId")
private Long designItemId;
@ApiModelProperty("图层信息")
private List<DesignPythonOutfitVO> layers;
@ApiModelProperty("合成图")
private String designItemUrl;
}

View File

@@ -23,9 +23,12 @@ public class DesignItemClothesDetailVO {
@ApiModelProperty("上传时候对应的类型,一级类型 Moodboard Printboard Sketchboard MarketingSketch Colorboard")
private String level1Type;
@ApiModelProperty("对应的图片的绝对路径")
@ApiModelProperty("对应的图片路径")
private String path;
@ApiModelProperty("对应图片minIO路径")
private String minIOPath;
@ApiModelProperty(" 颜色 存 RGB值 中间空格分隔 比如 58 58 169")
// private String color;
private PantoneVO color;

View File

@@ -17,9 +17,12 @@ public class DesignItemOthersDetailVO {
@ApiModelProperty("对应的类型 有Hairstyle Earring Body")
private String type;
@ApiModelProperty("对应的图片的绝对路径")
@ApiModelProperty("对应的图片路径")
private String path;
@ApiModelProperty("对应图片minIO路径")
private String minIOPath;
@ApiModelProperty(" 颜色 存 RGB值 中间空格分隔 比如 58 58 169")
// private String color;
private PantoneVO color;

View File

@@ -42,4 +42,9 @@ public class DesignPythonOutfitVO {
*/
@ApiModelProperty(value = "位置")
private List<Long> position;
/**
* 图层缩放比例
*/
@ApiModelProperty(value = "缩放比例")
private Float scale = 1.0f;
}

View File

@@ -15,6 +15,9 @@ public class DesignSinglePrint {
@ApiModelProperty("印花url")
private String path;
@ApiModelProperty("印花minIO路径")
private String minIOPath;
@ApiModelProperty("印花位置")
private List<Double> location;
@@ -38,8 +41,9 @@ public class DesignSinglePrint {
this.scale = scale;
}
public DesignSinglePrint(String path, List<Double> location, Double scale, Double angle, Integer priority) {
public DesignSinglePrint(String path, String minIOPath, List<Double> location, Double scale, Double angle, Integer priority) {
this.path = path;
this.minIOPath = minIOPath;
this.location = location;
this.scale = scale;
this.angle = angle;

View File

@@ -8,11 +8,10 @@ import java.util.List;
@Data
public class DesignSingleVO {
@ApiModelProperty("designItemId")
private Long designItemId;
/**
* 全身图
*/
@ApiModelProperty("全身图")
private String designItemUrl;

View File

@@ -0,0 +1,15 @@
package com.ai.da.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("编辑图层的位置、大小")
public class EditLayersPositionAndScaleVO {
@ApiModelProperty("layers")
private ComposeLayersVO layers;
@ApiModelProperty("时区")
private String timeZone;
}

View File

@@ -1404,7 +1404,7 @@ public class PythonService {
location.add(priority - 1, p.getLocation());
scale.add(priority - 1,p.getScale());
angle.add(priority - 1,p.getAngle());
paths.add(priority - 1,p.getPath());
paths.add(priority - 1,p.getMinIOPath());
}
// log.info("本次print打点locations###{}###fileVO{}", p.getLocation(), JSON.toJSONString(fileVO));
});
@@ -1697,7 +1697,7 @@ public class PythonService {
throw new BusinessException("Generate Exception! Code : " + jsonObject.get("code"));
}
public String sendPostToModel(Map<String,Object> content,String portAndRoute,String functionName){
public Response sendPostToModel(String content,String portAndRoute,String functionName){
OkHttpClient client = new OkHttpClient().newBuilder()
.connectTimeout(30, TimeUnit.SECONDS)
@@ -1706,26 +1706,26 @@ public class PythonService {
.writeTimeout(60, TimeUnit.SECONDS)//写入超时(单位:秒)
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(content));
RequestBody body = RequestBody.create(mediaType, content);
Request request = new Request.Builder()
.url(accessPythonIp + ":" + portAndRoute)
.url("http://18.167.251.121" + ":" + portAndRoute)
.method("POST", body)
.addHeader("Authorization", "Basic YWlkbGFiOjEyMw==")
.addHeader("Content-Type", "application/json")
.build();
Response response = null;
String bodyString = null;
// String bodyString = null;
try {
log.info(functionName + "请求入参content###{}", JSON.toJSONString(content));
log.info(functionName + "请求入参content###{}", content);
response = client.newCall(request).execute();
bodyString = response.body().string();
// bodyString = response.body().string();
} catch (IOException ioException) {
log.error("PythonService##"+ functionName +"异常###{}", ExceptionUtil.getThrowableList(ioException));
}
return bodyString;
return response;
}
private static List<String> setGenerateImageList(JSONObject jsonObject){
private List<String> setGenerateImageList(JSONObject jsonObject){
List<String> imageUrlList = JSONObject.parseArray(jsonObject.get("list").toString(),String.class);
if (imageUrlList.isEmpty()){
log.error("PythonService##generateSketchOrPrint异常###{}","diffusion response list is null");
@@ -1735,4 +1735,38 @@ public class PythonService {
return imageUrlList;
}
public String composeLayers(List<OutfitDetailPythonItem> layersDetail) throws IOException {
HashMap<String, List<OutfitDetailPythonItem>> layers = new HashMap<>();
HashMap<String, HashMap<String, List<OutfitDetailPythonItem>>> content = new HashMap<>();
layers.put("layers", layersDetail);
content.put("0",layers);
String jsonString = JSON.toJSONString(content, SerializerFeature.WriteNullStringAsEmpty);
// todo 添加限流
Response response = this.sendPostToModel(jsonString, "9991/api/preview_control", "composeLayers");
// todo 结束限流
String bodyString;
// 生成失败
if (Objects.isNull(response) || Objects.isNull(response.body())) {
log.error("PythonService##composeLayers异常###{}", "response or body is empty!");
throw new BusinessException("generate exception!");
}else {
bodyString = response.body().string();
}
JSONObject jsonObject = JSON.parseObject(bodyString);
Boolean result = JSON.parseObject(JSON.toJSONString(response)).getBoolean("successful");
if (result && jsonObject.get("msg").equals("OK!")) {
return getCompositeImage(jsonObject.getJSONObject("code"));
}
log.info("composeLayers 失败###{}", jsonObject);
//生成失败
throw new BusinessException("composeLayers Exception!");
}
private String getCompositeImage(JSONObject jsonObject){
JSONObject item0 = jsonObject.getJSONObject("0");
return item0.getString("synthesis_url");
}
}

View File

@@ -46,7 +46,6 @@ public class DesignPythonItemPrint {
return IfSingle;
}
// todo
public DesignPythonItemPrint(String singlePath, String level1Type, Float scale, Boolean ifSingle) {
this.path = singlePath;
this.level1Type = level1Type;

View File

@@ -0,0 +1,33 @@
package com.ai.da.python.vo;
import lombok.Data;
import java.util.List;
@Data
public class OutfitDetailPythonItem {
private String image_category;
private List<Long> position;
private List<Long> image_size;
private Float scale;
private String image_url;
private String mask_url;
public OutfitDetailPythonItem() {
}
public OutfitDetailPythonItem(String image_category, List<Long> position, List<Long> image_size, Float scale, String image_url, String mask_url) {
this.image_category = image_category;
this.position = position;
this.image_size = image_size;
this.scale = scale;
this.image_url = image_url;
this.mask_url = mask_url;
}
}

View File

@@ -6,6 +6,7 @@ import com.ai.da.model.dto.DesignSingleIncludeLayersDTO;
import com.ai.da.model.vo.*;
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.IOException;
import java.util.List;
/**
@@ -47,4 +48,6 @@ public interface DesignItemService extends IService<DesignItem> {
DesignSingleVO designSingleIncludeLayers(DesignSingleIncludeLayersDTO designSingleIncludeLayersDTO);
ComposeLayersVO editLayersPositionAndScale(EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException;
}

View File

@@ -10,15 +10,10 @@ import com.ai.da.common.utils.DateUtil;
import com.ai.da.common.utils.MinioUtil;
import com.ai.da.mapper.DesignItemMapper;
import com.ai.da.mapper.entity.*;
import com.ai.da.model.dto.DesignSingleDTO;
import com.ai.da.model.dto.DesignSingleIncludeLayersDTO;
import com.ai.da.model.dto.DesignSingleItemDTO;
import com.ai.da.model.dto.DesignSinglePrintDTO;
import com.ai.da.model.dto.*;
import com.ai.da.model.vo.*;
import com.ai.da.python.PythonService;
import com.ai.da.python.vo.DesignPythonItem;
import com.ai.da.python.vo.DesignPythonItemPrint;
import com.ai.da.python.vo.DesignPythonObjects;
import com.ai.da.python.vo.*;
import com.ai.da.service.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
@@ -26,11 +21,14 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
@@ -356,6 +354,7 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
designPythonOutfitDetail.setImageSize(jsonObject.getString("image_size"));
designPythonOutfitDetail.setImageCategory(jsonObject.getString("image_category"));
designPythonOutfitDetail.setMaskUrl(jsonObject.getString("mask_url"));
designPythonOutfitDetail.setScale(Objects.isNull(jsonObject.getString("scale")) ? null : jsonObject.getString("scale"));
designPythonOutfitDetail.setUserId(userId);
list.add(designPythonOutfitDetail);
}
@@ -421,10 +420,68 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
TDesignPythonOutfit designPythonOutfit = designPythonOutfitService.getByDesignItemId(designSingleIncludeLayersDTO.getDesignItemId());
Assert.notNull(designItem,"design item detail layers does not exists!");
return assembleDesignSingleResponse(designItem.getId(),minioUtil.splitThenGetPreviewUrl(designPythonOutfit.getDesignUrl(),480),
return assembleDesignSingleResponse(designItem.getId(),
minioUtil.splitThenGetPreviewUrl(designPythonOutfit.getDesignUrl(),480),
designSingleIncludeLayersDTO.getDesignSingleItemDTOList(),detailsVO);
}
@Override
public ComposeLayersVO editLayersPositionAndScale(EditLayersPositionAndScaleVO positionAndScaleVO) throws IOException {
ComposeLayersVO designItemLayer = positionAndScaleVO.getLayers();
// 1、校验designItem是是否存在
DesignItem designItem = selectById(designItemLayer.getDesignItemId());
Assert.notNull(designItem,"designItem does not exists!");
// 2、校验layers是否存在
designItemLayer.getLayers().forEach(layer -> {
TDesignPythonOutfitDetail detail = designPythonOutfitDetailService.getById(layer.getId());
Assert.notNull(detail,layer.getImageCategory() + " layer does not exists!");
layer.setImageUrl(detail.getImageUrl());
layer.setMaskUrl(detail.getMaskUrl());
});
// 3、组装python入参
List<OutfitDetailPythonItem> outfitDetailPythonItems = convertToOutfitDetailPythonItemList(designItemLayer.getLayers());
// 4、合成图层
String synthesisUrl = pythonService.composeLayers(outfitDetailPythonItems);
designItemLayer.setDesignItemUrl(minioUtil.splitThenGetPreviewUrl(synthesisUrl,480));
// 5、更新数据库根据designItemId更新designItemUrl
designItem.setUpdateDate(DateUtil.getByTimeZone(positionAndScaleVO.getTimeZone()));
designItem.setDesignUrl(synthesisUrl);
designItem.setId(designItemLayer.getDesignItemId());
updateById(designItem);
// 6、将图层信息position和scale更新到t_design_python_outfit_detail表
ArrayList<TDesignPythonOutfitDetail> details = new ArrayList<>();
designItemLayer.getLayers().forEach(layer -> {
TDesignPythonOutfitDetail layerDetail = new TDesignPythonOutfitDetail();
layerDetail.setPosition(layer.getPosition().toString());
layerDetail.setScale(layer.getScale().toString());
layerDetail.setId(layer.getId());
details.add(layerDetail);
});
designPythonOutfitDetailService.updateBatchById(details);
// 7、返回图层及合成图信息
designItemLayer.getLayers().forEach(layer -> {
ArrayList<Long> imageSize = new ArrayList<>();
for (int i = 0; i < layer.getImageSize().size(); i++) {
imageSize.add((long) (layer.getImageSize().get(i) * layer.getScale()));
}
layer.setImageSize(imageSize);
if (!StringUtil.isNullOrEmpty(layer.getImageUrl())){
layer.setImageUrl(minioUtil.splitThenGetPreviewUrl(layer.getImageUrl(),480));
}
if (!StringUtil.isNullOrEmpty(layer.getMaskUrl())){
layer.setMaskUrl(minioUtil.splitThenGetPreviewUrl(layer.getMaskUrl(),480));
}
});
return designItemLayer;
}
private DesignSingleVO assembleDesignSingleResponse(Long designItemId,String designItemUrl,
List<DesignSingleItemDTO> designSingleItemDTOList,
List<DesignPythonOutfitVO> layersObject){
@@ -440,6 +497,8 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
DesignItemClothesDetailVO designItemClothesDetailVO = new DesignItemClothesDetailVO();
designItemClothesDetailVO.setId(singleItem.getId());
designItemClothesDetailVO.setType(singleItem.getType());
designItemClothesDetailVO.setPath(minioUtil.splitThenGetPreviewUrl(singleItem.getPath(),480));
designItemClothesDetailVO.setMinIOPath(singleItem.getPath());
designItemClothesDetailVO.setColor(panToneService.getPantoneByRgb(singleItem.getColor()));
// designItemClothesDetailVO.setPrintObject(new DesignPythonItemPrint(singleItem.getPrintObject().getPath()));
designItemClothesDetailVO.setPrintObject(singleItem.getPrintObject());
@@ -496,4 +555,16 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
return designItemDetailPrints;
}
private List<OutfitDetailPythonItem> convertToOutfitDetailPythonItemList(List<DesignPythonOutfitVO> layers){
ArrayList<OutfitDetailPythonItem> composeLayerPythonItem = new ArrayList<>();
layers.forEach(layer -> {
composeLayerPythonItem.add(new OutfitDetailPythonItem(layer.getImageCategory(),
layer.getPosition(),
layer.getImageSize(),
layer.getScale(),
layer.getImageUrl(),
layer.getMaskUrl()));
});
return composeLayerPythonItem;
}
}

View File

@@ -837,6 +837,8 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
.collect(Collectors.toList());
response.setClothes(CopyUtil.copyList(filterDetail,DesignItemClothesDetailVO.class,(o,d)->{
d.setId(o.getId());
d.setPath(minIoUtil.splitThenGetPreviewUrl(o.getPath(),480));
d.setMinIOPath(o.getPath());
d.setLevel1Type(converTypeToLevel1(o.getType()));
// 根据designItemDetailId获取印花
List<DesignItemDetailPrint> prints = designItemDetailPrintService.getByDesignItemDetailId(o.getId());
@@ -860,6 +862,8 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
.collect(Collectors.toList());
response.setOthers(CopyUtil.copyList(filterDetail2, DesignItemOthersDetailVO.class, (o, d) -> {
d.setId(o.getBusinessId());
d.setPath(minIoUtil.splitThenGetPreviewUrl(o.getPath(),480));
d.setMinIOPath(o.getPath());
d.setPrintObject(new DesignPythonItemPrint());
}));
return editDesignItemLayer(flag,designPythonOutfit,
@@ -992,7 +996,8 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
designSinglePrint.setAngle(detailPrint.getAngle());
designSinglePrint.setPriority(detailPrint.getPriority());
}
designSinglePrint.setPath(detailPrint.getPath());
designSinglePrint.setPath(minIoUtil.splitThenGetPreviewUrl(detailPrint.getPath(),480));
designSinglePrint.setMinIOPath(detailPrint.getPath());
designSinglePrint.setScale(detailPrint.getScale());
prints.add(designSinglePrint);
}else {
@@ -1000,7 +1005,9 @@ public class DesignServiceImpl extends ServiceImpl<DesignMapper, Design> impleme
designSinglePrintDTO.setIfSingle(Boolean.TRUE);
designItemDetailPrints.forEach(print -> {
if (print.getSingleOrOverall().equals("single")){
prints.add(new DesignSinglePrint(print.getPath(),
prints.add(new DesignSinglePrint(
minIoUtil.splitThenGetPreviewUrl(print.getPath(),480),
print.getPath(),
JSONArray.parseArray(print.getPosition(),Double.class),
print.getScale(),
print.getAngle(),