873 lines
54 KiB
Python
873 lines
54 KiB
Python
from ..components.tree import TREE_RASTERIX
|
|
from ..components.tree import PRIMERE_ROOT
|
|
import random
|
|
import folder_paths
|
|
from ..components.images import img_shade_level as img_shade_level
|
|
from ..components.images import img_brightness_contrast as img_brightness_contrast
|
|
from ..components.images import img_color_balance as img_color_balance
|
|
from ..components.images import img_hue_saturation as img_hue_saturation
|
|
from ..components.images import img_levels_auto as img_levels_auto
|
|
from ..components.images import isgen_detect_ext_full as isgen_detect_ext_full
|
|
from ..components.images import img_film_grain as img_film_grain
|
|
from ..components.images import img_blur as img_blur
|
|
from ..components.images import img_selective_tone as img_selective_tone
|
|
from ..components.images import img_smart_lighting as img_smart_lighting
|
|
from ..components.images import img_white_balance as img_white_balance
|
|
from ..components.images import img_film_rendering as img_film_rendering
|
|
from ..components.images.img_film_rendering import FILM_PRESETS
|
|
from ..components.images import img_lens_effects as img_lens_effects
|
|
from ..components.images import img_levels_compress as img_levels_compress
|
|
from ..components.images import img_dithering as img_dithering
|
|
from ..components.images import histogram as histogram
|
|
from ..components import utility
|
|
from .Dashboard import PrimereModelConceptSelector as PrimereModelConceptSelector
|
|
import os
|
|
from server import PromptServer
|
|
|
|
class PrimereRasterix:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_rasterix"
|
|
CATEGORY = TREE_RASTERIX
|
|
OUTPUT_NODE = True
|
|
|
|
MODELLIST = PrimereModelConceptSelector.MODELLIST
|
|
CONCEPT_LIST = PrimereModelConceptSelector.CONCEPT_LIST
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"concepts": (["Auto"] + cls.CONCEPT_LIST,),
|
|
"models": (["Auto"] + cls.MODELLIST,),
|
|
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"precision": ("BOOLEAN", {"default": False, "label_off": "8 bit", "label_on": "16 bit"}),
|
|
|
|
"auto_normalize": ("BOOLEAN", {"default": False, "label_off": "No auto levels", "label_on": "Apply auto levels"}),
|
|
"auto_levels_threshold": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 10.0, "step": 0.1}),
|
|
"auto_gamma": ("BOOLEAN", {"default": False, "label_on": "Auto gamma: ON", "label_off": "Auto gamma:: OFF"}),
|
|
"gamma_target": ("FLOAT", {"default": 128.0, "min": 0.0, "max": 255.0, "step": 0.1}),
|
|
|
|
"use_white_balance": ("BOOLEAN", {"default": False, "label_off": "Ignore white balance", "label_on": "Apply white balance"}),
|
|
"wb_temperature": ("FLOAT", {"default": 6500, "min": 2000, "max": 12000, "step": 100}),
|
|
"wb_tint": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
|
|
"use_smart_lighting": ("BOOLEAN", {"default": False, "label_off": "Ignore smart lightning", "label_on": "Apply smart lightning"}),
|
|
"smart_lighting": ("FLOAT", {"default": 0, "min": 0, "max": 100, "step": 1}),
|
|
|
|
"use_blur": ("BOOLEAN", {"default": False, "label_off": "Ignore blur", "label_on": "Apply blur"}),
|
|
"blur_type": (["gaussian", "box", "motion", "bilateral", "lens"], {"default": "bilateral"}),
|
|
"blur_intensity": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 5.0, "step": 0.1}),
|
|
"blur_radius": ("FLOAT", {"default": 2.0, "min": 0.5, "max": 50.0, "step": 0.5}),
|
|
"angle": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 360.0, "step": 1.0}),
|
|
"bilateral_edge_sensitivity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"blur_edge_only": ("BOOLEAN", {"default": False, "label_off": "Full image blur", "label_on": "Flat areas only, edges protected"}),
|
|
"edge_threshold": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
|
|
"use_brightness_contrast": ("BOOLEAN", {"default": False, "label_off": "Ignore brightness-contrast", "label_on": "Apply brightness-contrast"}),
|
|
"brightness": ("FLOAT", {"default": 0, "min": -150, "max": 150, "step": 1}),
|
|
"contrast": ("FLOAT", {"default": 0, "min": -50, "max": 100, "step": 1}),
|
|
"use_legacy": ("BOOLEAN", {"default": False, "label_off": "Use non-linear shift", "label_on": "Use adaptive offset"}),
|
|
|
|
"use_film_rendering": ("BOOLEAN", {"default": False, "label_off": "Ignore film rendering", "label_on": "Apply film rendering"}),
|
|
"film_rendering": (list(FILM_PRESETS.keys()), {"default": list(FILM_PRESETS.keys())[0]}),
|
|
"film_rendering_intensity": ("FLOAT", {"default": 100, "min": 0, "max": 200, "step": 1}),
|
|
"iso_grain": ("BOOLEAN", {"default": False, "label_off": "Ignore ISO grain", "label_on": "Add ISO grain"}),
|
|
"halation": ("BOOLEAN", {"default": False, "label_off": "Ignore halation", "label_on": "Add halation"}),
|
|
"expiration_years": ("INT", {"default": 0, "min": 0, "max": 30, "step": 1}),
|
|
|
|
"use_selective_tone": ("BOOLEAN", {"default": False, "label_off": "Ignore selective tone", "label_on": "Apply selective tone"}),
|
|
"selective_tone_value": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"selective_tone_zone": (["highlights", "midtones", "shadows", "blacks"], {"default": "midtones"}),
|
|
"selective_tone_separation": ("FLOAT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
"selective_tone_strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
|
|
"use_color_balance": ("BOOLEAN", {"default": False, "label_off": "Ignore color balance", "label_on": "Apply color balance"}),
|
|
"color_balance_cyan_red": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"color_balance_magenta_green": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"color_balance_yellow_blue": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"color_balance_tone": (["highlights", "midtones", "shadows"], {"default": "midtones"}),
|
|
"color_balance_preserve_luminosity": ("BOOLEAN", {"default": False, "label_off": "Modify luminosity", "label_on": "Restore original luminosity"}),
|
|
"color_balance_separation": ("FLOAT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
|
|
"use_hsl": ("BOOLEAN", {"default": False, "label_off": "Ignore HSL", "label_on": "Apply HSL"}),
|
|
"hsl_hue": ("FLOAT", {"default": 0, "min": -180, "max": 180, "step": 1}),
|
|
"hsl_saturation": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"hsl_lightness": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"hsl_vibrance": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"hsl_channel": (["master", "red", "green", "blue"], {"default": "master"}),
|
|
"hsl_channel_width": ("FLOAT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
"hsl_skin_protection": ("BOOLEAN", {"default": True, "label_off": "Vibrance affects skin tones", "label_on": "Skin tones protected from vibrance"}),
|
|
|
|
"use_shade_detailer": ("BOOLEAN", {"default": False, "label_off": "Ignore shade detailer", "label_on": "Apply shade detailer"}),
|
|
"shade_level": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"shade_radius": ("FLOAT", {"default": 0, "min": 0, "max": 50, "step": 0.5}),
|
|
"detail_mode": (["fine", "medium", "broad"], {"default": "medium"}),
|
|
"shade_strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
|
|
"use_level_endpoints": ("BOOLEAN", {"default": False, "label_off": "Ignore endpoint offset", "label_on": "Apply endpoint offset"}),
|
|
"black_offset": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 25.0, "step": 0.1}),
|
|
"white_offset": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 25.0, "step": 0.1}),
|
|
"skip_if_no_clip": ("BOOLEAN", {"default": False, "label_off": "Offset all values", "label_on": "Skip if no clips"}),
|
|
|
|
"normalize_gaps": ("BOOLEAN", {"default": False, "label_on": "Anti-comb filter: ON", "label_off": "Anti-comb filter: OFF"}),
|
|
"normalize_midpeaks": ("BOOLEAN", {"default": False, "label_on": "Anti-spike filter: ON", "label_off": "Anti-spike filter: OFF"}),
|
|
"peak_width": ("INT", {"default": 3, "min": 1, "max": 10, "step": 1}),
|
|
"dither_quantization": ("BOOLEAN", {"default": False, "label_off": "Dither quantization OFF", "label_on": "Dither quantization ON"}),
|
|
"adaptive_dither_strength": ("BOOLEAN", {"default": False, "label_off": "Keep dither strength", "label_on": "Increase dither strength"}),
|
|
"error_diffusion": ("BOOLEAN", {"default": False, "label_off": "Error diffusion OFF", "label_on": "Error diffusion ON"}),
|
|
|
|
"use_ai_detection_bypasser": ("BOOLEAN", {"default": False, "label_off": "AI detection bypass off", "label_on": "AI detection bypass on"}),
|
|
"adb_freq_strength": ("FLOAT", {"default": 0.019, "min": 0.0, "max": 0.1, "step": 0.001}),
|
|
"adb_variance_strength": ("FLOAT", {"default": 0.32, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"adb_unsharp_percent": ("INT", {"default": 38, "min": 0, "max": 150, "step": 1}),
|
|
"adb_jpeg_cycles": ("INT", {"default": 4, "min": 0, "max": 6, "step": 1}),
|
|
|
|
"show_histogram": ("BOOLEAN", {"default": False, "label_off": "Ignore histogram", "label_on": "Create histogram"}),
|
|
"histogram_source": ("BOOLEAN", {"default": False, "label_off": "Show output histogram", "label_on": "Show input histogram"}),
|
|
"histogram_channel": (["RGB", "RED", "GREEN", "BLUE"], {"default": "RGB"}),
|
|
"histogram_style": (["bars", "lines", "waveform", "heatmap", "stacked", "luma", "parade", "gradient", "glow", "dots", "step", "log", "percentile", "inverse"], {"default": "bars"}),
|
|
},
|
|
"optional": {
|
|
"model_concept": ("STRING", {"default": None, "forceInput": True}),
|
|
"model_name": ("CHECKPOINT_NAME", {"default": None, "forceInput": True}),
|
|
}
|
|
}
|
|
|
|
def primere_rasterix(self, **kwargs):
|
|
concepts = kwargs.get('concepts', 'Auto')
|
|
models = kwargs.get('models', 'Auto')
|
|
model_concept = kwargs.get('model_concept', None)
|
|
model_name = kwargs.get('model_name', None)
|
|
active_concept = model_concept if concepts == "Auto" else concepts
|
|
active_display = active_concept
|
|
|
|
if concepts == "Auto" and models == "Auto":
|
|
raw_model = model_name
|
|
model_key = os.path.splitext(os.path.basename(raw_model))[0] if raw_model else None
|
|
json_path = os.path.join(PRIMERE_ROOT, 'front_end', 'rasterix_settings.json')
|
|
concept_data = utility.json2tuple(json_path)
|
|
if model_key and concept_data and model_key in concept_data:
|
|
lookup_key = model_key
|
|
active_display = model_key
|
|
else:
|
|
lookup_key = active_concept
|
|
active_display = active_concept
|
|
if not concept_data or lookup_key not in concept_data:
|
|
PromptServer.instance.send_sync("primere.rasterix_setting", {"status": "missing", "concept": active_concept})
|
|
else:
|
|
saved = concept_data[lookup_key]
|
|
for k, v in saved.items():
|
|
if k in kwargs:
|
|
kwargs[k] = v
|
|
|
|
image = kwargs.get('image')
|
|
precision = kwargs.get('precision', False)
|
|
auto_normalize = kwargs.get('auto_normalize', False)
|
|
auto_levels_threshold = kwargs.get('auto_levels_threshold', 0.2)
|
|
normalize_midpeaks = kwargs.get('normalize_midpeaks', False)
|
|
peak_width = kwargs.get('peak_width', 3)
|
|
auto_gamma = kwargs.get('auto_gamma', False)
|
|
gamma_target = kwargs.get('gamma_target', 128.0)
|
|
use_white_balance = kwargs.get('use_white_balance', False)
|
|
wb_temperature = kwargs.get('wb_temperature', 6500)
|
|
wb_tint = kwargs.get('wb_tint', 0)
|
|
use_blur = kwargs.get('use_blur', False)
|
|
blur_type = kwargs.get('blur_type', "bilateral")
|
|
blur_intensity = kwargs.get('blur_intensity', 0.0)
|
|
blur_radius = kwargs.get('blur_radius', 2.0)
|
|
angle = kwargs.get('angle', 0.0)
|
|
bilateral_edge_sensitivity = kwargs.get('bilateral_edge_sensitivity', 0.5)
|
|
blur_edge_only = kwargs.get('blur_edge_only', False)
|
|
edge_threshold = kwargs.get('edge_threshold', 0.0)
|
|
use_smart_lighting = kwargs.get('use_smart_lighting', False)
|
|
smart_lighting = kwargs.get('smart_lighting', 0)
|
|
use_brightness_contrast = kwargs.get('use_brightness_contrast', False)
|
|
brightness = kwargs.get('brightness', 0)
|
|
contrast = kwargs.get('contrast', 0)
|
|
use_legacy = kwargs.get('use_legacy', False)
|
|
use_film_rendering = kwargs.get('use_film_rendering', False)
|
|
film_rendering = kwargs.get('film_rendering', list(FILM_PRESETS.keys())[0])
|
|
film_rendering_intensity = kwargs.get('film_rendering_intensity', 100)
|
|
iso_grain = kwargs.get('iso_grain', False)
|
|
halation = kwargs.get('halation', False)
|
|
expiration_years = kwargs.get('expiration_years', 0)
|
|
use_selective_tone = kwargs.get('use_selective_tone', False)
|
|
selective_tone_separation = kwargs.get('selective_tone_separation', 50)
|
|
selective_tone_strength = kwargs.get('selective_tone_strength', 0.5)
|
|
use_color_balance = kwargs.get('use_color_balance', False)
|
|
color_balance_preserve_luminosity = kwargs.get('color_balance_preserve_luminosity', False)
|
|
color_balance_separation = kwargs.get('color_balance_separation', 50)
|
|
use_hsl = kwargs.get('use_hsl', False)
|
|
hsl_channel_width = kwargs.get('hsl_channel_width', 50)
|
|
hsl_skin_protection = kwargs.get('hsl_skin_protection', True)
|
|
use_shade_detailer = kwargs.get('use_shade_detailer', False)
|
|
shade_strength = kwargs.get('shade_strength', 0.5)
|
|
use_ai_detection_bypasser = kwargs.get('use_ai_detection_bypasser', False)
|
|
adb_freq_strength = kwargs.get('adb_freq_strength', 0.019)
|
|
adb_variance_strength = kwargs.get('adb_variance_strength', 0.32)
|
|
adb_unsharp_percent = kwargs.get('adb_unsharp_percent', 38)
|
|
adb_jpeg_cycles = kwargs.get('adb_jpeg_cycles', 4)
|
|
use_level_endpoints = kwargs.get('use_level_endpoints', False)
|
|
black_offset = kwargs.get('black_offset', 0.0)
|
|
white_offset = kwargs.get('white_offset', 0.0)
|
|
skip_if_no_clip = kwargs.get('skip_if_no_clip', False)
|
|
normalize_gaps = kwargs.get('normalize_gaps', False)
|
|
dither_quantization = kwargs.get('dither_quantization', False)
|
|
adaptive_dither_strength = kwargs.get('adaptive_dither_strength', False)
|
|
error_diffusion = kwargs.get('error_diffusion', False)
|
|
show_histogram = kwargs.get('show_histogram', False)
|
|
histogram_source = kwargs.get('histogram_source', False)
|
|
histogram_channel = kwargs.get('histogram_channel', "RGB")
|
|
histogram_style = kwargs.get('histogram_style', "bars")
|
|
|
|
pil_img = utility.tensor_to_image(image)
|
|
pil_img_input = pil_img.copy()
|
|
|
|
rasterix_json_path = os.path.join(PRIMERE_ROOT, 'front_end', 'rasterix.json')
|
|
rasterix_data = utility.json2tuple(rasterix_json_path) or {}
|
|
|
|
if auto_normalize:
|
|
pil_img = img_levels_auto.img_levels_auto(image=pil_img, auto_normalize=auto_normalize, threshold=auto_levels_threshold, normalize_gaps=normalize_gaps, normalize_midpeaks=False, peak_width=peak_width, auto_gamma=auto_gamma, gamma_target=gamma_target, precision=precision)
|
|
|
|
if use_white_balance and (wb_temperature != 6500 or wb_tint != 0):
|
|
pil_img = img_white_balance.img_white_balance(image=pil_img, temperature=wb_temperature, tint=wb_tint)
|
|
|
|
if use_blur and blur_intensity != 0:
|
|
pil_img = img_blur.img_blur(image=pil_img, blur_type=blur_type, intensity=blur_intensity, radius=blur_radius, angle=angle, edge_only=blur_edge_only, bilateral_edge_sensitivity=bilateral_edge_sensitivity, edge_threshold=edge_threshold)
|
|
|
|
if use_smart_lighting and smart_lighting != 0:
|
|
pil_img = img_smart_lighting.img_smart_lighting(image=pil_img, intensity=smart_lighting)
|
|
|
|
if use_brightness_contrast and (brightness != 0 or contrast != 0):
|
|
pil_img = img_brightness_contrast.img_brightness_contrast(image=pil_img, brightness=brightness, contrast=contrast, use_legacy=use_legacy)
|
|
|
|
if use_film_rendering and film_rendering_intensity != 0:
|
|
pil_img = img_film_rendering.img_film_rendering(image=pil_img, rendering=film_rendering, intensity=film_rendering_intensity, add_grain=iso_grain, add_halation=halation, expiration_years=expiration_years)
|
|
|
|
st_data = rasterix_data.get('selective_tone', {})
|
|
if use_selective_tone and st_data:
|
|
pil_img = img_selective_tone.img_selective_tone(image=pil_img, channels_data=st_data, separation=selective_tone_separation, strength=selective_tone_strength)
|
|
|
|
cb_data = rasterix_data.get('color_balance', {})
|
|
if use_color_balance and cb_data:
|
|
pil_img = img_color_balance.img_color_balance(image=pil_img, channels_data=cb_data, preserve_luminosity=color_balance_preserve_luminosity, separation=color_balance_separation)
|
|
|
|
hs_data = rasterix_data.get('hue_saturation', {})
|
|
if use_hsl and hs_data:
|
|
pil_img = img_hue_saturation.img_hue_saturation(image=pil_img, channels_data=hs_data, channel_width=hsl_channel_width, skin_protection=hsl_skin_protection)
|
|
|
|
shade_data = rasterix_data.get('shade', {})
|
|
if use_shade_detailer and shade_data:
|
|
for mode, vals in shade_data.items():
|
|
lvl = vals.get('shade_level', 0)
|
|
if lvl != 0:
|
|
rad = vals.get('shade_radius', 0)
|
|
pil_img = img_shade_level.img_shade_level(image=pil_img, shade_level=lvl, radius=rad, strength=shade_strength)
|
|
|
|
if use_level_endpoints and (black_offset != 0 or white_offset != 0):
|
|
pil_img = img_levels_compress.img_levels_compress(image=pil_img, black_offset=black_offset, white_offset=white_offset, skip_if_no_clip=skip_if_no_clip, high_precision=precision)
|
|
|
|
if dither_quantization or error_diffusion or normalize_midpeaks:
|
|
pil_img = img_dithering.img_dithering(image=pil_img, dither_quantization=dither_quantization, adaptive_dither_strength=adaptive_dither_strength, error_diffusion=error_diffusion, normalize_midpeaks=normalize_midpeaks, peak_width=peak_width, high_precision=precision)
|
|
|
|
if use_ai_detection_bypasser:
|
|
pil_img = isgen_detect_ext_full.bypass_ai_detector(image=pil_img, freq_strength=adb_freq_strength, variance_strength=adb_variance_strength, unsharp_percent=adb_unsharp_percent, jpeg_cycles=adb_jpeg_cycles)
|
|
|
|
histogram.rasterix_hist_cache_store(pil_img_input, pil_img, precision)
|
|
if show_histogram:
|
|
histogram.rasterix_hist_cache_store(pil_img_input, pil_img, precision)
|
|
active_hist = histogram.rasterix_hist_render_selected(pil_img_input, pil_img, precision, histogram_source, histogram_channel, histogram_style,)
|
|
suffix = ''.join(random.choice("abcdefghijklmnopqrstuvwxyz0123456789") for _ in range(8))
|
|
temp_file = f"rasterix_hist_{suffix}.png"
|
|
active_hist.save(os.path.join(folder_paths.temp_directory, temp_file), compress_level=1)
|
|
# return {"ui": {"images": [{"filename": temp_file, "subfolder": "", "type": "temp"}]}, "result": (utility.image_to_tensor(pil_img),), }
|
|
return {"ui": {"images": [{"filename": temp_file, "subfolder": "", "type": "temp"}], "active_concept": [active_display]}, "result": (utility.image_to_tensor(pil_img),), }
|
|
else:
|
|
INVALID_IMAGE_PATH = os.path.join(PRIMERE_ROOT, 'front_end', 'images')
|
|
INVALID_IMAGE = os.path.join(INVALID_IMAGE_PATH, "No_histogram_08.jpg")
|
|
images = utility.ImageLoaderFromPath(INVALID_IMAGE)
|
|
r1 = random.randint(1000, 9999)
|
|
temp_filename = f"Primere_ComfyUI_{r1}.png"
|
|
os.makedirs(folder_paths.get_temp_directory(), exist_ok=True)
|
|
TEMP_FILE = os.path.join(folder_paths.get_temp_directory(), temp_filename)
|
|
utility.tensor_to_image(images[0]).save(TEMP_FILE)
|
|
# return {"ui": {"images": [{"filename": temp_filename, "subfolder": "", "type": "temp"}]}, "result": (utility.image_to_tensor(pil_img),),}
|
|
return {"ui": {"images": [{"filename": temp_filename, "subfolder": "", "type": "temp"}], "active_concept": [active_display]}, "result": (utility.image_to_tensor(pil_img),),}
|
|
|
|
class PrimereAutoNormalize:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_auto_normalize"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"precision": ("BOOLEAN", {"default": False, "label_off": "8 bit", "label_on": "16 bit"}),
|
|
"auto_normalize": ("BOOLEAN", {"default": False, "label_off": "No auto levels", "label_on": "Apply auto levels"}),
|
|
"auto_levels_threshold": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 10.0, "step": 0.1}),
|
|
"auto_gamma": ("BOOLEAN", {"default": False, "label_on": "Auto gamma: ON", "label_off": "Auto gamma:: OFF"}),
|
|
"gamma_target": ("FLOAT", {"default": 128.0, "min": 0.0, "max": 255.0, "step": 0.1}),
|
|
"normalize_gaps": ("BOOLEAN", {"default": False, "label_on": "Anti-comb filter: ON", "label_off": "Anti-comb filter: OFF"}),
|
|
"normalize_midpeaks": ("BOOLEAN", {"default": False, "label_on": "Anti-spike filter: ON", "label_off": "Anti-spike filter: OFF"}),
|
|
"peak_width": ("INT", {"default": 3, "min": 1, "max": 10, "step": 1}),
|
|
}
|
|
}
|
|
|
|
def primere_auto_normalize(self, image, precision, auto_normalize, auto_levels_threshold, auto_gamma, gamma_target, normalize_gaps, normalize_midpeaks, peak_width):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if auto_normalize:
|
|
pil_img = img_levels_auto.img_levels_auto(image=pil_img, auto_normalize=auto_normalize, threshold=auto_levels_threshold, normalize_gaps=normalize_gaps, normalize_midpeaks=normalize_midpeaks, peak_width=peak_width, auto_gamma=auto_gamma, gamma_target=gamma_target, precision=precision)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereWhiteBalance:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_white_balance"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_white_balance": ("BOOLEAN", {"default": False, "label_off": "Ignore white balance", "label_on": "Apply white balance"}),
|
|
"wb_temperature": ("FLOAT", {"default": 6500, "min": 2000, "max": 12000, "step": 100}),
|
|
"wb_tint": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
}
|
|
}
|
|
|
|
def primere_white_balance(self, image, use_white_balance, wb_temperature, wb_tint):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_white_balance and (wb_temperature != 6500 or wb_tint != 0):
|
|
pil_img = img_white_balance.img_white_balance(image=pil_img, temperature=wb_temperature, tint=wb_tint)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereSmartLighting:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_smart_lighting"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_smart_lighting": ("BOOLEAN", {"default": False, "label_off": "Ignore smart lightning", "label_on": "Apply smart lightning"}),
|
|
"smart_lighting": ("FLOAT", {"default": 0, "min": 0, "max": 100, "step": 1}),
|
|
}
|
|
}
|
|
|
|
def primere_smart_lighting(self, image, use_smart_lighting, smart_lighting):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_smart_lighting and smart_lighting != 0:
|
|
pil_img = img_smart_lighting.img_smart_lighting(image=pil_img, intensity=smart_lighting)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereBlur:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_blur"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_blur": ("BOOLEAN", {"default": False, "label_off": "Ignore blur", "label_on": "Apply blur"}),
|
|
"blur_type": (["gaussian", "box", "motion", "bilateral", "lens"], {"default": "bilateral"}),
|
|
"blur_intensity": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 5.0, "step": 0.1}),
|
|
"blur_radius": ("FLOAT", {"default": 2.0, "min": 0.5, "max": 50.0, "step": 0.5}),
|
|
"angle": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 360.0, "step": 1.0}),
|
|
"bilateral_edge_sensitivity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"blur_edge_only": ("BOOLEAN", {"default": False, "label_off": "Full image blur", "label_on": "Flat areas only, edges protected"}),
|
|
"edge_threshold": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
}
|
|
}
|
|
|
|
def primere_blur(self, image, use_blur, blur_type, blur_intensity, blur_radius, angle, bilateral_edge_sensitivity, blur_edge_only, edge_threshold):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_blur and blur_intensity != 0:
|
|
pil_img = img_blur.img_blur(image=pil_img, blur_type=blur_type, intensity=blur_intensity, radius=blur_radius, angle=angle, edge_only=blur_edge_only, bilateral_edge_sensitivity=bilateral_edge_sensitivity, edge_threshold=edge_threshold)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereBrightnessContrast:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_brightness_contrast"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_brightness_contrast": ("BOOLEAN", {"default": False, "label_off": "Ignore brightness-contrast", "label_on": "Apply brightness-contrast"}),
|
|
"brightness": ("FLOAT", {"default": 0, "min": -150, "max": 150, "step": 1}),
|
|
"contrast": ("FLOAT", {"default": 0, "min": -50, "max": 100, "step": 1}),
|
|
"use_legacy": ("BOOLEAN", {"default": False, "label_off": "Use non-linear shift", "label_on": "Use adaptive offset"}),
|
|
}
|
|
}
|
|
|
|
def primere_brightness_contrast(self, image, use_brightness_contrast, brightness, contrast, use_legacy):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_brightness_contrast and (brightness != 0 or contrast != 0):
|
|
pil_img = img_brightness_contrast.img_brightness_contrast(image=pil_img, brightness=brightness, contrast=contrast, use_legacy=use_legacy)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereFilmRendering:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_film_rendering"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_film_rendering": ("BOOLEAN", {"default": False, "label_off": "Ignore film rendering", "label_on": "Apply film rendering"}),
|
|
"film_rendering": (list(FILM_PRESETS.keys()), {"default": list(FILM_PRESETS.keys())[0]}),
|
|
"film_rendering_intensity": ("FLOAT", {"default": 100, "min": 0, "max": 200, "step": 1}),
|
|
"iso_grain": ("BOOLEAN", {"default": False, "label_off": "Ignore ISO grain", "label_on": "Add ISO grain"}),
|
|
"halation": ("BOOLEAN", {"default": False, "label_off": "Ignore halation", "label_on": "Add halation"}),
|
|
"expiration_years": ("INT", {"default": 0, "min": 0, "max": 30, "step": 1}),
|
|
}
|
|
}
|
|
|
|
def primere_film_rendering(self, image, use_film_rendering, film_rendering, film_rendering_intensity, iso_grain, halation, expiration_years):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_film_rendering and film_rendering_intensity != 0:
|
|
pil_img = img_film_rendering.img_film_rendering(image=pil_img, rendering=film_rendering, intensity=film_rendering_intensity, add_grain=iso_grain, add_halation=halation, expiration_years=expiration_years)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereSelectiveTone:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_selective_tone"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_selective_tone": ("BOOLEAN", {"default": False, "label_off": "Ignore selective tone", "label_on": "Apply selective tone"}),
|
|
"selective_tone_value": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"selective_tone_zone": (["highlights", "midtones", "shadows", "blacks"], {"default": "midtones"}),
|
|
"selective_tone_separation": ("FLOAT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
"selective_tone_strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
}
|
|
}
|
|
|
|
def primere_selective_tone(self, image, use_selective_tone, selective_tone_value, selective_tone_zone, selective_tone_separation, selective_tone_strength):
|
|
pil_img = utility.tensor_to_image(image)
|
|
rasterix_json_path = os.path.join(PRIMERE_ROOT, 'front_end', 'rasterix.json')
|
|
rasterix_data = utility.json2tuple(rasterix_json_path) or {}
|
|
st_data = rasterix_data.get('selective_tone', {})
|
|
if use_selective_tone and st_data:
|
|
pil_img = img_selective_tone.img_selective_tone(image=pil_img, channels_data=st_data, separation=selective_tone_separation, strength=selective_tone_strength)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereColorBalance:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_color_balance"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_color_balance": ("BOOLEAN", {"default": False, "label_off": "Ignore color balance", "label_on": "Apply color balance"}),
|
|
"color_balance_cyan_red": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"color_balance_magenta_green": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"color_balance_yellow_blue": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"color_balance_tone": (["highlights", "midtones", "shadows"], {"default": "midtones"}),
|
|
"color_balance_preserve_luminosity": ("BOOLEAN", {"default": False, "label_off": "Modify luminosity", "label_on": "Restore original luminosity"}),
|
|
"color_balance_separation": ("FLOAT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
}
|
|
}
|
|
|
|
def primere_color_balance(self, image, use_color_balance, color_balance_cyan_red, color_balance_magenta_green, color_balance_yellow_blue, color_balance_tone, color_balance_preserve_luminosity, color_balance_separation):
|
|
pil_img = utility.tensor_to_image(image)
|
|
rasterix_json_path = os.path.join(PRIMERE_ROOT, 'front_end', 'rasterix.json')
|
|
rasterix_data = utility.json2tuple(rasterix_json_path) or {}
|
|
cb_data = rasterix_data.get('color_balance', {})
|
|
if use_color_balance and cb_data:
|
|
pil_img = img_color_balance.img_color_balance(image=pil_img, channels_data=cb_data, preserve_luminosity=color_balance_preserve_luminosity, separation=color_balance_separation)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereHSL:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_hsl"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_hsl": ("BOOLEAN", {"default": False, "label_off": "Ignore HSL", "label_on": "Apply HSL"}),
|
|
"hsl_hue": ("FLOAT", {"default": 0, "min": -180, "max": 180, "step": 1}),
|
|
"hsl_saturation": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"hsl_lightness": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"hsl_vibrance": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"hsl_channel": (["master", "red", "green", "blue"], {"default": "master"}),
|
|
"hsl_channel_width": ("FLOAT", {"default": 50, "min": 0, "max": 100, "step": 1}),
|
|
"hsl_skin_protection": ("BOOLEAN", {"default": True, "label_off": "Vibrance affects skin tones", "label_on": "Skin tones protected from vibrance"}),
|
|
}
|
|
}
|
|
|
|
def primere_hsl(self, image, use_hsl, hsl_hue, hsl_saturation, hsl_lightness, hsl_vibrance, hsl_channel, hsl_channel_width, hsl_skin_protection):
|
|
pil_img = utility.tensor_to_image(image)
|
|
rasterix_json_path = os.path.join(PRIMERE_ROOT, 'front_end', 'rasterix.json')
|
|
rasterix_data = utility.json2tuple(rasterix_json_path) or {}
|
|
hs_data = rasterix_data.get('hue_saturation', {})
|
|
if use_hsl and hs_data:
|
|
pil_img = img_hue_saturation.img_hue_saturation(image=pil_img, channels_data=hs_data, channel_width=hsl_channel_width, skin_protection=hsl_skin_protection)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereShadeDetailer:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_shade_detailer"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_shade_detailer": ("BOOLEAN", {"default": False, "label_off": "Ignore shade detailer", "label_on": "Apply shade detailer"}),
|
|
"shade_level": ("FLOAT", {"default": 0, "min": -100, "max": 100, "step": 1}),
|
|
"shade_radius": ("FLOAT", {"default": 0, "min": 0, "max": 50, "step": 0.5}),
|
|
"detail_mode": (["fine", "medium", "broad"], {"default": "medium"}),
|
|
"shade_strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
}
|
|
}
|
|
|
|
def primere_shade_detailer(self, image, use_shade_detailer, shade_level, shade_radius, detail_mode, shade_strength):
|
|
pil_img = utility.tensor_to_image(image)
|
|
rasterix_json_path = os.path.join(PRIMERE_ROOT, 'front_end', 'rasterix.json')
|
|
rasterix_data = utility.json2tuple(rasterix_json_path) or {}
|
|
shade_data = rasterix_data.get('shade', {})
|
|
if use_shade_detailer and shade_data:
|
|
for mode, vals in shade_data.items():
|
|
lvl = vals.get('shade_level', 0)
|
|
if lvl != 0:
|
|
rad = vals.get('shade_radius', 0)
|
|
pil_img = img_shade_level.img_shade_level(image=pil_img, shade_level=lvl, radius=rad, strength=shade_strength)
|
|
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereLevelEndpoints:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_level_endpoints"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"precision": ("BOOLEAN", {"default": False, "label_off": "8 bit", "label_on": "16 bit"}),
|
|
"use_level_endpoints": ("BOOLEAN", {"default": False, "label_off": "Ignore endpoint offset", "label_on": "Apply endpoint offset"}),
|
|
"black_offset": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 25.0, "step": 0.1}),
|
|
"white_offset": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 25.0, "step": 0.1}),
|
|
"skip_if_no_clip": ("BOOLEAN", {"default": False, "label_off": "Offset all values", "label_on": "Skip if no clips"}),
|
|
}
|
|
}
|
|
|
|
def primere_level_endpoints(self, image, precision, use_level_endpoints, black_offset, white_offset, skip_if_no_clip):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_level_endpoints and (black_offset != 0 or white_offset != 0):
|
|
pil_img = img_levels_compress.img_levels_compress(image=pil_img, black_offset=black_offset, white_offset=white_offset, skip_if_no_clip=skip_if_no_clip, high_precision=precision)
|
|
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereDithering:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_dithering"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"precision": ("BOOLEAN", {"default": False, "label_off": "8 bit", "label_on": "16 bit"}),
|
|
"normalize_midpeaks": ("BOOLEAN", {"default": False, "label_on": "Anti-spike filter: ON", "label_off": "Anti-spike filter: OFF"}),
|
|
"peak_width": ("INT", {"default": 3, "min": 1, "max": 10, "step": 1}),
|
|
"dither_quantization": ("BOOLEAN", {"default": False, "label_off": "Dither quantization OFF", "label_on": "Dither quantization ON"}),
|
|
"adaptive_dither_strength": ("BOOLEAN", {"default": False, "label_off": "Keep dither strength", "label_on": "Increase dither strength"}),
|
|
"error_diffusion": ("BOOLEAN", {"default": False, "label_off": "Error diffusion OFF", "label_on": "Error diffusion ON"}),
|
|
}
|
|
}
|
|
|
|
def primere_dithering(self, image, precision, normalize_midpeaks, peak_width, dither_quantization, adaptive_dither_strength, error_diffusion):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if dither_quantization or error_diffusion or normalize_midpeaks:
|
|
pil_img = img_dithering.img_dithering(image=pil_img, dither_quantization=dither_quantization, adaptive_dither_strength=adaptive_dither_strength, error_diffusion=error_diffusion, normalize_midpeaks=normalize_midpeaks, peak_width=peak_width, high_precision=precision)
|
|
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereAIDetectionBypasser:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_ai_detection_bypasser"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"use_ai_detection_bypasser": ("BOOLEAN", {"default": False, "label_off": "AI detection bypass off", "label_on": "AI detection bypass on"}),
|
|
"adb_freq_strength": ("FLOAT", {"default": 0.019, "min": 0.0, "max": 0.1, "step": 0.001}),
|
|
"adb_variance_strength": ("FLOAT", {"default": 0.32, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"adb_unsharp_percent": ("INT", {"default": 38, "min": 0, "max": 150, "step": 1}),
|
|
"adb_jpeg_cycles": ("INT", {"default": 4, "min": 0, "max": 6, "step": 1}),
|
|
}
|
|
}
|
|
|
|
def primere_ai_detection_bypasser(self, image, use_ai_detection_bypasser, adb_freq_strength, adb_variance_strength, adb_unsharp_percent, adb_jpeg_cycles):
|
|
pil_img = utility.tensor_to_image(image)
|
|
if use_ai_detection_bypasser:
|
|
pil_img = isgen_detect_ext_full.bypass_ai_detector(image=pil_img, freq_strength=adb_freq_strength, variance_strength=adb_variance_strength, unsharp_percent=adb_unsharp_percent, jpeg_cycles=adb_jpeg_cycles)
|
|
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
class PrimereRasterixGrain:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_rasterix_grain"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
|
|
"use_grain": ("BOOLEAN", {"default": False, "label_off": "Ignore grain", "label_on": "Apply grain"}),
|
|
"intensity": ("FLOAT", {"default": 20.0, "min": 0.0, "max": 100.0, "step": 0.5}),
|
|
"grain_size": ("FLOAT", {"default": 1.0, "min": 0.5, "max": 8.0, "step": 0.1}),
|
|
"grain_type": (["gaussian", "organic", "salt_pepper", "fine"], {"default": "gaussian"}),
|
|
"color_mode": (["color", "monochrome"], {"default": "color"}),
|
|
"color_tint": (["neutral", "warm", "cool", "green", "custom"], {"default": "neutral"}),
|
|
"color_tint_r": ("FLOAT", {"default": 0, "min": -50, "max": 50, "step": 1}),
|
|
"color_tint_g": ("FLOAT", {"default": 0, "min": -50, "max": 50, "step": 1}),
|
|
"color_tint_b": ("FLOAT", {"default": 0, "min": -50, "max": 50, "step": 1}),
|
|
"shadow_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.05}),
|
|
"highlight_strength": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 3.0, "step": 0.05}),
|
|
"midtone_peak": ("FLOAT", {"default": 0.4, "min": 0.0, "max": 1.0, "step": 0.05}),
|
|
"vignette_boost": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.05}),
|
|
},
|
|
"optional": {
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": utility.MAX_SEED, "forceInput": True}),
|
|
}
|
|
}
|
|
|
|
def primere_rasterix_grain(self, image, use_grain, intensity, grain_size, grain_type, color_mode, color_tint, color_tint_r, color_tint_g, color_tint_b, shadow_strength, highlight_strength, midtone_peak, vignette_boost, seed=None):
|
|
if intensity == 0 or use_grain == False:
|
|
return (image,)
|
|
|
|
pil_img = utility.tensor_to_image(image)
|
|
pil_img = img_film_grain.img_film_grain(
|
|
image=pil_img,
|
|
intensity=intensity,
|
|
grain_size=grain_size,
|
|
grain_type=grain_type,
|
|
color_mode=color_mode,
|
|
color_tint=color_tint,
|
|
color_tint_rgb=(color_tint_r, color_tint_g, color_tint_b),
|
|
shadow_strength=shadow_strength,
|
|
highlight_strength=highlight_strength,
|
|
midtone_peak=midtone_peak,
|
|
vignette_boost=vignette_boost,
|
|
seed=seed,
|
|
)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
|
|
class PrimereRasterixLens:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_rasterix_lens"
|
|
CATEGORY = TREE_RASTERIX
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
|
|
"use_vignette": ("BOOLEAN", {"default": False, "label_off": "Ignore vignette", "label_on": "Apply vignette"}),
|
|
"vignette_strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"vignette_radius": ("FLOAT", {"default": 0.65, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"vignette_feather": ("FLOAT", {"default": 0.4, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"vignette_shape": (["circular", "oval", "corner"], {"default": "circular"}),
|
|
|
|
"use_chroma": ("BOOLEAN", {"default": False, "label_off": "Ignore chromatic aberration", "label_on": "Apply chromatic aberration"}),
|
|
"chroma_intensity": ("FLOAT", {"default": 2.0, "min": 0.0, "max": 10.0, "step": 0.1}),
|
|
"chroma_falloff": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"chroma_fringe_color": (["red_blue", "green_magenta", "yellow_purple"], {"default": "red_blue"}),
|
|
|
|
"use_bokeh": ("BOOLEAN", {"default": False, "label_off": "Ignore bokeh", "label_on": "Apply bokeh"}),
|
|
"bokeh_radius": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 40.0, "step": 0.5}),
|
|
"bokeh_blades": ("INT", {"default": 0, "min": 0, "max": 12, "step": 1}),
|
|
"bokeh_highlight_boost": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"bokeh_cat_eye": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
|
|
"use_distortion": ("BOOLEAN", {"default": False, "label_off": "Ignore lens distortion", "label_on": "Apply lens distortion"}),
|
|
"distortion_barrel": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"distortion_pincushion": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"distortion_zoom": ("FLOAT", {"default": 1.0, "min": 0.5, "max": 2.0, "step": 0.01}),
|
|
|
|
"use_flare": ("BOOLEAN", {"default": False, "label_off": "Ignore lens flare", "label_on": "Apply lens flare"}),
|
|
"flare_intensity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"flare_pos_x": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"flare_pos_y": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"flare_streak_count": ("INT", {"default": 6, "min": 2, "max": 12, "step": 1}),
|
|
"flare_streak_length":("FLOAT", {"default": 0.4, "min": 0.1, "max": 1.0, "step": 0.01}),
|
|
"flare_ghost_count": ("INT", {"default": 4, "min": 0, "max": 8, "step": 1}),
|
|
"flare_color": (["warm", "cool", "neutral", "rainbow"], {"default": "warm"}),
|
|
|
|
"use_halation": ("BOOLEAN", {"default": False, "label_off": "Ignore halation", "label_on": "Apply halation"}),
|
|
"halation_intensity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"halation_radius": ("FLOAT", {"default": 15.0, "min": 2.0, "max": 50.0, "step": 0.5}),
|
|
"halation_threshold": ("FLOAT", {"default": 0.75, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"halation_warmth": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
|
|
"use_focus": ("BOOLEAN", {"default": False, "label_off": "Ignore focus falloff", "label_on": "Apply focus falloff"}),
|
|
"focus_blur_radius": ("FLOAT", {"default": 8.0, "min": 0.0, "max": 30.0, "step": 0.5}),
|
|
"focus_mode": (["horizontal", "vertical", "radial", "oval"], {"default": "horizontal"}),
|
|
"focus_pos": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"focus_width": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"focus_feather": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
|
|
"use_spherical": ("BOOLEAN", {"default": False, "label_off": "Ignore spherical aberration", "label_on": "Apply spherical aberration"}),
|
|
"spherical_intensity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"spherical_radius": ("FLOAT", {"default": 3.0, "min": 0.5, "max": 15.0, "step": 0.5}),
|
|
"spherical_zone": (["centre", "edge", "global"], {"default": "centre"}),
|
|
|
|
"use_anamorphic": ("BOOLEAN", {"default": False, "label_off": "Ignore anamorphic", "label_on": "Apply anamorphic"}),
|
|
"anamorphic_intensity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"anamorphic_streak_color": (["blue", "warm", "white"], {"default": "blue"}),
|
|
"anamorphic_streak_length": ("FLOAT", {"default": 0.8, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"anamorphic_oval_bokeh": ("FLOAT", {"default": 0.4, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"anamorphic_blue_bias": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
}
|
|
}
|
|
|
|
def primere_rasterix_lens(self, image, use_vignette, vignette_strength, vignette_radius, vignette_feather, vignette_shape, use_chroma, chroma_intensity, chroma_falloff, chroma_fringe_color, use_bokeh, bokeh_radius, bokeh_blades, bokeh_highlight_boost, bokeh_cat_eye, use_distortion, distortion_barrel, distortion_pincushion, distortion_zoom, use_flare, flare_intensity, flare_pos_x, flare_pos_y, flare_streak_count, flare_streak_length, flare_ghost_count, flare_color, use_halation, halation_intensity, halation_radius, halation_threshold, halation_warmth, use_focus, focus_blur_radius, focus_mode, focus_pos, focus_width, focus_feather, use_spherical, spherical_intensity, spherical_radius, spherical_zone, use_anamorphic, anamorphic_intensity, anamorphic_streak_color, anamorphic_streak_length, anamorphic_oval_bokeh, anamorphic_blue_bias):
|
|
pil_img = utility.tensor_to_image(image)
|
|
pil_img = img_lens_effects.img_lens_effect(
|
|
image=pil_img,
|
|
vignette_strength=vignette_strength if use_vignette else 0,
|
|
vignette_radius=vignette_radius,
|
|
vignette_feather=vignette_feather,
|
|
vignette_shape=vignette_shape,
|
|
chroma_intensity=chroma_intensity if use_chroma else 0,
|
|
chroma_falloff=chroma_falloff,
|
|
chroma_fringe_color=chroma_fringe_color,
|
|
bokeh_radius=bokeh_radius if use_bokeh else 0,
|
|
bokeh_blades=bokeh_blades,
|
|
bokeh_highlight_boost=bokeh_highlight_boost,
|
|
bokeh_cat_eye=bokeh_cat_eye,
|
|
distortion_barrel=distortion_barrel if use_distortion else 0,
|
|
distortion_pincushion=distortion_pincushion if use_distortion else 0,
|
|
distortion_zoom=distortion_zoom,
|
|
flare_intensity=flare_intensity if use_flare else 0,
|
|
flare_pos_x=flare_pos_x,
|
|
flare_pos_y=flare_pos_y,
|
|
flare_streak_count=flare_streak_count,
|
|
flare_streak_length=flare_streak_length,
|
|
flare_ghost_count=flare_ghost_count,
|
|
flare_color=flare_color,
|
|
halation_intensity=halation_intensity if use_halation else 0,
|
|
halation_radius=halation_radius,
|
|
halation_threshold=halation_threshold,
|
|
halation_warmth=halation_warmth,
|
|
focus_blur_radius=focus_blur_radius if use_focus else 0,
|
|
focus_mode=focus_mode,
|
|
focus_pos=focus_pos,
|
|
focus_width=focus_width,
|
|
focus_feather=focus_feather,
|
|
spherical_intensity=spherical_intensity if use_spherical else 0,
|
|
spherical_radius=spherical_radius,
|
|
spherical_zone=spherical_zone,
|
|
anamorphic_intensity=anamorphic_intensity if use_anamorphic else 0,
|
|
anamorphic_streak_color=anamorphic_streak_color,
|
|
anamorphic_streak_length=anamorphic_streak_length,
|
|
anamorphic_oval_bokeh=anamorphic_oval_bokeh,
|
|
anamorphic_blue_bias=anamorphic_blue_bias,
|
|
)
|
|
return (utility.image_to_tensor(pil_img),)
|
|
|
|
class PrimereHistogram:
|
|
RETURN_TYPES = ("IMAGE",)
|
|
RETURN_NAMES = ("IMAGE",)
|
|
FUNCTION = "primere_histogram"
|
|
CATEGORY = TREE_RASTERIX
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE", {"forceInput": True}),
|
|
"precision": ("BOOLEAN", {"default": False, "label_off": "8 bit", "label_on": "16 bit"}),
|
|
"show_histogram": ("BOOLEAN", {"default": False, "label_off": "Ignore histogram", "label_on": "Create histogram"}),
|
|
# "histogram_source": ("BOOLEAN", {"default": False, "label_off": "Show output histogram", "label_on": "Show input histogram"}),
|
|
"histogram_channel": (["RGB", "RED", "GREEN", "BLUE"], {"default": "RGB"}),
|
|
"histogram_style": (["bars", "lines", "waveform", "heatmap", "stacked", "luma", "parade", "gradient", "glow", "dots", "step", "log", "percentile", "inverse"], {"default": "bars"}),
|
|
}
|
|
}
|
|
|
|
def primere_histogram(self, image, precision, show_histogram=False, histogram_channel="RGB", histogram_style="bars"):
|
|
pil_img = utility.tensor_to_image(image)
|
|
pil_img_input = pil_img.copy()
|
|
|
|
histogram.rasterix_hist_cache_store(pil_img_input, pil_img, precision)
|
|
|
|
if show_histogram:
|
|
histogram.rasterix_hist_cache_store(pil_img_input, pil_img, precision)
|
|
active_hist = histogram.rasterix_hist_render_selected(pil_img_input, pil_img, precision, True, histogram_channel, histogram_style,)
|
|
suffix = ''.join(random.choice("abcdefghijklmnopqrstuvwxyz0123456789") for _ in range(8))
|
|
temp_file = f"rasterix_hist_{suffix}.png"
|
|
active_hist.save(os.path.join(folder_paths.temp_directory, temp_file), compress_level=1)
|
|
return {"ui": {"images": [{"filename": temp_file, "subfolder": "", "type": "temp"}]}, "result": (utility.image_to_tensor(pil_img),), }
|
|
else:
|
|
INVALID_IMAGE_PATH = os.path.join(PRIMERE_ROOT, 'front_end', 'images')
|
|
INVALID_IMAGE = os.path.join(INVALID_IMAGE_PATH, "No_histogram_08.jpg")
|
|
images = utility.ImageLoaderFromPath(INVALID_IMAGE)
|
|
r1 = random.randint(1000, 9999)
|
|
temp_filename = f"Primere_ComfyUI_{r1}.png"
|
|
os.makedirs(folder_paths.get_temp_directory(), exist_ok=True)
|
|
TEMP_FILE = os.path.join(folder_paths.get_temp_directory(), temp_filename)
|
|
utility.tensor_to_image(images[0]).save(TEMP_FILE)
|
|
return {"ui": {"images": [{"filename": temp_filename, "subfolder": "", "type": "temp"}]}, "result": (utility.image_to_tensor(pil_img),),} |