first commit
This commit is contained in:
245
plugins/openai_image_edit/js/edit.js
Normal file
245
plugins/openai_image_edit/js/edit.js
Normal file
@@ -0,0 +1,245 @@
|
||||
|
||||
const canvas = document.getElementById('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
const overlayCanvas = document.getElementById('overlayCanvas');
|
||||
const overlayCtx = overlayCanvas.getContext('2d');
|
||||
|
||||
const image = document.getElementById('image');
|
||||
|
||||
let drawing = false;
|
||||
let penSize = document.getElementById('penSize').value;
|
||||
let lastX = 0;
|
||||
let lastY = 0;
|
||||
|
||||
image.onload = drawImageOnCanvas;
|
||||
|
||||
function drawImageOnCanvas() {
|
||||
canvas.width = image.width
|
||||
canvas.height = image.height;
|
||||
|
||||
overlayCanvas.width = image.width
|
||||
overlayCanvas.height = image.height;
|
||||
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
|
||||
document.getElementById('canvas-container').style.visibility='visible';
|
||||
document.getElementById('toolbox').style.visibility='visible';
|
||||
CentralSpaceHideProcessing();
|
||||
HideThumbs(); // More visual space
|
||||
};
|
||||
|
||||
// Adjust pen size
|
||||
document.getElementById('penSize').addEventListener('input', function () {
|
||||
penSize = this.value;
|
||||
});
|
||||
|
||||
// Start drawing
|
||||
canvas.addEventListener('mousedown', (e) => {
|
||||
drawing = true;
|
||||
[lastX, lastY] = getMousePos(e);
|
||||
draw(e);
|
||||
});
|
||||
|
||||
canvas.addEventListener('mouseup', () => drawing = false);
|
||||
canvas.addEventListener('mousemove', draw);
|
||||
|
||||
function draw(e) {
|
||||
|
||||
if (document.getElementById('penSize').disabled) {return false;}
|
||||
|
||||
const [x, y] = getMousePos(e);
|
||||
const mode = document.getElementById('editMode').value;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Clear the previous brush preview
|
||||
overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
|
||||
|
||||
if (!drawing)
|
||||
{
|
||||
// Not drawing, draw a pen preview only.
|
||||
// Draw a circle at the current mouse position
|
||||
|
||||
// Set dashed pattern for visibility on any background
|
||||
overlayCtx.setLineDash([5, 5]); // Alternating dash pattern
|
||||
overlayCtx.lineWidth = 2;
|
||||
|
||||
// Draw a white circle outline
|
||||
overlayCtx.strokeStyle = 'white';
|
||||
overlayCtx.beginPath();
|
||||
overlayCtx.arc(x, y, penSize / 2, 0, Math.PI * 2);
|
||||
overlayCtx.stroke();
|
||||
|
||||
// Draw a black circle outline over the white to create contrast
|
||||
overlayCtx.strokeStyle = 'black';
|
||||
overlayCtx.lineWidth = 1;
|
||||
overlayCtx.beginPath();
|
||||
overlayCtx.arc(x, y, penSize / 2, 0, Math.PI * 2);
|
||||
overlayCtx.stroke();
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.lineWidth = penSize;
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
|
||||
if (mode=="clone" || mode=="white" || mode=="black")
|
||||
{
|
||||
// Add shadow for blur effect
|
||||
ctx.lineWidth = penSize/3;
|
||||
ctx.shadowColor = 'black'; // Set shadow color to match stroke
|
||||
ctx.shadowBlur = penSize/2; // Increase this value for stronger blur
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(lastX, lastY);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
|
||||
[lastX, lastY] = [x, y];
|
||||
}
|
||||
|
||||
// Get mouse position relative to the canvas
|
||||
function getMousePos(e) {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
return [
|
||||
e.clientX - rect.left,
|
||||
e.clientY - rect.top
|
||||
];
|
||||
}
|
||||
|
||||
// Hide the brush preview when the mouse leaves the main canvas
|
||||
canvas.addEventListener('mouseleave', () => {
|
||||
overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
|
||||
drawing=false;
|
||||
});
|
||||
|
||||
// Submit canvas as mask
|
||||
document.getElementById('submitBtn').addEventListener('click', async () => {
|
||||
|
||||
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
const tempCtx = tempCanvas.getContext('2d');
|
||||
tempCanvas.width = 1024;
|
||||
tempCanvas.height = 1024;
|
||||
tempCtx.drawImage(canvas, 0, 0);
|
||||
|
||||
const mask = tempCanvas.toDataURL('image/png');
|
||||
const prompt = document.getElementById('prompt').value;
|
||||
|
||||
CentralSpaceShowProcessing(0,defaultLoadingMessage);
|
||||
|
||||
// Send mask and image to the backend via AJAX
|
||||
|
||||
// Prepare form data
|
||||
const formData = new URLSearchParams({
|
||||
...csrf_pair,
|
||||
mask: mask,
|
||||
imageType: document.getElementById('downloadType').value,
|
||||
mode: document.getElementById('editMode').value,
|
||||
prompt: prompt,
|
||||
ajax: true
|
||||
});
|
||||
|
||||
const response = await fetch(submit_url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const result = await response.json(); // Parse the response as JSON
|
||||
|
||||
// Check if a valid image URL is returned
|
||||
if (result.image_base64) {
|
||||
|
||||
const base64Image = result.image_base64; // Extract the base64 image data
|
||||
|
||||
// Update the image src behind the canvas with the new one
|
||||
image.src = `data:image/png;base64,${base64Image}`;
|
||||
|
||||
// Redraw the canvas with the new image once it loads
|
||||
image.onload = () => {
|
||||
|
||||
// I have no idea why this is necessary or why it does anything, but without it the following drawImage() fails to draw anything.
|
||||
canvas.width = canvas.width;
|
||||
canvas.height = canvas.height;
|
||||
|
||||
ctx.drawImage(image, 0, 0); // Draw new image
|
||||
|
||||
document.getElementById('downloadOptions').style.visibility='visible';
|
||||
};
|
||||
} else {
|
||||
console.error('Failed to get a valid image URL from OpenAI.');
|
||||
styledalert('OpenAI',result.error.message);
|
||||
}
|
||||
CentralSpaceHideProcessing();
|
||||
});
|
||||
|
||||
// Get the mode selector and add an event listener
|
||||
document.getElementById('editMode').addEventListener('change', () => {
|
||||
const mode = document.getElementById('editMode').value;
|
||||
const brush = document.getElementById('penSize');
|
||||
const prompt = document.getElementById('prompt');
|
||||
brush.disabled=(mode=='generate' || mode=='variation');
|
||||
prompt.disabled=(mode=='white' || mode=='black' || mode=='variation');
|
||||
});
|
||||
|
||||
|
||||
// Get the download button and add an event listener
|
||||
document.getElementById('downloadBtn').addEventListener('click', () => {
|
||||
// Convert the canvas content to a data URL (PNG format)
|
||||
const dataURL = canvas.toDataURL(document.getElementById('downloadType').value);
|
||||
const downloadAction=document.getElementById('downloadAction').value;
|
||||
|
||||
if (downloadAction=='download')
|
||||
{
|
||||
// Download the file (or really, save, as it's already on the user's system)
|
||||
|
||||
// Create a temporary link element
|
||||
const link = document.createElement('a');
|
||||
link.href = dataURL;
|
||||
link.download = 'ai_edited.' + document.getElementById('downloadType').value.split('/')[1]; // The name of the downloaded image
|
||||
|
||||
// Programmatically click the link to trigger the download
|
||||
link.click();
|
||||
}
|
||||
|
||||
if (downloadAction=='alternative' || downloadAction=='new')
|
||||
{
|
||||
// Save as alternative file
|
||||
CentralSpaceShowProcessing(0);
|
||||
|
||||
// Prepare form data
|
||||
const formData = new URLSearchParams({
|
||||
...csrf_pair,
|
||||
ajax: true,
|
||||
imageData: dataURL,
|
||||
imageType: document.getElementById('downloadType').value
|
||||
});
|
||||
|
||||
fetch(downloadAction=='alternative' ? alternative_url : save_new_url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
console.log('Image submitted successfully:', result);
|
||||
|
||||
if (downloadAction=='alternative')
|
||||
{
|
||||
window.location.href=view_url;
|
||||
}
|
||||
else
|
||||
{
|
||||
window.location.href=view_new_url + result['resource'];
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Error submitting image:' + error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
Reference in New Issue
Block a user