Adds Save to Gallery button to staging toolbar

This commit is contained in:
psychedelicious 2022-11-20 20:23:35 +11:00 committed by blessedcoolant
parent d27d92325d
commit e1e978b423
5 changed files with 77 additions and 7 deletions

View File

@ -32,9 +32,10 @@ opt = Args()
args = opt.parse_args() args = opt.parse_args()
# Set the root directory for static files and relative paths # Set the root directory for static files and relative paths
args.root_dir = os.path.expanduser(args.root_dir or '..') args.root_dir = os.path.expanduser(args.root_dir or "..")
if not os.path.isabs(args.outdir): if not os.path.isabs(args.outdir):
args.outdir=os.path.join(args.root_dir,args.outdir) args.outdir = os.path.join(args.root_dir, args.outdir)
class InvokeAIWebServer: class InvokeAIWebServer:
def __init__(self, generate, gfpgan, codeformer, esrgan) -> None: def __init__(self, generate, gfpgan, codeformer, esrgan) -> None:
@ -80,7 +81,9 @@ class InvokeAIWebServer:
socketio_args["cors_allowed_origins"] = opt.cors socketio_args["cors_allowed_origins"] = opt.cors
self.app = Flask( self.app = Flask(
__name__, static_url_path="", static_folder=os.path.join(args.root_dir,"frontend/dist") __name__,
static_url_path="",
static_folder=os.path.join(args.root_dir, "frontend/dist"),
) )
self.socketio = SocketIO(self.app, **socketio_args) self.socketio = SocketIO(self.app, **socketio_args)
@ -308,6 +311,50 @@ class InvokeAIWebServer:
traceback.print_exc() traceback.print_exc()
print("\n") print("\n")
@socketio.on("requestSaveStagingAreaImageToGallery")
def save_temp_image_to_gallery(url):
try:
image_path = self.get_image_path_from_url(url)
new_path = os.path.join(self.result_path, os.path.basename(image_path))
shutil.copy2(image_path, new_path)
if os.path.splitext(new_path)[1] == ".png":
metadata = retrieve_metadata(new_path)
else:
metadata = {}
pil_image = Image.open(new_path)
(width, height) = pil_image.size
thumbnail_path = save_thumbnail(
pil_image, os.path.basename(new_path), self.thumbnail_image_path
)
image_array = [
{
"url": self.get_url_from_image_path(new_path),
"thumbnail": self.get_url_from_image_path(thumbnail_path),
"mtime": os.path.getmtime(new_path),
"metadata": metadata,
"width": width,
"height": height,
"category": "result",
}
]
socketio.emit(
"galleryImages",
{"images": image_array, "category": "result"},
)
except Exception as e:
self.socketio.emit("error", {"message": (str(e))})
print("\n")
traceback.print_exc()
print("\n")
@socketio.on("requestLatestImages") @socketio.on("requestLatestImages")
def handle_request_latest_images(category, latest_mtime): def handle_request_latest_images(category, latest_mtime):
try: try:
@ -431,7 +478,7 @@ class InvokeAIWebServer:
} }
) )
except: except:
print(f'>> Unable to load {path}') print(f">> Unable to load {path}")
socketio.emit("error", {"message": f"Unable to load {path}"}) socketio.emit("error", {"message": f"Unable to load {path}"})
socketio.emit( socketio.emit(

View File

@ -3,7 +3,6 @@ import { GalleryCategory } from 'features/gallery/store/gallerySlice';
import { InvokeTabName } from 'features/tabs/components/InvokeTabs'; import { InvokeTabName } from 'features/tabs/components/InvokeTabs';
import * as InvokeAI from 'app/invokeai'; import * as InvokeAI from 'app/invokeai';
/** /**
* We can't use redux-toolkit's createSlice() to make these actions, * We can't use redux-toolkit's createSlice() to make these actions,
* because they have no associated reducer. They only exist to dispatch * because they have no associated reducer. They only exist to dispatch
@ -26,8 +25,6 @@ export const requestNewImages = createAction<GalleryCategory>(
export const cancelProcessing = createAction<undefined>( export const cancelProcessing = createAction<undefined>(
'socketio/cancelProcessing' 'socketio/cancelProcessing'
); );
// export const uploadImage = createAction<InvokeAI.UploadImagePayload>('socketio/uploadImage');
// export const uploadMaskImage = createAction<File>('socketio/uploadMaskImage');
export const requestSystemConfig = createAction<undefined>( export const requestSystemConfig = createAction<undefined>(
'socketio/requestSystemConfig' 'socketio/requestSystemConfig'
@ -36,3 +33,7 @@ export const requestSystemConfig = createAction<undefined>(
export const requestModelChange = createAction<string>( export const requestModelChange = createAction<string>(
'socketio/requestModelChange' 'socketio/requestModelChange'
); );
export const saveStagingAreaImageToGallery = createAction<string>(
'socketio/saveStagingAreaImageToGallery'
);

View File

@ -171,6 +171,9 @@ const makeSocketIOEmitters = (
dispatch(modelChangeRequested()); dispatch(modelChangeRequested());
socketio.emit('requestModelChange', modelName); socketio.emit('requestModelChange', modelName);
}, },
emitSaveStagingAreaImageToGallery: (url: string) => {
socketio.emit('requestSaveStagingAreaImageToGallery', url)
}
}; };
}; };

View File

@ -58,6 +58,7 @@ export const socketioMiddleware = () => {
emitCancelProcessing, emitCancelProcessing,
emitRequestSystemConfig, emitRequestSystemConfig,
emitRequestModelChange, emitRequestModelChange,
emitSaveStagingAreaImageToGallery,
} = makeSocketIOEmitters(store, socketio); } = makeSocketIOEmitters(store, socketio);
/** /**
@ -163,6 +164,11 @@ export const socketioMiddleware = () => {
emitRequestModelChange(action.payload); emitRequestModelChange(action.payload);
break; break;
} }
case 'socketio/saveStagingAreaImageToGallery': {
emitSaveStagingAreaImageToGallery(action.payload);
break;
}
} }
next(action); next(action);

View File

@ -10,6 +10,7 @@ import {
FaCheck, FaCheck,
FaEye, FaEye,
FaEyeSlash, FaEyeSlash,
FaSave,
FaTrash, FaTrash,
} from 'react-icons/fa'; } from 'react-icons/fa';
import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { canvasSelector } from 'features/canvas/store/canvasSelectors';
@ -22,6 +23,7 @@ import {
setShouldShowStagingOutline, setShouldShowStagingOutline,
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { saveStagingAreaImageToGallery } from 'app/socketio/actions';
const selector = createSelector( const selector = createSelector(
[canvasSelector], [canvasSelector],
@ -151,6 +153,17 @@ const IAICanvasStagingAreaToolbar = () => {
} }
data-selected={true} data-selected={true}
/> />
<IAIIconButton
tooltip="Save to Gallery"
aria-label="Save to Gallery"
icon={<FaSave />}
onClick={() =>
dispatch(
saveStagingAreaImageToGallery(currentStagingAreaImage.image.url)
)
}
data-selected={true}
/>
<IAIIconButton <IAIIconButton
tooltip="Discard All" tooltip="Discard All"
aria-label="Discard All" aria-label="Discard All"