stable-diffusion-for-fun/templates/index.html

886 lines
45 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html>
<head>
<meta charset="utf-8">
<title>Happy Diffusion (Private Access) | 9pm</title>
<meta name="description" content="Stable Diffusion Online">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="card mb-3">
<div class="card-body">
<div class="row mb-3">
<div class="col-sm-8">
<label for="apiKey" class="form-label" data-en_XX="API Key" data-zh_CN="API 密钥">API Key</label>
<input type="password" class="form-control" id="apiKey" value="">
</div>
<div class="col-sm-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="showPreview" disabled>
<label class="form-check-label" for="showPreview" data-en_XX="Preview Image"
data-zh_CN="预览生成图像">Preview Image
</label>
</div>
<select class="form-select" size="2" id="language">
<option value="zh_CN">中文</option>
<option selected value="en_XX">English</option>
</select>
</div>
</div>
<div class="form-row mb-3">
<label for="prompt" class="form-label" data-en_XX="Describe Your Image"
data-zh_CN="形容你的图片(提示词)">Describe Your Image (Prompts)</label>
<input type="text" class="form-control" id="prompt" aria-describedby="promptHelp" value="">
<div id="promptHelp" class="form-text"
data-en_XX="Less than 77 words. Example: photo of a cute cat. Use () to emphasize."
data-zh_CN="少于77个词。比如一张可爱的猫的照片。用括号强调重要性。">Less than 77 words. Example: photo of a cute cat.
Use () to emphasize.</div>
</div>
<div class="form-row mb-3">
<label for="negPrompt" class="form-label"
data-en_XX="Describe What's NOT Your Image (Negative Prompts)"
data-zh_CN="反向形容你的图片(反向提示词)">Describe What's NOT Your Image (Negative Prompts)</label>
<input type="text" class="form-control" id="negPrompt" aria-describedby="negPromptHelp" value="">
<div id="negPromptHelp" class="form-text" data-en_XX="Less than 77 words. Optional."
data-zh_CN="少于77个词。非必填。">Less than 77 words. Optional.</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="form-row">
<label for="inputSeed" data-en_XX="Seed" data-zh_CN="随机数">Seed</label>
<input type="text" class="form-control" id="inputSeed" aria-describedby="inputSeedHelp"
value="">
<div id="inputSeedHelp" class="form-text"
data-en_XX="Leave it empty or set 0 to use random seed" data-zh_CN="非必填。留白或填0使用默认随机数">
Leave it empty or set 0 to use a random seed
</div>
</div>
<div class="form-row">
<label for="inputSteps" data-en_XX="Steps" data-zh_CN="迭代次数">Steps</label>
<input type="number" class="form-control" id="inputSteps" aria-describedby="inputStepsHelp"
placeholder="50">
<div id="inputStepsHelp" class="form-text"
data-en_XX="More steps better image but longer time to generate"
data-zh_CN="迭代次数越多图片越好,但生成时间越久">More steps better image but longer time to generate
</div>
</div>
<div class="form-row">
<label for="inputWidth" data-en_XX="Width" data-zh_CN="图片宽度">Width</label>
<input type="number" class="form-control" id="inputWidth" placeholder="512" min="1"
max="1024">
</div>
<div class="form-row">
<label for="inputHeight" data-en_XX="Height" data-zh_CN="图片高度">Height</label>
<input type="number" class="form-control" id="inputHeight" placeholder="512" min="1"
max="1024">
</div>
<div class="form-row mb-3">
<label for="guidanceScale" data-en_XX="Guidance Scale" data-zh_CN="指导强度">Guidance
Scale</label>
<input type="number" class="form-control" id="inputGuidanceScale"
aria-describedby="inputGuidanceScaleHelp" placeholder="12.5" min="1" max="30">
<div id="inputGuidanceScaleHelp" class="form-text"
data-en_XX="Don't set it to the extremes (1 or 30). 20 means strictly follow prompt, 7 creative/artistic. Lower this number if you see bad images."
data-zh_CN="不建议设最低1或最高30。20代表提示词非常重要7更有创造性。如果看到图片结果较差适当减少强度。">
Don't set it to the extremes (1 or 30). 20 means strictly follow prompt, 7
creative/artistic. Lower this number if you see bad images.
</div>
</div>
<div class="row">
<button id="newTxt2ImgJob" class="btn btn-primary" data-en_XX="Let's Go!"
data-zh_CN="生成图片!">Let's Go!</button>
</div>
</div>
<div class="col-md-9">
<div class="card mb-3">
<div class="card-header">
<ul class="nav nav-pills card-header-pills">
<li class="nav-item">
<a class="nav-link" href="#card-txt" data-en_XX="Text-to-Image"
data-zh_CN="文字->图片">Text-to-Image</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#card-img" data-en_XX="Image-to-Image"
data-zh_CN="图片->图片">Image-to-Image</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#card-inpainting" data-en_XX="Inpainting"
data-zh_CN="图片修复">Inpainting</a>
</li>
</ul>
</div>
<div class="card-body card-specific" id="card-img" style="display:none">
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-header" data-en_XX="1. Choose Reference Image"
data-zh_CN="1. 选择参照图">
1. Choose Reference Image
</div>
<div class="card-body">
<div class="row">
<button id="copy-txt-to-img" class="btn btn-primary mb-3"
data-en_XX="Copy from text-to-image"
data-zh_CN="从【文字->图片】结果复制">Copy from text-to-image</button>
<button id="copy-last-img" class="btn btn-primary mb-3"
data-en_XX="Copy from last image result"
data-zh_CN="从【图片->图片】结果复制">Copy from last image result</button>
<button id="upload-img" class="btn btn-primary mb-3"
data-en_XX="Upload image" data-zh_CN="上传一张图片">Upload
image</button>
</div>
<div class="form-row">
<label for="strength" data-en_XX="Strength"
data-zh_CN="改变程度">Strength</label>
<input type="number" class="form-control" id="inputStrength"
aria-describedby="inputStrengthHelp" placeholder="0.5" min="0"
max="1">
<div id="inputStrengthHelp" class="form-text"
data-en_XX="How different from the original image. 0 means the same, 1 means very different."
data-zh_CN="和参照图有多么的不同。0指一样1指非常不一样。">How different from the
original image
</div>
</div>
<div class="row">
<button id="newImg2ImgJob" class="btn btn-primary mb-3"
data-en_XX="Let's Go with Image Below!"
data-zh_CN="就用下面的图生成!">Let's Go with Image Below!</button>
</div>
</div>
<img class="card-img-bottom" id="reference-img">
</div>
</div>
<div class="col-md-8">
<div class="card">
<div class="card-header" data-en_XX="2. Result" data-zh_CN="2. 结果">
2. Result
</div>
<div class="card-body">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center"
id="img2ImgJobUUID"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="img2ImgStatus"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="img2ImgSeed"></li>
</ul>
</div>
<img class="card-img-bottom" id="img2ImgImg">
</div>
</div>
</div>
</div>
<div class="card-body card-specific" id="card-inpainting" style="display:none">
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-header" data-en_XX="1. Choose Original Image"
data-zh_CN="1. 选择原图">
1. Choose Original Image
</div>
<div class="card-body">
<div class="row">
<button id="copy-txt-to-img-inpaint" class="btn btn-primary mb-3"
data-en_XX="Copy from text-to-image"
data-zh_CN="从【文字->图片】结果复制">Copy
from text-to-image</button>
<button id="copy-last-img-inpaint" class="btn btn-primary mb-3"
data-en_XX="Copy from last image result"
data-zh_CN="从【图片->图片】结果复制">Copy from last image result</button>
<button id="upload-img-inpaint" class="btn btn-primary mb-3"
data-en_XX="Upload image" data-zh_CN="上传一张图片">Upload
image</button>
</div>
</div>
<img class="card-img-bottom" id="inpaint-img">
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header" data-en_XX="2. Remove Area (Mask)"
data-zh_CN="2. 抹去要修复的部分">
2. Remove Area (Mask)
</div>
<div class="card-body">
<div class="row">
<button id="newInpaintingJob" class="btn btn-primary mb-3"
data-en_XX="Let's Go with Image + Mask Below!"
data-zh_CN="进行修复!">Let's
Go with Image + Mask Below!</button>
</div>
<div class="input-group mb-3">
<button id="inpaint-reset" class="btn btn-outline-secondary"
data-en_XX="Reset" data-zh_CN="重置">Reset</button>
<button id="inpaint-undo" class="btn btn-outline-secondary"
data-en_XX="Undo" data-zh_CN="撤销">Undo</button>
<button id="inpaint-redo" class="btn btn-outline-secondary"
data-en_XX="Redo" data-zh_CN="重做">Redo</button>
</div>
<div class="form-row">
<label for="inpaint-strike-size" class="form-label"
data-en_XX="Strike Size" data-zh_CN="笔触大小">Strike Size</label>
<input type="range" class="form-range" min="1" max="30"
id="inpaint-strike-size">
<output id='range-value'></output>
</div>
</div>
<div class="card-img-bottom" style="position: relative;">
<img id="inpaint-img-for-mask" width="100%">
<div id="inpaint-mask-canvas-container"
style="cursor: pointer; position: absolute; top: 0; left: 0;">
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header" data-en_XX="3. Result" data-zh_CN="3. 结果">
3. Result
</div>
<div class="card-body">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center"
id="inpaintJobUUID"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="inpaintStatus"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="inpaintSeed"></li>
</ul>
</div>
<img class="card-img-bottom" id="inpaintImg">
</div>
</div>
</div>
</div>
<div class="card-body card-specific" id="card-txt" style="display:none">
<div class="card">
<div class="card-header" data-en_XX="Result" data-zh_CN="结果">
Result
</div>
<div class="card-body">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center"
id="txt2ImgJobUUID"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="txt2ImgStatus"></li>
<li class="list-group-item d-flex justify-content-between align-items-center"
id="txt2ImgSeed"></li>
</ul>
</div>
<img class="card-img-bottom" id="txt2ImgImg">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<form>
<div class="mb-3">
<label for="jobuuid" class="form-label">Job UUID</label>
<input type="jobuuid" class="form-control" id="jobuuid" aria-describedby="">
</div>
<button id="getjob" type="submit" class="btn btn-primary" data-en_XX="Get Jobs" data-zh_CN="搜索生成结果"
disabled>Get Jobs</button>
<button id="canceljob" type="submit" class="btn btn-primary" data-en_XX="Cancel Job" data-zh_CN="取消"
disabled>Cancel Job</button>
</form>
<div class="mb-3" id="joblist">
</div>
</div>
<script src="{{ url_for('static',filename='jquery-3.6.1.min.js') }}"></script>
<script src="{{ url_for('static',filename='bootstrap.bundle.min.js') }}"></script>
<script src="{{ url_for('static',filename='jsketch.min.js') }}"></script>
<script src="{{ url_for('static',filename='jquery.sketchable.min.js') }}"></script>
<script src="{{ url_for('static',filename='jquery.sketchable.memento.min.js') }}"></script>
<script>
function waitForImage(apikeyVal, uuidValue) {
// Wait until image is done
$.ajax({
type: 'POST',
url: '/get_jobs',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({ 'apikey': apikeyVal, 'uuid': uuidValue }),
success: function (response) {
console.log(response);
if (response.jobs.length == 1) {
if (response.jobs[0].type == 'txt') {
$('#txt2ImgStatus').html(response.jobs[0].status);
$('#txt2ImgSeed').html("seed: " + response.jobs[0].seed);
if (response.jobs[0].status == "done") {
$('#txt2ImgImg').attr('src', response.jobs[0].img);
return;
}
if (response.jobs[0].status == "failed") {
return;
}
} else if (response.jobs[0].type == 'img') {
$('#img2ImgStatus').html(response.jobs[0].status);
$('#img2ImgSeed').html("seed: " + response.jobs[0].seed);
if (response.jobs[0].status == "done") {
$('#img2ImgImg').attr('src', response.jobs[0].img);
return;
}
if (response.jobs[0].status == "failed") {
return;
}
} else if (response.jobs[0].type == 'inpaint') {
$('#inpaintStatus').html(response.jobs[0].status);
$('#inpaintSeed').html("seed: " + response.jobs[0].seed);
if (response.jobs[0].status == "done") {
$('#inpaintImg').attr('src', response.jobs[0].img);
return;
}
if (response.jobs[0].status == "failed") {
return;
}
}
}
setTimeout(function () { waitForImage(apikeyVal, uuidValue); }, 1500); // refresh every second
},
error: function (xhr, status, error) {
// Handle error response
console.log(xhr.responseText);
$('#txt2ImgStatus').html('failed');
}
});
}
$(document).ready(function () {
console.log("--- csrf token set ---");
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$('input').each(function () {
var input = $(this);
var key = input.attr('id');
var value = localStorage.getItem(key);
if (value) {
input.val(value);
}
input.on('input', function () {
localStorage.setItem(key, input.val());
});
});
// Cache variable to store the selected image data for img2img
var imageData = null;
$("#copy-txt-to-img").click(function () {
data = $("#txt2ImgImg").attr("src");
if (data == null || data == "") {
alert("nothing found from txt-to-img result");
return;
}
imageData = data;
$("#reference-img").attr("src", imageData);
});
$("#copy-last-img").click(function () {
data = $("#img2ImgImg").attr("src");
if (data == null || data == "") {
alert("nothing found from img-to-img result");
return;
}
imageData = data;
$("#reference-img").attr("src", imageData);
});
$("#upload-img").click(function () {
var input = $("<input type='file' accept='image/*'>");
input.on("change", function () {
var reader = new FileReader();
reader.onload = function (e) {
imageData = e.target.result;
$("#reference-img").attr("src", imageData);
};
reader.readAsDataURL(input[0].files[0]);
});
input.click();
});
var activeLink = localStorage.getItem('activeLink') || $('.nav-link:first').attr('href');
// Set the active link as the current active link
$('.nav-link[href="' + activeLink + '"]').addClass('active');
$(activeLink).show();
$(".nav-link").click(function (e) {
e.preventDefault();
var target = $(this).attr("href"); // get the href value of the clicked link
// hide all card divs and show the corresponding one
$(".card-specific").hide();
$(".nav-link").removeClass("active");
$(this).addClass("active");
$(target).show();
localStorage.setItem('activeLink', target);
});
$('#newTxt2ImgJob').click(function (e) {
e.preventDefault(); // Prevent the default form submission
// Gather input field values
var apikeyVal = $('#apiKey').val();
var promptVal = $('#prompt').val();
var negPromptVal = $('#negPrompt').val();
var seedVal = $('#inputSeed').val();
if (seedVal == "0" || seedVal == "") {
seedVal = "0";
}
var guidanceScaleVal = parseFloat($('#inputGuidanceScale').val())
if (isNaN(guidanceScaleVal)) {
guidanceScaleVal = 12.5;
}
var stepsVal = parseInt($('#inputSteps').val());
if (isNaN(stepsVal)) {
stepsVal = 50;
}
var widthVal = parseInt($('#inputWidth').val());
if (isNaN(widthVal)) {
widthVal = 512;
}
var heightVal = parseInt($('#inputHeight').val());
if (isNaN(heightVal)) {
heightVal = 512;
}
if (promptVal == "") {
alert("missing prompt!");
return;
}
if (guidanceScaleVal < 1 || guidanceScaleVal > 30) {
alert("guidance scale must be between 1 and 30");
return;
}
if (widthVal < 8 || widthVal > 960) {
alert("width must be between 8 and 960!");
return;
}
if (widthVal % 8 != 0) {
alert("width must be divisible by 8!");
return;
}
if (heightVal < 8 || heightVal > 960) {
alert("height must be between 8 and 960!");
return;
}
if (heightVal % 8 != 0) {
alert("height must be divisible by 8!");
return;
}
if (stepsVal > 200 || stepsVal < 1) {
alert("steps value must be between 1 and 200!");
return;
}
$.ajax({
type: 'POST',
url: '/add_job',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({
'apikey': apikeyVal,
'type': 'txt',
'prompt': promptVal,
'seed': seedVal,
'steps': stepsVal,
'width': widthVal,
'height': heightVal,
'lang': $("#language option:selected").val(),
'guidance_scale': guidanceScaleVal,
'neg_prompt': negPromptVal
}),
success: function (response) {
console.log(response);
if (response.uuid) {
$('#txt2ImgJobUUID').val(response.uuid);
}
$('#txt2ImgStatus').html('submitting new job..');
waitForImage(apikeyVal, response.uuid);
},
error: function (xhr, status, error) {
// Handle error response
console.log(xhr.responseText);
$('#txt2ImgStatus').html('failed');
}
});
});
$('#newImg2ImgJob').click(function (e) {
e.preventDefault(); // Prevent the default form submission
if (imageData == null) {
alert("No image cached")
return;
}
// Gather input field values
var apikeyVal = $('#apiKey').val();
var promptVal = $('#prompt').val();
var negPromptVal = $('#negPrompt').val();
var seedVal = $('#inputSeed').val();
if (seedVal == "0" || seedVal == "") {
seedVal = "0";
}
var guidanceScaleVal = parseFloat($('#inputGuidanceScale').val())
if (isNaN(guidanceScaleVal)) {
guidanceScaleVal = 25.0;
}
var stepsVal = parseInt($('#inputSteps').val());
if (isNaN(stepsVal)) {
stepsVal = 50;
}
var widthVal = parseInt($('#inputWidth').val());
if (isNaN(widthVal)) {
widthVal = 512;
}
var heightVal = parseInt($('#inputHeight').val());
if (isNaN(heightVal)) {
heightVal = 512;
}
var strengthVal = parseFloat($('#inputStrength').val());
if (isNaN(strengthVal)) {
strengthVal = 0.5;
}
if (promptVal == "") {
alert("missing prompt!");
return;
}
if (guidanceScaleVal < 1 || guidanceScaleVal > 30) {
alert("guidance scale must be between 1 and 30");
return;
}
if (strengthVal < 0 || strengthVal > 1) {
alert("strength must be between 0 and 1");
return;
}
if (widthVal < 8 || widthVal > 960) {
alert("width must be between 8 and 960!");
return;
}
if (widthVal % 8 != 0) {
alert("width must be divisible by 8!");
return;
}
if (heightVal < 8 || heightVal > 960) {
alert("height must be between 8 and 960!");
return;
}
if (heightVal % 8 != 0) {
alert("height must be divisible by 8!");
return;
}
if (stepsVal > 200 || stepsVal < 1) {
alert("steps value must be between 1 and 200!");
return;
}
// Send POST request using Ajax
$.ajax({
type: 'POST',
url: '/add_job',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({
'apikey': apikeyVal,
'type': 'img',
'ref_img': imageData,
'prompt': promptVal,
'seed': seedVal,
'steps': stepsVal,
'width': widthVal,
'height': heightVal,
'lang': $("#language option:selected").val(),
'guidance_scale': guidanceScaleVal,
'strength': strengthVal,
'neg_prompt': negPromptVal
}),
success: function (response) {
console.log(response);
if (response.uuid) {
$('#img2ImgJobUUID').val(response.uuid);
}
$('#img2ImgStatus').html('submitting new job..');
waitForImage(apikeyVal, response.uuid);
},
error: function (xhr, status, error) {
// Handle error response
console.log(xhr.responseText);
$('#img2ImgStatus').html('failed');
}
});
});
$('#newInpaintingJob').click(function (e) {
e.preventDefault(); // Prevent the default form submission
if (inpaintOriginalImg == null) {
alert("No image cached")
return;
}
var canvas = $('#inpaint-img-mask')[0];
var ctx = canvas.getContext('2d');
var maskImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// Loop through the pixels and change the colors
for (var i = 0; i < maskImageData.data.length; i += 4) {
if (maskImageData.data[i + 3] == 0) { // If pixel is transparent, change to black
maskImageData.data[i] = 0;
maskImageData.data[i + 1] = 0;
maskImageData.data[i + 2] = 0;
maskImageData.data[i + 3] = 255;
} else { // If pixel is not transparent, change to white
maskImageData.data[i] = 255;
maskImageData.data[i + 1] = 255;
maskImageData.data[i + 2] = 255;
maskImageData.data[i + 3] = 255;
}
}
var tempCanvas = document.createElement('canvas'); // Create a new canvas element
tempCanvas.width = canvas.width; // Set the width of the new canvas to match the original canvas
tempCanvas.height = canvas.height; // Set the height of the new canvas to match the original canvas
var tempCtx = tempCanvas.getContext('2d');
tempCtx.putImageData(maskImageData, 0, 0); // Put modified image data onto the new canvas
var inpaintMaskImg = tempCanvas.toDataURL(); // Get the modified base64-encoded image data
// Gather input field values
var apikeyVal = $('#apiKey').val();
var promptVal = $('#prompt').val();
var negPromptVal = $('#negPrompt').val();
var seedVal = $('#inputSeed').val();
if (seedVal == "0" || seedVal == "") {
seedVal = "0";
}
var guidanceScaleVal = parseFloat($('#inputGuidanceScale').val())
if (isNaN(guidanceScaleVal)) {
guidanceScaleVal = 25.0;
}
var stepsVal = parseInt($('#inputSteps').val());
if (isNaN(stepsVal)) {
stepsVal = 50;
}
var widthVal = parseInt($('#inputWidth').val());
if (isNaN(widthVal)) {
widthVal = 512;
}
var heightVal = parseInt($('#inputHeight').val());
if (isNaN(heightVal)) {
heightVal = 512;
}
if (promptVal == "") {
alert("missing prompt!");
return;
}
if (guidanceScaleVal < 1 || guidanceScaleVal > 30) {
alert("guidance scale must be between 1 and 30");
return;
}
if (widthVal < 8 || widthVal > 960) {
alert("width must be between 8 and 960!");
return;
}
if (widthVal % 8 != 0) {
alert("width must be divisible by 8!");
return;
}
if (heightVal < 8 || heightVal > 960) {
alert("height must be between 8 and 960!");
return;
}
if (heightVal % 8 != 0) {
alert("height must be divisible by 8!");
return;
}
if (stepsVal > 200 || stepsVal < 1) {
alert("steps value must be between 1 and 200!");
return;
}
// Send POST request using Ajax
$.ajax({
type: 'POST',
url: '/add_job',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({
'apikey': apikeyVal,
'type': 'inpaint',
'ref_img': inpaintOriginalImg,
'mask_img': inpaintMaskImg,
'prompt': promptVal,
'seed': seedVal,
'steps': stepsVal,
'width': widthVal,
'height': heightVal,
'lang': $("#language option:selected").val(),
'guidance_scale': guidanceScaleVal,
'neg_prompt': negPromptVal
}),
success: function (response) {
console.log(response);
if (response.uuid) {
$('#inpaintJobUUID').val(response.uuid);
}
$('#inpaintStatus').html('submitting new job..');
waitForImage(apikeyVal, response.uuid);
},
error: function (xhr, status, error) {
// Handle error response
console.log(xhr.responseText);
$('#inpaintStatus').html('failed');
}
});
});
// Listen for changes to the select element
$("#language").change(function () {
// Get the newly selected value
var newLanguage = $(this).val();
// Store the selected value in cache
localStorage.setItem("selectedLanguage", newLanguage);
$("[data-" + newLanguage + "]").each(function () {
$(this).text($(this).data(newLanguage.toLowerCase()));
});
});
// Get the selected value from cache (if it exists)
var cachedLanguage = localStorage.getItem("selectedLanguage");
if (cachedLanguage) {
// Set the selected value
$("#language").val(cachedLanguage);
// Trigger a change event to update the text and store in cache
$("#language").change();
}
// Cache variable to store the selected image data for inpainting
var inpaintOriginalImg = null;
$("#copy-txt-to-img-inpaint").click(function () {
data = $("#txt2ImgImg").attr("src");
if (data == null || data == "") {
alert("nothing found from txt-to-img result");
return;
}
inpaintOriginalImg = data
$("#inpaint-img").attr("src", inpaintOriginalImg);
$("#inpaint-img").trigger("change");
});
$("#copy-last-img-inpaint").click(function () {
data = $("#img2ImgImg").attr("src");
if (data == null || data == "") {
alert("nothing found from img-to-img result");
return;
}
inpaintOriginalImg = data;
$("#inpaint-img").attr("src", inpaintOriginalImg);
$("#inpaint-img").trigger("change");
});
$("#upload-img-inpaint").click(function () {
var input = $("<input type='file' accept='image/*'>");
input.on("change", function () {
var reader = new FileReader();
reader.onload = function (e) {
inpaintOriginalImg = e.target.result;
$("#inpaint-img").attr("src", inpaintOriginalImg);
var img = new Image();
img.src = inpaintOriginalImg;
img.onload = function () {
$("#inpaint-img").trigger("change");
};
};
reader.readAsDataURL(input[0].files[0]);
});
input.click();
});
$("#inpaint-strike-size").on("input", function () {
$('#range-value').val($(this).val());
});
$('#range-value').val($('#inpaint-strike-size').val());
$("#inpaint-img").on("change", function () {
var src = $(this).attr("src");
$("#inpaint-img-for-mask").attr("src", src);
$("#inpaint-mask-canvas-container").html("<canvas id='inpaint-img-mask' width=" + $(this).width() + " height=" + $(this).height() + ">");
var options = {
graphics: {
firstPointSize: 0,
lineWidth: 10,
strokeStyle: 'black',
}
};
$sketcher = $('#inpaint-img-mask').sketchable(options);
$('#inpaint-reset').click(function () {
$sketcher.sketchable('clear');
});
$('#inpaint-undo').click(function () {
$sketcher.sketchable('memento.undo');
});
$('#inpaint-redo').click(function () {
$sketcher.sketchable('memento.redo');
});
$("#inpaint-strike-size").on("input", function () {
$sketcher.sketchable('config', { graphics: { lineWidth: $(this).val() } });
});
});
});
</script>
</body>
</html>