Commit ee1cdc60 authored by Administrator's avatar Administrator

增加局部重绘

parent f69ff7a9
...@@ -31,12 +31,12 @@ export default { ...@@ -31,12 +31,12 @@ export default {
img_idx: string = "", img_idx: string = "",
prompt: string = "", prompt: string = "",
negative_prompt: string = "", negative_prompt: string = "",
width: string = "960", width: string = "",
height: string = "512", height: string = "",
sampler_index: string = "DPM++ 2M Karras", sampler_index: string = "",
seed: string = "-1", seed: string = "",
steps: string = "25", steps: string = "",
cfg_scale: string = "9", cfg_scale: string = "",
encrypt: string = "false", encrypt: string = "false",
model: string = "" model: string = ""
): Promise<{"domain_image_path": string, "local_image_path": string}> { ): Promise<{"domain_image_path": string, "local_image_path": string}> {
...@@ -73,6 +73,57 @@ export default { ...@@ -73,6 +73,57 @@ export default {
}); });
}, },
submitSDInPaint(
task_id: string = "",
img_idx: string = "",
prompt: string = "",
negative_prompt: string = "",
width: string = "",
height: string = "",
sampler_index: string = "",
seed: string = "",
steps: string = "",
cfg_scale: string = "",
encrypt: string = "false",
model: string = "",
base_img: string = "",
mask: string = ""
): Promise<{"domain_image_path": string, "local_image_path": string}> {
if (!prompt || !base_img || !mask) {
return Promise.reject("SD提示词、基础图、mask均不能为空");
}
const post_data = {
task_id: task_id,
img_idx: img_idx,
prompt: prompt,
negative_prompt: negative_prompt,
sampler_index: sampler_index,
seed: seed,
steps: steps,
width: width,
height: height,
cfg_scale: cfg_scale,
encrypt: encrypt,
model: model,
base_img: base_img,
mask: mask
}
return request.post('/text2video/img2img_inpaint', post_data)
.then((res: any) => {
// console.log(res);
if (res && res.code === 0) {
return {"domain_image_path": res.data.result.domain_image_path, "local_image_path": res.data.result.local_image_path};
} else {
const errorMessage = res ? res.message : "未知错误";
return Promise.reject(errorMessage);
}
})
.catch((err: any) => {
console.log(`err = ${JSON.stringify(err)}`);
return Promise.reject(`与 stable-diffusion-webui Api 通讯失败`);
});
},
submitGenVideo(gen_video_param: any): Promise<string> { submitGenVideo(gen_video_param: any): Promise<string> {
if (!gen_video_param) { if (!gen_video_param) {
return Promise.reject("输入不能为空"); return Promise.reject("输入不能为空");
......
...@@ -87,6 +87,13 @@ const cover_backcover = reactive({ ...@@ -87,6 +87,13 @@ const cover_backcover = reactive({
product_pic_speech: "", product_pic_speech: "",
}); });
const inPaintVisible = ref(false);
const inPaintBaseImgData = ref("");
const inPaintMaskData = ref("");
const inPaintType = ref("");
const inPaintItem = ref();
const inPaintPrompt = ref("");
onMounted(() => { onMounted(() => {
// 初始化task_id // 初始化task_id
...@@ -775,7 +782,7 @@ const onChangeScreen = (val: string) => { ...@@ -775,7 +782,7 @@ const onChangeScreen = (val: string) => {
if (!form.task_id) { if (!form.task_id) {
// 初始化task_id // 初始化task_id
form.task_id = utils.genDateTimeStr(); form.task_id = utils.genDateTimeStr();
console.log('更改屏幕设置,重新生成task_id=', form.task_id) console.log('更改屏幕设置,task_id=', form.task_id)
} }
if (debug.value == true) { if (debug.value == true) {
...@@ -997,7 +1004,7 @@ const MarketingTemplateUploadProductPicSuccess = (val: Wm.UploadResult) => { ...@@ -997,7 +1004,7 @@ const MarketingTemplateUploadProductPicSuccess = (val: Wm.UploadResult) => {
message: '上传成功', message: '上传成功',
type: 'success' type: 'success'
}) })
onMarketingTemplateAddTextToPic('product'); // onMarketingTemplateAddTextToPic('product');
} else { } else {
ElMessage({ ElMessage({
message: '上传失败:'+val.message, message: '上传失败:'+val.message,
...@@ -1028,7 +1035,7 @@ const MarketingTemplateUploadCoverPicSuccess = (val: Wm.UploadResult) => { ...@@ -1028,7 +1035,7 @@ const MarketingTemplateUploadCoverPicSuccess = (val: Wm.UploadResult) => {
message: '上传成功', message: '上传成功',
type: 'success' type: 'success'
}) })
onMarketingTemplateAddTextToPic('cover'); // onMarketingTemplateAddTextToPic('cover');
} else { } else {
ElMessage({ ElMessage({
message: '上传失败:'+val.message, message: '上传失败:'+val.message,
...@@ -1093,7 +1100,7 @@ const onAddMarketingTemplatePicText = async (type: string, action: string, index ...@@ -1093,7 +1100,7 @@ const onAddMarketingTemplatePicText = async (type: string, action: string, index
}; };
if (type == 'product') { if (type == 'product') {
const newElement = { const newElement = {
text: "关注 点赞 评论\n记得一键三连哦", text: "关注 点赞 评论",
color: "#DAFB01", color: "#DAFB01",
bg_color: "#000000", bg_color: "#000000",
font_size: 60, font_size: 60,
...@@ -1279,6 +1286,228 @@ const onSelectCoverChange = (value: any) => { ...@@ -1279,6 +1286,228 @@ const onSelectCoverChange = (value: any) => {
cover_backcover.cover_pic_with_text_local = ''; cover_backcover.cover_pic_with_text_local = '';
onMarketingTemplateAddTextToPic('cover'); onMarketingTemplateAddTextToPic('cover');
} }
// 局部重绘Dialog
const showInPaintDialog = (type: string, item: any) => {
let base_img_path = "";
inPaintType.value = type;
inPaintItem.value = null;
inPaintPrompt.value = "";
inPaintBaseImgData.value = "";
inPaintMaskData.value = "";
if (type == "scene") {
inPaintItem.value = item;
inPaintPrompt.value = inPaintItem.value.场景关键词+' '+inPaintItem.value.角色关键词;
base_img_path = inPaintItem.value.本镜配图;
} else if (type == "cover") {
inPaintPrompt.value = "";
base_img_path = cover_backcover.cover_pic;
} else if (type == 'product') {
inPaintPrompt.value = "";
base_img_path = cover_backcover.product_pic;
};
if (!base_img_path || base_img_path.length==0) {
ElMessage({
message: "没有基础图片,请确认",
type: "error",
});
return;
}
inPaintVisible.value = true; // 打开对话框
// 等待元素加载完成
nextTick(() => {
// 局部重绘
const base_canvas = document.getElementById('baseCanvas') as HTMLCanvasElement;
const mask_canvas = document.getElementById('maskCanvas') as HTMLCanvasElement;
if (base_canvas && mask_canvas) {
let base_ctx = base_canvas.getContext('2d') as CanvasRenderingContext2D;
base_ctx.clearRect(0, 0, base_canvas.width, base_canvas.height);
var img = new Image();
img.crossOrigin = 'Anonymous'; // 如果图片需要用于跨域,则需要设置这个属性
img.onload = function() {
base_canvas.width = img.width;
base_canvas.height = img.height;
base_ctx.drawImage(img, 0, 0, base_canvas.width, base_canvas.height);
};
img.src = base_img_path;
let mask_ctx = mask_canvas.getContext('2d') as CanvasRenderingContext2D;
mask_ctx.clearRect(0, 0, mask_canvas.width, mask_canvas.height);
// mask_ctx.globalAlpha = 0.5; // 可自定义透明度
let isDrawing = false;
// 鼠标或触摸事件开始绘制
mask_canvas.addEventListener('mousedown', startDrawing);
mask_canvas.addEventListener('touchstart', startDrawing);
// 鼠标或触摸事件绘制中
mask_canvas.addEventListener('mousemove', draw);
mask_canvas.addEventListener('touchmove', draw);
// 鼠标或触摸事件结束绘制
mask_canvas.addEventListener('mouseup', stopDrawing);
mask_canvas.addEventListener('touchend', stopDrawing);
mask_canvas.addEventListener('mouseout', stopDrawing);
// 清除按钮点击事件
const clearButton = document.getElementById('clearButton') as HTMLButtonElement;
clearButton.addEventListener('click', clearCanvas);
// 开始绘制
function startDrawing(e: any) {
isDrawing = true;
const { offsetX, offsetY } = getOffset(e);
mask_ctx.lineWidth = 40; // 设置线条粗细
// mask_ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)'; // 设置线条颜色
mask_ctx.strokeStyle = 'white'; // 设置线条颜色
mask_ctx.lineCap = "round"; // 线头尾为圆形
mask_ctx.beginPath();
mask_ctx.moveTo(offsetX, offsetY);
}
// 绘制中
function draw(e: any) {
if (!isDrawing) return;
const { offsetX, offsetY } = getOffset(e);
mask_ctx.lineTo(offsetX, offsetY);
mask_ctx.stroke();
}
// 结束绘制
function stopDrawing() {
isDrawing = false;
inPaintBaseImgData.value = base_canvas.toDataURL('image/png');
inPaintMaskData.value = mask_canvas.toDataURL('image/png');
}
// 清除画布
function clearCanvas() {
mask_ctx.clearRect(0, 0, mask_canvas.width, mask_canvas.height);
}
// 获取鼠标或触摸事件的偏移量
function getOffset(e: any) {
const rect = mask_canvas.getBoundingClientRect();
let offsetX, offsetY;
if (e.type.includes('touch')) {
offsetX = e.touches[0].clientX - rect.left;
offsetY = e.touches[0].clientY - rect.top;
} else {
offsetX = e.offsetX;
offsetY = e.offsetY;
}
return { offsetX, offsetY };
}
} else {
console.error('Canvas element not found');
}
});
}
const onSubmitInPaint = async () => {
if (!form.task_id) {
ElMessage({
message: "task_id不能为空,请刷新页面",
type: "error",
});
return;
}
// console.log('333', inPaintBaseImgData.value)
// console.log('333', inPaintMaskData.value)
// return;
if (!inPaintBaseImgData.value || !inPaintMaskData.value) {
ElMessage({
message: "请在图片上涂抹需要保留的部分!",
type: "error",
});
return;
}
if (!inPaintPrompt.value || inPaintPrompt.value.length==0) {
ElMessage({
message: "请填写画面描述!",
type: "error",
});
return;
}
const sampler_index = sd_model.sampler_index;
const seed = sd_model.seed;
const steps = sd_model.steps;
const cfg_scale = sd_model.cfg_scale;
const model = sd_model.model;
const base_img = inPaintBaseImgData.value;
const mask = inPaintMaskData.value;
let sd_prompt = "";
let img_id = ""
let item = null;
if (inPaintType.value == "scene") {
item = inPaintItem.value;
item.本镜配图 = "src/assets/loading.gif";
img_id = item.编号;
} else if (inPaintType.value == "cover") {
img_id = 'cover';
cover_backcover.cover_pic = 'src/assets/waiting.png';
cover_backcover.cover_pic_local = '';
} else if (inPaintType.value == 'product') {
img_id = 'product';
cover_backcover.product_pic = 'src/assets/waiting.png';
cover_backcover.product_pic_local = '';
};
try {
let keywords_en = await text2videoService.submitTranslateToEn(utils.aesEncrypt(inPaintPrompt.value), form.task_id, "true");
sd_prompt = keywords_en.replace(/"/g, '') + "," + sd_prompt_prefix;
const sd_img = await text2videoService.submitSDInPaint(
form.task_id,
img_id,
utils.aesEncrypt(sd_prompt),
utils.aesEncrypt(sd_negative_prompt_prefix),
utils.aesEncrypt(form.img_size.width),
utils.aesEncrypt(form.img_size.height),
utils.aesEncrypt(sampler_index),
utils.aesEncrypt(seed),
utils.aesEncrypt(steps),
utils.aesEncrypt(cfg_scale),
"true",
utils.aesEncrypt(model),
utils.aesEncrypt(base_img),
utils.aesEncrypt(mask),
);
if (inPaintType.value == "scene") {
item.本镜配图 = sd_img.domain_image_path + "?v=" + utils.genDateTimeStr();
item.local_image_path = sd_img.local_image_path;
} else if (inPaintType.value == 'cover') {
cover_backcover.cover_pic = sd_img.domain_image_path + "?v=" + utils.genDateTimeStr();
cover_backcover.cover_pic_local = sd_img.local_image_path;
} else if (inPaintType.value == 'product') {
cover_backcover.product_pic = sd_img.domain_image_path + "?v=" + utils.genDateTimeStr();
cover_backcover.product_pic_local = sd_img.local_image_path;
};
} catch (error) {
ElMessage({
message: String(error),
type: "error",
});
} finally {
inPaintVisible.value = false; // 关闭对话框
}
}
</script> </script>
<template> <template>
...@@ -1510,6 +1739,14 @@ const onSelectCoverChange = (value: any) => { ...@@ -1510,6 +1739,14 @@ const onSelectCoverChange = (value: any) => {
>上传图片</el-button >上传图片</el-button
> >
</el-upload> </el-upload>
<div style="margin: 5px 0">
<el-button
type="primary"
size="small"
@click="showInPaintDialog('scene', scope.row)"
>局部重绘</el-button
>
</div>
<!-- <div style="margin: 5px 0"><el-button plain size="small" @click="onClearOnePic(scope.row)">清除图片</el-button></div> --> <!-- <div style="margin: 5px 0"><el-button plain size="small" @click="onClearOnePic(scope.row)">清除图片</el-button></div> -->
<div style="margin: 5px 0"> <div style="margin: 5px 0">
<el-button plain size="small" @click="showsdprompt(scope.row)" <el-button plain size="small" @click="showsdprompt(scope.row)"
...@@ -1599,6 +1836,13 @@ const onSelectCoverChange = (value: any) => { ...@@ -1599,6 +1836,13 @@ const onSelectCoverChange = (value: any) => {
style="margin-left: 12px" style="margin-left: 12px"
>清除图片</el-button >清除图片</el-button
> >
<el-button
type="primary"
size="small"
@click="showInPaintDialog('cover', '')"
style="margin-left: 12px"
>局部重绘</el-button
>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div style="width: 100%"> <div style="width: 100%">
...@@ -1708,6 +1952,13 @@ const onSelectCoverChange = (value: any) => { ...@@ -1708,6 +1952,13 @@ const onSelectCoverChange = (value: any) => {
style="margin-left: 12px" style="margin-left: 12px"
>清除图片</el-button >清除图片</el-button
> >
<el-button
type="primary"
size="small"
@click="showInPaintDialog('product', '')"
style="margin-left: 12px"
>局部重绘</el-button
>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div style="width: 100%"> <div style="width: 100%">
...@@ -1899,6 +2150,7 @@ const onSelectCoverChange = (value: any) => { ...@@ -1899,6 +2150,7 @@ const onSelectCoverChange = (value: any) => {
<video :src="form.final_video" controls></video> <video :src="form.final_video" controls></video>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 授权密码框 --> <!-- 授权密码框 -->
<el-dialog <el-dialog
v-model="pwdCheckDialogVisible" v-model="pwdCheckDialogVisible"
...@@ -2015,6 +2267,53 @@ const onSelectCoverChange = (value: any) => { ...@@ -2015,6 +2267,53 @@ const onSelectCoverChange = (value: any) => {
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<!-- 局部重绘 -->
<el-dialog
v-model="inPaintVisible"
title="局部重绘"
:fullscreen="true"
:close-on-click-modal="false"
:close-on-press-escape="true"
:show-close="true"
:lock-scroll="true"
>
<div>请在图片上涂抹需要保留的部分</div>
<div
ref="inpaint"
:style="
'position: relative; width: ' +
form.img_size.width +
'px; height: ' +
form.img_size.height +
'px'
"
>
<canvas
id="baseCanvas"
:width="form.img_size.width"
:height="form.img_size.height"
style="position: absolute; left: 0; top: 0"
></canvas>
<canvas
id="maskCanvas"
:width="form.img_size.width"
:height="form.img_size.height"
style="position: absolute; left: 0; top: 0; z-index: 1; background: none"
></canvas>
</div>
<button id="clearButton">清除涂抹</button>
<div>
<span>画面描述:</span>
<el-input v-model="inPaintPrompt" :autosize="true" type="textarea"></el-input>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="inPaintVisible = false">取消</el-button>
<el-button type="primary" @click="onSubmitInPaint">提交</el-button>
</div>
</template>
</el-dialog>
</main> </main>
</template> </template>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment