Thumbnail option for gallery/queue images
This commit is contained in:
139
src/lib/utils.ts
139
src/lib/utils.ts
@@ -9,6 +9,7 @@ import workflowState, { type WorkflowReceiveOutputTargets } from "./stores/workf
|
||||
import { ImageViewer } from "./ImageViewer";
|
||||
import configState from "$lib/stores/configState";
|
||||
import SendOutputModal, { type SendOutputModalResult } from "$lib/components/modal/SendOutputModal.svelte";
|
||||
import { OutputThumbnailsMode } from "./stores/configDefs";
|
||||
|
||||
export function clamp(n: number, min: number, max: number): number {
|
||||
if (max <= min)
|
||||
@@ -300,31 +301,80 @@ export function convertComfyOutputToGradio(output: SerializedPromptOutput): Grad
|
||||
|
||||
export function convertComfyOutputEntryToGradio(r: ComfyImageLocation): GradioFileData {
|
||||
const url = configState.getBackendURL();
|
||||
const params = new URLSearchParams(r)
|
||||
const fileData: GradioFileData = {
|
||||
name: r.filename,
|
||||
orig_name: r.filename,
|
||||
is_file: false,
|
||||
data: url + "/view?" + params
|
||||
data: convertComfyOutputToComfyURL(r)
|
||||
}
|
||||
return fileData
|
||||
}
|
||||
|
||||
export function convertComfyOutputToComfyURL(output: string | ComfyImageLocation): string {
|
||||
function convertComfyPreviewTypeToString(preview: ComfyImagePreviewType): string {
|
||||
const arr = []
|
||||
switch (preview.format) {
|
||||
case ComfyImagePreviewFormat.JPEG:
|
||||
arr.push("jpeg")
|
||||
break;
|
||||
case ComfyImagePreviewFormat.WebP:
|
||||
default:
|
||||
arr.push("webp")
|
||||
break;
|
||||
}
|
||||
|
||||
arr.push(String(preview.quality))
|
||||
|
||||
return arr.join(";")
|
||||
}
|
||||
|
||||
export function convertComfyOutputToComfyURL(output: string | ComfyImageLocation, thumbnail: boolean = false): string {
|
||||
if (typeof output === "string")
|
||||
return output;
|
||||
|
||||
const params = new URLSearchParams(output)
|
||||
const paramsObj = {
|
||||
filename: output.filename,
|
||||
subfolder: output.subfolder,
|
||||
type: output.type
|
||||
}
|
||||
|
||||
if (thumbnail) {
|
||||
let doThumbnail: boolean;
|
||||
|
||||
switch (get(configState).outputThumbnails) {
|
||||
case OutputThumbnailsMode.AlwaysFullSize:
|
||||
doThumbnail = false;
|
||||
break;
|
||||
case OutputThumbnailsMode.AlwaysThumbnail:
|
||||
doThumbnail = true;
|
||||
break;
|
||||
case OutputThumbnailsMode.Auto:
|
||||
default:
|
||||
// TODO detect colab, etc.
|
||||
if (isMobileBrowser(navigator.userAgent)) {
|
||||
doThumbnail = true;
|
||||
}
|
||||
else {
|
||||
doThumbnail = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (doThumbnail) {
|
||||
output.preview = {
|
||||
format: ComfyImagePreviewFormat.WebP,
|
||||
quality: 80
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (output.preview != null)
|
||||
paramsObj["preview"] = convertComfyPreviewTypeToString(output.preview)
|
||||
|
||||
const params = new URLSearchParams(paramsObj)
|
||||
const url = configState.getBackendURL();
|
||||
return url + "/view?" + params
|
||||
}
|
||||
|
||||
export function convertGradioFileDataToComfyURL(image: GradioFileData, type: ComfyUploadImageType = "input"): string {
|
||||
const baseUrl = configState.getBackendURL();
|
||||
const params = new URLSearchParams({ filename: image.name, subfolder: "", type })
|
||||
return `${baseUrl}/view?${params}`
|
||||
}
|
||||
|
||||
export function convertGradioFileDataToComfyOutput(fileData: GradioFileData, type: ComfyUploadImageType = "input"): ComfyImageLocation {
|
||||
if (!fileData.is_file)
|
||||
throw "Can't convert blob data to comfy output!"
|
||||
@@ -336,18 +386,6 @@ export function convertGradioFileDataToComfyOutput(fileData: GradioFileData, typ
|
||||
}
|
||||
}
|
||||
|
||||
export function convertFilenameToComfyURL(filename: string,
|
||||
subfolder: string = "",
|
||||
type: "input" | "output" | "temp" = "output"): string {
|
||||
const params = new URLSearchParams({
|
||||
filename,
|
||||
subfolder,
|
||||
type
|
||||
})
|
||||
const url = configState.getBackendURL();
|
||||
return url + "/view?" + params
|
||||
}
|
||||
|
||||
export function jsonToJsObject(json: string): string {
|
||||
// Try to parse, to see if it's real JSON
|
||||
JSON.parse(json);
|
||||
@@ -413,6 +451,16 @@ export interface SerializedPromptOutput {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export enum ComfyImagePreviewFormat {
|
||||
WebP = "webp",
|
||||
JPEG = "jpeg",
|
||||
}
|
||||
|
||||
export type ComfyImagePreviewType = {
|
||||
format: ComfyImagePreviewFormat,
|
||||
quality: number
|
||||
}
|
||||
|
||||
/** Raw output entry as received from ComfyUI's backend */
|
||||
export type ComfyImageLocation = {
|
||||
/* Filename with extension in the subfolder. */
|
||||
@@ -420,7 +468,19 @@ export type ComfyImageLocation = {
|
||||
/* Subfolder in the containing folder. */
|
||||
subfolder: string,
|
||||
/* Base ComfyUI folder where the image is located. */
|
||||
type: ComfyUploadImageType
|
||||
type: ComfyUploadImageType,
|
||||
/*
|
||||
* Preview information
|
||||
*
|
||||
* "format;quality"
|
||||
*
|
||||
* ex)
|
||||
* webp;50 -> webp, quality 50
|
||||
* webp;50 -> webp, quality 50
|
||||
* jpeg;80 -> rgb, jpeg, quality 80
|
||||
*
|
||||
*/
|
||||
preview?: ComfyImagePreviewType
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -544,27 +604,54 @@ export function comfyBoxImageToComfyURL(image: ComfyBoxImageMetadata): string {
|
||||
return convertComfyOutputToComfyURL(image.comfyUIFile)
|
||||
}
|
||||
|
||||
function parseComfyUIPreviewType(previewStr: string): ComfyImagePreviewType {
|
||||
let split = previewStr.split(";")
|
||||
let format = ComfyImagePreviewFormat.WebP;
|
||||
if (split[0] === "webp")
|
||||
format = ComfyImagePreviewFormat.WebP;
|
||||
else if (split[0] === "jpeg")
|
||||
format = ComfyImagePreviewFormat.JPEG;
|
||||
|
||||
let quality = parseInt(split[0])
|
||||
if (isNaN(quality))
|
||||
quality = 80
|
||||
|
||||
return { format, quality }
|
||||
}
|
||||
|
||||
export function comfyURLToComfyFile(urlString: string): ComfyImageLocation | null {
|
||||
const url = new URL(urlString);
|
||||
const params = new URLSearchParams(url.search);
|
||||
const filename = params.get("filename")
|
||||
const type = params.get("type") as ComfyUploadImageType;
|
||||
const subfolder = params.get("subfolder") || ""
|
||||
const previewStr = params.get("preview") || null;
|
||||
let preview = null
|
||||
|
||||
if (previewStr != null) {
|
||||
preview = parseComfyUIPreviewType(preview);
|
||||
}
|
||||
|
||||
// If at least filename and type exist then we're good
|
||||
if (filename != null && type != null) {
|
||||
return { filename, type, subfolder }
|
||||
return { filename, type, subfolder, preview }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function showLightbox(images: string[], index: number, e: Event) {
|
||||
export function showLightbox(images: ComfyImageLocation[] | string[], index: number, e: Event) {
|
||||
e.preventDefault()
|
||||
if (!images)
|
||||
return
|
||||
|
||||
ImageViewer.instance.showModal(images, index);
|
||||
let images_: string[]
|
||||
if (typeof images[0] === "object")
|
||||
images_ = (images as ComfyImageLocation[]).map(v => convertComfyOutputToComfyURL(v))
|
||||
else
|
||||
images_ = (images as string[])
|
||||
|
||||
ImageViewer.instance.showModal(images_, index);
|
||||
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user