Merge branch 'main' into dev/uv-tools
This commit is contained in:
+41
-29
@@ -436,8 +436,11 @@ class MaskToImage:
|
||||
return (pil2tensor(images),)
|
||||
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class ColoredImage:
|
||||
"""Constant color image of given size"""
|
||||
"""Constant color image of given size."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
@@ -565,43 +568,52 @@ class ColoredImage:
|
||||
return img.crop((left, top, right, bottom))
|
||||
|
||||
def render_img(
|
||||
self, color, width, height, foreground_image=None, foreground_mask=None
|
||||
self,
|
||||
color,
|
||||
width,
|
||||
height,
|
||||
foreground_image: Optional[torch.Tensor] = None,
|
||||
foreground_mask: Optional[torch.Tensor] = None,
|
||||
):
|
||||
image = Image.new("RGBA", (width, height), color=color)
|
||||
output = []
|
||||
if foreground_image is not None:
|
||||
if foreground_mask is None:
|
||||
fg_images = tensor2pil(foreground_image)
|
||||
for img in fg_images:
|
||||
if image.size != img.size:
|
||||
raise ValueError(
|
||||
f"Dimension mismatch: image {image.size}, img {img.size}"
|
||||
)
|
||||
fg_images = tensor2pil(foreground_image)
|
||||
fg_masks = [None] * len(
|
||||
fg_images
|
||||
) # Default to None for each foreground image
|
||||
|
||||
if img.mode != "RGBA":
|
||||
raise ValueError(
|
||||
f"Foreground image must be in 'RGBA' mode when no mask is provided, got {img.mode}"
|
||||
)
|
||||
if foreground_mask is not None:
|
||||
if foreground_image.size()[0] != foreground_mask.size()[0]:
|
||||
raise ValueError(
|
||||
"Foreground image and mask must have same batch size"
|
||||
)
|
||||
fg_masks = tensor2pil(foreground_mask)
|
||||
|
||||
for fg_image, fg_mask in zip(fg_images, fg_masks):
|
||||
# Resize and crop if dimensions mismatch
|
||||
if fg_image.size != image.size:
|
||||
fg_image = self.resize_and_crop(fg_image, image.size)
|
||||
if fg_mask:
|
||||
fg_mask = self.resize_and_crop(fg_mask, image.size)
|
||||
|
||||
if fg_mask:
|
||||
output.append(
|
||||
Image.alpha_composite(image, img).convert("RGB")
|
||||
Image.composite(
|
||||
fg_image.convert("RGBA"),
|
||||
image,
|
||||
fg_mask,
|
||||
).convert("RGB")
|
||||
)
|
||||
else:
|
||||
if fg_image.mode != "RGBA":
|
||||
raise ValueError(
|
||||
"Foreground image must be in 'RGBA' mode when no mask is provided, got {fg_image.mode}"
|
||||
)
|
||||
output.append(
|
||||
Image.alpha_composite(image, fg_image).convert("RGB")
|
||||
)
|
||||
|
||||
elif foreground_image.size[0] != foreground_mask.size[0]:
|
||||
raise ValueError(
|
||||
"Foreground image and mask must have same batch size"
|
||||
)
|
||||
else:
|
||||
fg_images = tensor2pil(foreground_image)
|
||||
fg_masks = tensor2pil(foreground_mask)
|
||||
output.extend(
|
||||
Image.composite(
|
||||
fg_image.convert("RGBA"),
|
||||
image,
|
||||
fg_mask,
|
||||
).convert("RGB")
|
||||
for fg_image, fg_mask in zip(fg_images, fg_masks)
|
||||
)
|
||||
elif foreground_mask is not None:
|
||||
log.warn("Mask ignored because no foreground image is given")
|
||||
|
||||
|
||||
+33
-1
@@ -20,6 +20,38 @@ export function makeUUID() {
|
||||
return uuid
|
||||
}
|
||||
|
||||
//- local storage manager
|
||||
export class LocalStorageManager {
|
||||
constructor(namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
_namespacedKey(key) {
|
||||
return `${this.namespace}:${key}`;
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
const serializedValue = JSON.stringify(value);
|
||||
localStorage.setItem(this._namespacedKey(key), serializedValue);
|
||||
}
|
||||
|
||||
get(key, default_val = null) {
|
||||
const value = localStorage.getItem(this._namespacedKey(key));
|
||||
return value ? JSON.parse(value) : default_val;
|
||||
}
|
||||
|
||||
remove(key) {
|
||||
localStorage.removeItem(this._namespacedKey(key));
|
||||
}
|
||||
|
||||
clear() {
|
||||
Object.keys(localStorage)
|
||||
.filter(k => k.startsWith(this.namespace + ':'))
|
||||
.forEach(k => localStorage.removeItem(k));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// - log utilities
|
||||
|
||||
function createLogger(emoji, color, consoleMethod = 'log') {
|
||||
@@ -378,7 +410,7 @@ function getBrightness(rgbObj) {
|
||||
(parseInt(rgbObj[0]) * 299 +
|
||||
parseInt(rgbObj[1]) * 587 +
|
||||
parseInt(rgbObj[2]) * 114) /
|
||||
1000
|
||||
1000
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+24
-5
@@ -11,7 +11,7 @@
|
||||
|
||||
import { api } from '../../scripts/api.js'
|
||||
import { app } from '../../scripts/app.js'
|
||||
|
||||
import { LocalStorageManager } from "./comfy_shared.js"
|
||||
const styles = {
|
||||
lighbox: {
|
||||
position: 'fixed',
|
||||
@@ -53,11 +53,31 @@ let currentImageIndex = 0
|
||||
const imageUrls = []
|
||||
|
||||
let image_menu = null
|
||||
let activated = true
|
||||
const storage = new LocalStorageManager('mtb');
|
||||
|
||||
let activated = storage.get("image_feed", true)
|
||||
|
||||
app.registerExtension({
|
||||
name: 'mtb.ImageFeed',
|
||||
setup: () => {
|
||||
app.ui.settings.addSetting({
|
||||
id: 'mtb.imageFeed.enabled',
|
||||
name: '[⚡mtb] Enable image feed',
|
||||
type: 'boolean',
|
||||
defaultValue: true,
|
||||
attrs: {
|
||||
style: {
|
||||
fontFamily: 'monospace',
|
||||
},
|
||||
},
|
||||
async onChange(value) {
|
||||
storage.set("image_feed", value)
|
||||
activated = value
|
||||
},
|
||||
})
|
||||
},
|
||||
init: async () => {
|
||||
if (!activated) { return }
|
||||
const pythongossFeed = app.extensions.find(
|
||||
(e) => e.name == 'pysssss.ImageFeed'
|
||||
)
|
||||
@@ -230,9 +250,8 @@ app.registerExtension({
|
||||
objectFit: 'cover',
|
||||
})
|
||||
|
||||
img.src = `/view?filename=${encodeURIComponent(src.filename)}&type=${
|
||||
src.type
|
||||
}&subfolder=${encodeURIComponent(src.subfolder)}`
|
||||
img.src = `/view?filename=${encodeURIComponent(src.filename)}&type=${src.type
|
||||
}&subfolder=${encodeURIComponent(src.subfolder)}`
|
||||
|
||||
imageUrls.push(img.src)
|
||||
|
||||
|
||||
+1
-1
@@ -582,7 +582,7 @@ const mtb_widgets = {
|
||||
setup: () => {
|
||||
app.ui.settings.addSetting({
|
||||
id: 'mtb.Debug.enabled',
|
||||
name: '[mtb] Enable Debug (py and js)',
|
||||
name: '[⚡mtb] Enable Debug (py and js)',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user