Fix image upload

This commit is contained in:
space-nuko
2023-05-13 15:14:52 -05:00
parent f66df94c36
commit 0656ae1d3a
5 changed files with 92 additions and 45 deletions

View File

@@ -339,6 +339,7 @@
border-bottom: 1px solid var(--block-border-color); border-bottom: 1px solid var(--block-border-color);
border-top: 1px solid var(--table-border-color); border-top: 1px solid var(--table-border-color);
background: var(--panel-background-fill); background: var(--panel-background-fill);
max-height: 14rem;
&:hover:not(:has(img:hover)) { &:hover:not(:has(img:hover)) {
cursor: pointer; cursor: pointer;
@@ -387,6 +388,7 @@
column-gap: 1px; column-gap: 1px;
row-gap: 1px; row-gap: 1px;
vertical-align: top; vertical-align: top;
flex: 1 1 40%;
img { img {
aspect-ratio: 1 / 1; aspect-ratio: 1 / 1;

View File

@@ -25,13 +25,13 @@
let _value: GradioFileData[] | null = null; let _value: GradioFileData[] | null = null;
const root = "comf" const root = "comf"
const root_url = "https//ComfyUI!" const root_url = "https//ComfyUI!"
let uploaded: boolean = false;
const dispatch = createEventDispatcher<{ const dispatch = createEventDispatcher<{
change: GalleryOutputEntry[]; change: GalleryOutputEntry[];
uploading: undefined; uploading: undefined;
uploaded: GalleryOutputEntry[]; uploaded: GalleryOutputEntry[];
upload_error: any; upload_error: any;
load: undefined;
clear: undefined; clear: undefined;
}>(); }>();
@@ -58,10 +58,6 @@
dispatch("clear") dispatch("clear")
} }
function onLoad() {
dispatch("load")
}
interface GradioUploadResponse { interface GradioUploadResponse {
error?: string; error?: string;
files?: Array<GalleryOutputEntry>; files?: Array<GalleryOutputEntry>;
@@ -114,7 +110,8 @@
} }
$: { $: {
if (JSON.stringify(_value) !== JSON.stringify(old_value)) { if (JSON.stringify(_value) !== JSON.stringify(old_value) || uploaded) {
uploaded = false;
pending_upload = true; pending_upload = true;
old_value = _value; old_value = _value;
@@ -128,11 +125,14 @@
if (allBlobs == null || allBlobs.length === 0) { if (allBlobs == null || allBlobs.length === 0) {
_value = null; _value = null;
value = null;
onChange(); onChange();
pending_upload = false; pending_upload = false;
} }
else if (!allBlobs.every(b => b != null)) { else if (!allBlobs.every(b => b != null)) {
_value = null; _value = null;
value = null;
onChange();
pending_upload = false; pending_upload = false;
} }
else { else {
@@ -155,7 +155,7 @@
} }
value = response.files; value = response.files;
dispatch("change") dispatch("change", value)
dispatch("uploaded", value) dispatch("uploaded", value)
}). }).
catch(err => { catch(err => {
@@ -166,26 +166,22 @@
} }
async function handle_upload({ detail }: CustomEvent<GradioFileData | Array<GradioFileData>>) { async function handle_upload({ detail }: CustomEvent<GradioFileData | Array<GradioFileData>>) {
// Received Gradio-format file data from the Upload component.
// In the reactive block above it will be uploaded to ComfyUI.
_value = Array.isArray(detail) ? detail : [detail]; _value = Array.isArray(detail) ? detail : [detail];
await tick(); uploaded = true;
dispatch("change")
dispatch("load")
} }
function handle_clear(_e: CustomEvent<null>) { function handle_clear(_e: CustomEvent<null>) {
_value = null; _value = null;
value = []; value = [];
dispatch("change") dispatch("change", value)
dispatch("clear") dispatch("clear")
} }
function convertGradioUpload(e: CustomEvent<GradioFileData[]>) { function convertGradioUpload(e: CustomEvent<GradioFileData[]>) {
_value = e.detail _value = e.detail
} }
function convertNodeValue(nodeValue: GalleryOutputEntry[]): GradioFileData[] {
return nodeValue.map(convertComfyOutputEntryToGradio);
}
</script> </script>
<div class="image-upload" {style}> <div class="image-upload" {style}>

View File

@@ -913,16 +913,34 @@ export class ComfyImageUploadNode extends ComfyWidgetNode<GalleryOutputEntry[]>
override svelteComponentType = ImageUploadWidget; override svelteComponentType = ImageUploadWidget;
override defaultValue = []; override defaultValue = [];
override outputIndex = null; override outputIndex = null;
override changedIndex = 3; override changedIndex = 4;
override storeActionName = "store"; override storeActionName = "store";
override saveUserState = false; override saveUserState = false;
imageSize: Vector2 = [1, 1]; imageSize: Vector2 = [0, 0];
constructor(name?: string) { constructor(name?: string) {
super(name, []) super(name, [])
} }
override onExecute(param: any, options: object) {
super.onExecute(param, options);
const value = get(this.value)
if (value.length > 0) {
this.setOutputData(0, value[0].filename) // TODO when ComfyUI LoadImage supports loading an image batch
this.setOutputData(1, this.imageSize[0])
this.setOutputData(2, this.imageSize[1])
this.setOutputData(3, value.length)
}
else {
this.setOutputData(0, "")
this.setOutputData(1, 0)
this.setOutputData(2, 0)
this.setOutputData(3, 0)
}
}
override parseValue(value: any): GalleryOutputEntry[] { override parseValue(value: any): GalleryOutputEntry[] {
if (value == null) if (value == null)
return [] return []
@@ -949,24 +967,6 @@ export class ComfyImageUploadNode extends ComfyWidgetNode<GalleryOutputEntry[]>
return [] return []
} }
override onExecute(param: any, options: object) {
super.onExecute(param, options);
const value = get(this.value)
if (value.length > 0) {
this.setOutputData(0, value[0].filename) // TODO when ComfyUI LoadImage supports loading an image batch
this.setOutputData(1, this.imageSize[0])
this.setOutputData(2, this.imageSize[1])
this.setOutputData(3, value.length)
}
else {
this.setOutputData(0, "")
this.setOutputData(1, 1)
this.setOutputData(2, 1)
this.setOutputData(3, 0)
}
}
override formatValue(value: GalleryOutputEntry[]): string { override formatValue(value: GalleryOutputEntry[]): string {
return `Images: ${value?.length || 0}` return `Images: ${value?.length || 0}`
} }
@@ -996,13 +996,18 @@ export class ComfyImageEditorNode extends ComfyWidgetNode<GalleryOutputEntry[]>
{ name: "store", type: BuiltInSlotType.ACTION } { name: "store", type: BuiltInSlotType.ACTION }
], ],
outputs: [ outputs: [
{ name: "filename", type: "string" }, // TODO support batches
{ name: "width", type: "number" },
{ name: "height", type: "number" },
{ name: "image_count", type: "number" },
{ name: "changed", type: BuiltInSlotType.EVENT },
] ]
} }
override svelteComponentType = ImageEditorWidget; override svelteComponentType = ImageEditorWidget;
override defaultValue: GalleryOutputEntry[] = []; override defaultValue: GalleryOutputEntry[] = [];
override outputIndex = null; override outputIndex = null;
override changedIndex = null; override changedIndex = 4;
override storeActionName = "store"; override storeActionName = "store";
override saveUserState = false; override saveUserState = false;
@@ -1010,7 +1015,25 @@ export class ComfyImageEditorNode extends ComfyWidgetNode<GalleryOutputEntry[]>
super(name, []) super(name, [])
} }
_value = null; imageSize: Vector2 = [0, 0];
override onExecute(param: any, options: object) {
super.onExecute(param, options);
const value = get(this.value)
if (value.length > 0) {
this.setOutputData(0, value[0].filename) // TODO when ComfyUI LoadImage supports loading an image batch
this.setOutputData(1, this.imageSize[0])
this.setOutputData(2, this.imageSize[1])
this.setOutputData(3, value.length)
}
else {
this.setOutputData(0, "")
this.setOutputData(1, 0)
this.setOutputData(2, 0)
this.setOutputData(3, 0)
}
}
override parseValue(value: any): GalleryOutputEntry[] { override parseValue(value: any): GalleryOutputEntry[] {
if (value == null) if (value == null)

View File

@@ -18,15 +18,22 @@
let node: ComfyImageEditorNode | null = null; let node: ComfyImageEditorNode | null = null;
let nodeValue: Writable<GalleryOutputEntry[]> | null = null; let nodeValue: Writable<GalleryOutputEntry[]> | null = null;
let attrsChanged: Writable<number> | null = null; let attrsChanged: Writable<number> | null = null;
let leftUrl: string = ""
let rightUrl: string = ""
let imgElem: HTMLImageElement | null = null
let imgWidth: number = 0; let imgWidth: number = 0;
let imgHeight: number = 0; let imgHeight: number = 0;
$: widget && setNodeValue(widget); $: widget && setNodeValue(widget);
$: if (!(node && $nodeValue && $nodeValue.length > 0)) {
node.imageSize = [0, 0]
}
else if (imgWidth > 0 && imgHeight > 0) {
node.imageSize = [imgWidth, imgHeight]
}
else {
node.imageSize = [0, 0]
}
function setNodeValue(widget: WidgetLayout) { function setNodeValue(widget: WidgetLayout) {
if (widget) { if (widget) {
node = widget.node as ComfyImageEditorNode node = widget.node as ComfyImageEditorNode
@@ -224,7 +231,6 @@
<ImageUpload value={$nodeValue} <ImageUpload value={$nodeValue}
bind:imgWidth bind:imgWidth
bind:imgHeight bind:imgHeight
bind:imgElem
fileCount={"single"} fileCount={"single"}
elem_classes={[]} elem_classes={[]}
style={""} style={""}

View File

@@ -3,6 +3,7 @@
import type { WidgetLayout } from "$lib/stores/layoutState"; import type { WidgetLayout } from "$lib/stores/layoutState";
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import type { ComfyGalleryNode, ComfyImageUploadNode, GalleryOutputEntry, MultiImageData } from "$lib/nodes/ComfyWidgetNodes"; import type { ComfyGalleryNode, ComfyImageUploadNode, GalleryOutputEntry, MultiImageData } from "$lib/nodes/ComfyWidgetNodes";
import notify from "$lib/notify";
export let widget: WidgetLayout | null = null; export let widget: WidgetLayout | null = null;
export let isMobile: boolean = false; export let isMobile: boolean = false;
@@ -32,11 +33,27 @@
} }
}; };
function onUploading() {
console.warn("ONUPLOAD!!!")
$nodeValue = []
}
function onChange(e: CustomEvent<GalleryOutputEntry[]>) { function onChange(e: CustomEvent<GalleryOutputEntry[]>) {
console.warn("ONCHANGE!!!", e.detail) console.warn("ONCHANGE!!!", e.detail)
$nodeValue = e.detail || [] $nodeValue = e.detail || []
} }
function onUploaded(e: CustomEvent<GalleryOutputEntry[]>) {
console.warn("ONUPLOADED!!!", e.detail)
$nodeValue = e.detail || []
}
function onUploadError(e: CustomEvent<any>) {
console.warn("ONUPLOADERRO!!!", e.detail)
notify(`Error uploading image to ComfyUI: ${e.detail}`)
$nodeValue = []
}
function onClear(e: CustomEvent<GalleryOutputEntry[]>) { function onClear(e: CustomEvent<GalleryOutputEntry[]>) {
console.warn("ONCLEAR!!!", e.detail) console.warn("ONCLEAR!!!", e.detail)
$nodeValue = [] $nodeValue = []
@@ -44,16 +61,19 @@
</script> </script>
<div class="wrapper gradio-file comfy-image-upload" style={widget.attrs.style}> <div class="wrapper gradio-file comfy-image-upload" style={widget.attrs.style}>
{#if widget && node && nodeValue} {#if widget && node}
<ImageUpload value={$nodeValue} <ImageUpload value={$nodeValue || []}
bind:imgWidth bind:imgWidth
bind:imgHeight bind:imgHeight
bind:fileCount={node.properties.fileCount} bind:fileCount={node.properties.fileCount}
elem_classes={widget.attrs.classes.split(",")} elem_classes={widget.attrs.classes.split(",")}
style={widget.attrs.style} style={widget.attrs.style}
label={widget.attrs.title} label={widget.attrs.title}
on:change={onChange} on:uploading={onUploading}
on:clear={onClear}/> on:uploaded={onUploaded}
on:upload_error={onUploadError}
on:clear={onClear}
on:change={onChange}/>
{/if} {/if}
</div> </div>