Added user setting to select preview image thumbnail type ("JPEG", "WEBP" or "JPEG/WEBP").

- Default is "JPEG/WEBP", which will fall back to "JPEG" if preview image is neither type (e.g. "PNG").
This commit is contained in:
Christian Bastian
2024-07-20 21:43:56 -04:00
parent 534f93e242
commit 94b6081e22
2 changed files with 53 additions and 6 deletions

View File

@@ -182,6 +182,7 @@ def ui_rules():
Rule("model-preview-fallback-search-safetensors-thumbnail", False, bool),
Rule("model-show-add-button", True, bool),
Rule("model-show-copy-button", True, bool),
Rule("model-preview-thumbnail-type", "JPEG/WEBP", str),
Rule("model-add-embedding-extension", False, bool),
Rule("model-add-drag-strict-on-field", False, bool),
Rule("model-add-offset", 25, int),
@@ -290,6 +291,16 @@ def image_format_is_equal(f1, f2):
return f1 == f2 or (f1 == "JPG" and f2 == "JPEG") or (f1 == "JPEG" and f2 == "JPG")
def is_auto_thumbnail_format(format):
return format in ["JPEG/WEBP", "WEBP/JPEG", "JPG/WEBP", "WEBP/JPG"]
def get_auto_thumbnail_format(original_format):
if original_format in ["JPEG", "WEBP", "JPG"]:
return original_format
return "JPEG" # default fallback
@server.PromptServer.instance.routes.get("/model-manager/preview/get")
async def get_model_preview(request):
uri = request.query.get("uri")
@@ -339,10 +350,13 @@ async def get_model_preview(request):
image_format = image.format
if response_image_format is None:
response_image_format = image_format
elif not image_format_is_equal(response_image_format, image_format):
elif is_auto_thumbnail_format(response_image_format):
response_image_format = get_auto_thumbnail_format(image_format)
if not image_format_is_equal(response_image_format, image_format):
exif = image.getexif()
metadata = get_image_info(image)
if response_image_format == 'JPEG' or response_image_format == 'JPG':
if response_image_format in ['JPEG', 'JPG']:
image = image.convert('RGB')
image_bytes = io.BytesIO()
image.save(image_bytes, format=response_image_format, exif=exif, pnginfo=metadata, quality=quality)
@@ -358,6 +372,9 @@ async def get_model_preview(request):
image_format = image.format
if response_image_format is None:
response_image_format = image_format
elif is_auto_thumbnail_format(response_image_format):
response_image_format = get_auto_thumbnail_format(image_format)
w0, h0 = image.size
if w is None:
w = (h * w0) // h0
@@ -387,13 +404,14 @@ async def get_model_preview(request):
resampling_method = Image.Resampling.BICUBIC
image.thumbnail((w, h), resample=resampling_method)
if not image_format_is_equal(image_format, response_image_format) and (response_image_format == 'JPEG' or response_image_format == 'JPG'):
if not image_format_is_equal(image_format, response_image_format) and response_image_format in ['JPEG', 'JPG']:
image = image.convert('RGB')
image_bytes = io.BytesIO()
image.save(image_bytes, format=response_image_format, exif=exif, pnginfo=metadata, quality=quality)
image_data = image_bytes.getvalue()
response_file_name = os.path.splitext(file_name)[0] + '.' + response_image_format.lower()
print(f"response_file_name: {response_file_name}")
return web.Response(
headers={
"Content-Disposition": f"inline; filename={response_file_name}",

View File

@@ -138,7 +138,6 @@ function imageUri(imageSearchPath = undefined, dateImageModified = undefined, wi
const PREVIEW_NONE_URI = imageUri();
const PREVIEW_THUMBNAIL_WIDTH = 320;
const PREVIEW_THUMBNAIL_HEIGHT = 480;
const PREVIEW_THUMBNAIL_FORMAT = "JPEG";
/**
* @param {(...args) => void} callback
@@ -230,6 +229,28 @@ function $checkbox(x = { $: (el) => {}, textContent: "", checked: false }) {
return label;
}
/**
* @returns {HTMLLabelElement}
*/
function $select(x = { $: (el) => {}, textContent: "", options: [""] }) {
const text = x.textContent;
const select = $el("select", {
name: text ?? "select",
}, x.options.map((option) => {
return $el("option", {
value: option,
}, option);
}));
const label = $el("label", [
select,
text === "" || text === undefined || text === null ? "" : " " + text,
]);
if (x.$ !== undefined){
x.$(select);
}
return label;
}
/**
* @param {Any} attr
* @returns {HTMLDivElement}
@@ -1654,6 +1675,7 @@ class ModelGrid {
const addOffset = parseInt(settingsElements["model-add-offset"].value);
const showModelExtension = settingsElements["model-show-label-extensions"].checked;
const removeEmbeddingExtension = !settingsElements["model-add-embedding-extension"].checked;
const previewThumbnailFormat = settingsElements["model-preview-thumbnail-type"].value;
if (models.length > 0) {
return models.map((item) => {
const previewInfo = item.preview;
@@ -1706,7 +1728,7 @@ class ModelGrid {
previewInfo?.dateModified,
PREVIEW_THUMBNAIL_WIDTH,
PREVIEW_THUMBNAIL_HEIGHT,
PREVIEW_THUMBNAIL_FORMAT,
previewThumbnailFormat,
),
draggable: false,
}),
@@ -3221,7 +3243,8 @@ class SettingsView {
case "range": setting.value = parseFloat(value); break;
case "textarea": setting.value = value; break;
case "number": setting.value = parseInt(value); break;
default: console.warn("Unknown settings input type!");
case "select-one": setting.value = value; break;
default: console.warn(`Unknown settings input type '${type}'!`);
}
}
@@ -3253,6 +3276,7 @@ class SettingsView {
case "range": value = el.value; break;
case "textarea": value = el.value; break;
case "number": value = el.value; break;
case "select-one": value = el.value; break;
default: console.warn("Unknown settings input type!");
}
settingsData[setting] = value;
@@ -3365,6 +3389,11 @@ class SettingsView {
$: (el) => (settings["model-show-copy-button"] = el),
textContent: "Show copy button",
}),
$select({
$: (el) => (settings["model-preview-thumbnail-type"] = el),
textContent: "Preview thumbnail type",
options: ["JPEG/WEBP", "JPEG", "WEBP"],
}),
$el("h2", ["Model Add"]),
$checkbox({
$: (el) => (settings["model-add-embedding-extension"] = el),