mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Fixes save to gallery including empty area, adds download and copy image
This commit is contained in:
parent
635e7da05d
commit
19322fc1ec
@ -165,20 +165,16 @@ class InvokeAIWebServer:
|
||||
|
||||
pil_image = Image.open(file_path)
|
||||
|
||||
# visible_image_bbox = pil_image.getbbox()
|
||||
# pil_image = pil_image.crop(visible_image_bbox)
|
||||
# pil_image.save(file_path)
|
||||
# if "cropVisible" in data and data["cropVisible"] == True:
|
||||
# visible_image_bbox = pil_image.getbbox()
|
||||
# pil_image = pil_image.crop(visible_image_bbox)
|
||||
# pil_image.save(file_path)
|
||||
if "cropVisible" in data and data["cropVisible"] == True:
|
||||
visible_image_bbox = pil_image.getbbox()
|
||||
pil_image = pil_image.crop(visible_image_bbox)
|
||||
pil_image.save(file_path)
|
||||
|
||||
(width, height) = pil_image.size
|
||||
|
||||
response = {
|
||||
"url": self.get_url_from_image_path(file_path),
|
||||
"mtime": mtime,
|
||||
# "bbox": visible_image_bbox,
|
||||
"width": width,
|
||||
"height": height,
|
||||
}
|
||||
@ -607,6 +603,12 @@ class InvokeAIWebServer:
|
||||
|
||||
actual_generation_mode = generation_parameters["generation_mode"]
|
||||
original_bounding_box = None
|
||||
|
||||
progress = Progress(generation_parameters=generation_parameters)
|
||||
|
||||
self.socketio.emit("progressUpdate", progress.to_formatted_dict())
|
||||
eventlet.sleep(0)
|
||||
|
||||
"""
|
||||
TODO:
|
||||
If a result image is used as an init image, and then deleted, we will want to be
|
||||
@ -658,8 +660,6 @@ class InvokeAIWebServer:
|
||||
initial_image, mask_image
|
||||
)
|
||||
|
||||
print(initial_image, mask_image)
|
||||
|
||||
"""
|
||||
Apply the mask to the init image, creating a "mask" image with
|
||||
transparency where inpainting should occur. This is the kind of
|
||||
@ -708,11 +708,6 @@ class InvokeAIWebServer:
|
||||
init_img_path = self.get_image_path_from_url(init_img_url)
|
||||
generation_parameters["init_img"] = init_img_path
|
||||
|
||||
progress = Progress(generation_parameters=generation_parameters)
|
||||
|
||||
self.socketio.emit("progressUpdate", progress.to_formatted_dict())
|
||||
eventlet.sleep(0)
|
||||
|
||||
def image_progress(sample, step):
|
||||
if self.canceled.is_set():
|
||||
raise CanceledException
|
||||
@ -967,6 +962,8 @@ class InvokeAIWebServer:
|
||||
eventlet.sleep(0)
|
||||
|
||||
progress.set_current_iteration(progress.current_iteration + 1)
|
||||
|
||||
print(generation_parameters)
|
||||
|
||||
self.generate.prompt2image(
|
||||
**generation_parameters,
|
||||
|
@ -78,7 +78,6 @@ const IAICanvasOutpaintingControls = () => {
|
||||
dispatch(
|
||||
mergeAndUploadCanvas({
|
||||
canvasImageLayerRef,
|
||||
saveToGallery: false,
|
||||
})
|
||||
);
|
||||
}}
|
||||
@ -89,7 +88,11 @@ const IAICanvasOutpaintingControls = () => {
|
||||
icon={<FaSave />}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
mergeAndUploadCanvas({ canvasImageLayerRef, saveToGallery: true })
|
||||
mergeAndUploadCanvas({
|
||||
canvasImageLayerRef,
|
||||
cropVisible: true,
|
||||
saveToGallery: true,
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@ -97,11 +100,29 @@ const IAICanvasOutpaintingControls = () => {
|
||||
aria-label="Copy Selection"
|
||||
tooltip="Copy Selection"
|
||||
icon={<FaCopy />}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
mergeAndUploadCanvas({
|
||||
canvasImageLayerRef,
|
||||
cropVisible: true,
|
||||
copyAfterSaving: true,
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<IAIIconButton
|
||||
aria-label="Download Selection"
|
||||
tooltip="Download Selection"
|
||||
icon={<FaDownload />}
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
mergeAndUploadCanvas({
|
||||
canvasImageLayerRef,
|
||||
cropVisible: true,
|
||||
downloadAfterSaving: true,
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
<ButtonGroup isAttached>
|
||||
|
34
frontend/src/features/canvas/util/copyImage.ts
Normal file
34
frontend/src/features/canvas/util/copyImage.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copies an image to the clipboard by drawing it to a canvas and then
|
||||
* calling toBlob() on the canvas.
|
||||
*/
|
||||
const copyImage = (url: string, width: number, height: number) => {
|
||||
const imageElement = document.createElement('img');
|
||||
|
||||
imageElement.addEventListener('load', () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const context = canvas.getContext('2d');
|
||||
|
||||
if (!context) return;
|
||||
|
||||
context.drawImage(imageElement, 0, 0);
|
||||
|
||||
canvas.toBlob((blob) => {
|
||||
blob &&
|
||||
navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
[blob.type]: blob,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
canvas.remove();
|
||||
imageElement.remove();
|
||||
});
|
||||
|
||||
imageElement.src = url;
|
||||
};
|
||||
|
||||
export default copyImage;
|
14
frontend/src/features/canvas/util/downloadFile.ts
Normal file
14
frontend/src/features/canvas/util/downloadFile.ts
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Downloads a file, given its URL.
|
||||
*/
|
||||
const downloadFile = (url: string) => {
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = '';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
a.remove();
|
||||
};
|
||||
|
||||
export default downloadFile;
|
@ -5,17 +5,28 @@ import { MutableRefObject } from 'react';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import layerToDataURL from './layerToDataURL';
|
||||
import downloadFile from './downloadFile';
|
||||
import copyImage from './copyImage';
|
||||
|
||||
export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
'canvas/mergeAndUploadCanvas',
|
||||
async (
|
||||
args: {
|
||||
canvasImageLayerRef: MutableRefObject<Konva.Layer | null>;
|
||||
saveToGallery: boolean;
|
||||
cropVisible?: boolean;
|
||||
saveToGallery?: boolean;
|
||||
downloadAfterSaving?: boolean;
|
||||
copyAfterSaving?: boolean;
|
||||
},
|
||||
thunkAPI
|
||||
) => {
|
||||
const { canvasImageLayerRef, saveToGallery } = args;
|
||||
const {
|
||||
canvasImageLayerRef,
|
||||
saveToGallery,
|
||||
downloadAfterSaving,
|
||||
cropVisible,
|
||||
copyAfterSaving,
|
||||
} = args;
|
||||
|
||||
const { getState } = thunkAPI;
|
||||
|
||||
@ -40,7 +51,7 @@ export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
dataURL,
|
||||
filename: 'merged_canvas.png',
|
||||
kind: saveToGallery ? 'result' : 'temp',
|
||||
cropVisible: saveToGallery,
|
||||
cropVisible,
|
||||
})
|
||||
);
|
||||
|
||||
@ -52,12 +63,15 @@ export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
const { url, mtime, width, height } =
|
||||
(await response.json()) as InvokeAI.ImageUploadResponse;
|
||||
|
||||
// const newBoundingBox = {
|
||||
// x: bbox[0],
|
||||
// y: bbox[1],
|
||||
// width: bbox[2],
|
||||
// height: bbox[3],
|
||||
// };
|
||||
if (downloadAfterSaving) {
|
||||
downloadFile(url);
|
||||
return;
|
||||
}
|
||||
|
||||
if (copyAfterSaving) {
|
||||
copyImage(url, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
const newImage: InvokeAI.Image = {
|
||||
uuid: uuidv4(),
|
||||
@ -72,7 +86,6 @@ export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
image: newImage,
|
||||
kind: saveToGallery ? 'merged_canvas' : 'temp_merged_canvas',
|
||||
originalBoundingBox,
|
||||
// newBoundingBox,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -29,7 +29,6 @@ export const uploadImage = createAsyncThunk(
|
||||
kind: 'init',
|
||||
})
|
||||
);
|
||||
// formData.append('kind', 'init');
|
||||
|
||||
const response = await fetch(window.location.origin + '/upload', {
|
||||
method: 'POST',
|
||||
@ -39,13 +38,6 @@ export const uploadImage = createAsyncThunk(
|
||||
const { url, mtime, width, height } =
|
||||
(await response.json()) as InvokeAI.ImageUploadResponse;
|
||||
|
||||
// const newBoundingBox = {
|
||||
// x: bbox[0],
|
||||
// y: bbox[1],
|
||||
// width: bbox[2],
|
||||
// height: bbox[3],
|
||||
// };
|
||||
|
||||
const newImage: InvokeAI.Image = {
|
||||
uuid: uuidv4(),
|
||||
url,
|
||||
|
Loading…
Reference in New Issue
Block a user