Skip to content

Commit

Permalink
added colorizer to new beta menu
Browse files Browse the repository at this point in the history
better regex for shaders
  • Loading branch information
Amorano committed Jul 16, 2024
1 parent 1fe5661 commit 0442d0b
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 56 deletions.
9 changes: 6 additions & 3 deletions core/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,10 +566,13 @@ def run(self, **kw) -> Tuple[Any, ...]:
pbar = ProgressBar(len(params))
for idx, (pA, start, use_range, end, fuzz, matte) in enumerate(params):
img = np.zeros((MIN_IMAGE_SIZE, MIN_IMAGE_SIZE, 3), dtype=np.uint8) if pA is None else tensor2cv(pA)

img, mask = image_filter(img, start, end, fuzz, use_range)
matte = image_matte(img, matte)[:,:,:3]
# logger.debug(f"{img.shape}, {type(img)}, {matte.shape}")
images.append([cv2tensor(img), cv2tensor(matte), cv2tensor(mask)])
if img.shape[2] == 3:
alpha_channel = np.zeros((img.shape[0], img.shape[1], 1), dtype=img.dtype)
img = np.concatenate((img, alpha_channel), axis=2)
img[:,:,3] = mask[:,:]
images.append(cv2tensor_full(img, matte))
pbar.update_absolute(idx)
return [torch.cat(i, dim=0) for i in zip(*images)]

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[project]
name = "jovimetrix"
description = "Integrates Webcam, MIDI, Spout and GLSL shader support. Animation via tick. Parameter manipulation with wave generator. Math operations with Unary and Binary support. Value conversion for all major types (int, string, list, dict, Image, Mask). Shape mask generation, image stacking and channel ops, batch splitting, merging and randomizing, load images and video from anywhere, dynamic bus routing with a single node, export support for GIPHY, save output anywhere! flatten, crop, transform; check colorblindness, make stereogram or stereoscopic images, or liner interpolate values and more."
version = "1.2.4"
version = "1.2.5"
license = "MIT"
dependencies = [
"aenum>=3.1.15, <4",
Expand Down
76 changes: 32 additions & 44 deletions sup/shader.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
'vec4': EnumConvertType.VEC4
}

RE_VARIABLE = re.compile(r"uniform\s*(\w*)\s*(\w*);(?:.*\/{2}\s*([A-Za-z0-9\-\.,\s]+)){0,1}$", re.MULTILINE)
RE_VARIABLE = re.compile(r"uniform\s*(\w*)\s*(\w*);(?:.*\/{2}\s*([A-Za-z0-9\-\.,\s]+)){0,1}\s*$", re.MULTILINE)

# =============================================================================

Expand Down Expand Up @@ -85,10 +85,8 @@ class GLSLShader():
u = mod(u, 2.);
vec2 uv = fragCoord.xy / iResolution.xy;
//vec3 col2 = texture2D(imageB, uv).rgb;
vec3 col2 = texture2D(imageB, uv).rgb;
vec3 col = texture2D(imageA, uv).rgb;
fragColor = vec4(col + (floor(sin(s)) - u.y - floor(cos(s)) - u.xxxx).rgb, 1.0);
}
"""
Expand All @@ -113,7 +111,6 @@ def __init__(self, vertex:str=None, fragment:str=None, width:int=IMAGE_SIZE_MIN,
#
self.__size: Tuple[int, int] = (max(width, IMAGE_SIZE_MIN), max(height, IMAGE_SIZE_MIN))
self.__fbo = None
self.__textures = None
self.__program = None
self.__source_vertex: None
self.__source_fragment: None
Expand Down Expand Up @@ -150,14 +147,16 @@ def __framebuffer(self) -> None:
gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, texture, 0)
if gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE:
raise RuntimeError("Framebuffer is not complete")
# gl.glUseProgram(self.__program)

def __del__(self) -> None:
# assume all other resources get cleaned up with the context
if len(self.__textures):
gl.glDeleteTextures(len(self.__textures), self.__textures)
if glfw:
glfw.terminate()
"""
try:
if len(self.__textures):
gl.glDeleteTextures(len(self.__textures), self.__textures)
except:
pass
"""

@property
def vertex(self) -> str:
Expand Down Expand Up @@ -259,35 +258,24 @@ def program(self, vertex:str=None, fragment:str=None) -> None:
# read the fragment and setup the vars....
for match in RE_VARIABLE.finditer(fragment):
typ, name, default = match.groups()
texIdx = None
tex_loc = None
if typ in ['sampler2D']:
texIdx = texture_count
texture_count += 1
else:
logger.debug(f"{name}.{typ}: {default}")
tex_loc = gl.glGenTextures(1)
logger.debug(f"{name}.{typ}: {default}")
self.__userVar[name] = [
# type
typ,
# gl location
gl.glGetUniformLocation(self.__program, name),
# default value
default,
# texture index (if any)
texIdx
# texture id -- if a texture
tex_loc
]
self.__textures = gl.glGenTextures(texture_count)
if not isinstance(self.__textures, (np.ndarray,)):
self.__textures = [self.__textures]
#else:
# self.__textures.tolist()

def render(self, time_delta:float=0., **kw) -> np.ndarray:
self.runtime = time_delta

gl.glUseProgram(self.__program)
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.__fbo)
gl.glClearColor(0.0, 0.0, 0.0, 1.0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)

# SET SHADER STATIC VARS
gl.glUniform3f(self.__shaderVar['iResolution'], self.__size[0], self.__size[1], 0)
Expand All @@ -300,43 +288,43 @@ def render(self, time_delta:float=0., **kw) -> np.ndarray:

# SET USER DYNAMIC VARS
# update any user vars...
texture_index = 0
for uk, uv in self.__userVar.items():
# type, loc, value, index
p_type, p_loc, p_value, p_index = uv
p_type, p_loc, p_value, p_tex = uv
# use the default....
val = p_value if not uk in kw else kw[uk]

# SET TEXTURE
if (p_type == 'sampler2D'):
# cache textures? or do we care per frame?
gl.glBindTexture(gl.GL_TEXTURE_2D, self.__textures[p_index])
if val is None:
print(uk, val)
gl.glBindTexture(gl.GL_TEXTURE_2D, p_tex)
val = empty if val is None else val
if val.ndim == 3:
op = gl.GL_RGBA if val.shape[2] == 4 else gl.GL_RGB
val = val[::-1,:]
val = val.astype(np.float32) / 255.0
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, op, val.shape[1], val.shape[0], 0, op, gl.GL_FLOAT, val)

gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, op, val.shape[1], val.shape[0], 0, op, gl.GL_FLOAT, val)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)

loc_image = gl.glGetUniformLocation(self.__program, uk)
gl.glUniform1i(loc_image, p_index)

# Bind the texture to the texture unit
gl.glActiveTexture(gl.GL_TEXTURE0 + texture_index)
gl.glBindTexture(gl.GL_TEXTURE_2D, p_tex)
gl.glUniform1i(p_loc, texture_index)
texture_index += 1
else:
if (funct := LAMBDA_UNIFORM.get(p_type, None)) is None:
logger.warning(f"no type function: {p_type}.")
continue
val = parse_value(val, PTYPE[p_type], 0)
if not isinstance(val, (list, tuple,)):
val = [val]
# logger.debug(f'{uk}.{p_type}=={val}')
funct(p_loc, *val)
funct = LAMBDA_UNIFORM.get(p_type)
if funct is not None:
val = parse_value(val, PTYPE[p_type], 0)
if not isinstance(val, (list, tuple)):
val = [val]
funct(p_loc, *val)

gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.__fbo)
gl.glClearColor(0.0, 0.0, 0.0, 1.0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)
data = gl.glReadPixels(0, 0, self.__size[0], self.__size[1], gl.GL_RGB, gl.GL_UNSIGNED_BYTE)
image = np.frombuffer(data, dtype=np.uint8).reshape(self.__size[1], self.__size[0], 3)
Expand Down
23 changes: 16 additions & 7 deletions web/core/core_colorize.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import { $el } from "../../../scripts/ui.js"
import { api_post } from '../util/util_api.js'
import { color_contrast, node_color_all, node_color_reset } from '../util/util_color.js'
import * as util_config from '../util/util_config.js'
//import { CONFIG_REGEX, USER, CONFIG_USER, CONFIG_THEME, CONFIG_COLOR, NODE_LIST } from '../util/util_config.js'

import { JovimetrixConfigDialog } from "./core_config.js"
import "../extern/jsColorPicker.js"

app.registerExtension({
name: "jovimetrix.colorize",
async init(app) {
async setup(app) {
const original_color = LiteGraph.NODE_TEXT_COLOR;

util_config.setting_make('color.contrast', '🇯 🎨 Auto-Contrast Text', 'boolean', 'Auto-contrast the title text for all nodes for better readability', true);

const showButton = $el("button.comfy-settings-btn", {
textContent: "🎨",
style: {
Expand All @@ -34,12 +38,17 @@ app.registerExtension({
const firstKid = document.querySelector(".comfy-settings-btn")
const parent = firstKid.parentElement
parent.insertBefore(showButton, firstKid.nextSibling)
},
async setup(app) {

const original_color = LiteGraph.NODE_TEXT_COLOR;

util_config.setting_make('color.contrast', '🇯 🎨 Auto-Contrast Text', 'boolean', 'Auto-contrast the title text for all nodes for better readability', true);
let showMenuButton;
if (!app.menu?.element.style.display && app.menu?.settingsGroup) {
showMenuButton = new (await import("../../../scripts/ui/components/button.js")).ComfyButton({
icon: "palette-outline",
action: () => showButton.click(),
tooltip: "Jovimetrix Colorizer",
content: "Jovimetrix Colorizer",
});
app.menu.settingsGroup.append(showMenuButton);
}

// Option for user to contrast text for better readability
const drawNodeShape = LGraphCanvas.prototype.drawNodeShape;
Expand Down
2 changes: 1 addition & 1 deletion web/nodes/glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { flashBackgroundColor } from '../util/util_fun.js';
const _id = "GLSL (JOV) 🍩";
const EVENT_JOVI_GLSL_ERROR = "jovi-glsl-error";
const EVENT_JOVI_GLSL_TIME = "jovi-glsl-time";
const RE_VARIABLE = /uniform\s*(\w*)\s*(\w*);(?:.*\/{2}\s*([A-Za-z0-9\-\.,\s]+)){0,1}$/gm
const RE_VARIABLE = /uniform\s*(\w*)\s*(\w*);(?:.*\/{2}\s*([A-Za-z0-9\-\.,\s]+)){0,1}\s*$/gm

app.registerExtension({
name: 'jovimetrix.node.' + _id,
Expand Down

0 comments on commit 0442d0b

Please sign in to comment.