diff --git a/README.MD b/README.MD
index 0525d2a..d6b0659 100644
--- a/README.MD
+++ b/README.MD
@@ -80,6 +80,7 @@ When this error has occurred, please check the network environment.
## Update
**If the dependency package error after updating, please reinstall the relevant dependency packages.
+* [LUT Apply](#LUT) Add the street parameter.
* Commit [AutoAdjustV2](#AutoAdjustV2) node, add optional mask input and support for multiple automatic color adjustment modes.
* Due to the upcoming discontinuation of gemini-pro vision services, [PromptTagger](#PromptTagger) and [PromptEmbellish](#PromptEmbellish) have added the "gemini-1.5-flash" API to continue using it.
* [Ultra](#Ultra) nodes added the option to run ```VitMatte``` on the CUDA device, resulting in a 5-fold increase in running speed.
@@ -356,11 +357,13 @@ Node options:
### LUT Apply
Apply LUT to the image. only supports .cube format.
+
Node options:

* LUT*: Here is a list of available. cube files in the LUT folder, and the selected LUT files will be applied to the image.
* color_space: For regular image, please select linear, for image in the log color space, please select log.
+* strength: Range 0~100, LUT application strength. The larger the value, the greater the difference from the original image, and the smaller the value, the closer it is to the original image.
*LUT folder is defined in ```resource_dir.ini```, this file is located in the root directory of the plug-in, and the default name is ```resource_dir.ini.example```. to use this file for the first time, you need to change the file suffix to ```.ini```.
Open the text editing software and find the line starting with "LUT_dir=", after "=", enter the custom folder path name. all .cube files in this folder will be collected and displayed in the node list during ComfyUI initialization.
diff --git a/README_CN.MD b/README_CN.MD
index c4db12b..ea077f7 100644
--- a/README_CN.MD
+++ b/README_CN.MD
@@ -80,6 +80,7 @@ git clone https://github.com/chflame163/ComfyUI_LayerStyle.git
## 更新说明
**如果本插件更新后出现依赖包错误,请重新安装相关依赖包。
+* [LUT Apply](#LUT) 节点增加strenght参数。
* 添加 [AutoAdjustV2](#AutoAdjustV2) 节点,增加可选遮罩输入,增加多种自动调色模式支持。
* 由于gemini-pro-vision即将停止服务, [PromptTagger](#PromptTagger) 和 [PromptEmbellish](#PromptEmbellish) 添加"gemini-1.5-flash" API以继续使用。
* [Ultra](#Ultra) 节点增加```VitMatte```方法在CUDA设备运行选项,运行速度提升5倍。
@@ -357,6 +358,7 @@ git clone https://github.com/chflame163/ComfyUI_LayerStyle.git

* LUT*: 这里列出了LUT文件夹中可用的.cube文件列表,选中的LUT文件将被应用到图像。
* color_space: 普通图片请选择linear, log色彩空间的图片请选择log。
+* strength: 范围0~100, LUT应用强度。数值越大,与原图的差别越大, 数值越小,越接近原图。
*LUT文件夹在```resource_dir.ini```中定义,这个文件位于插件根目录下, 默认名字是```resource_dir.ini.example```, 初次使用这个文件需将文件后缀改为.ini。用文本编辑软件打开,找到“LUT_dir=”开头的这一行,编辑“=”之后为自定义文件夹路径名。这个文件夹里面所有的.cube文件将在ComfyUI初始化时被收集并显示在节点的列表中。如果ini中设定的文件夹无效,将启用插件自带的LUT文件夹。
diff --git a/image/lut_apply_example.jpg b/image/lut_apply_example.jpg
index 659dc55..5c61f39 100644
Binary files a/image/lut_apply_example.jpg and b/image/lut_apply_example.jpg differ
diff --git a/image/lut_apply_node.jpg b/image/lut_apply_node.jpg
index 181e589..7f2747d 100644
Binary files a/image/lut_apply_node.jpg and b/image/lut_apply_node.jpg differ
diff --git a/py/color_correct_LUTapply.py b/py/color_correct_LUTapply.py
index 15dedea..2d28df2 100644
--- a/py/color_correct_LUTapply.py
+++ b/py/color_correct_LUTapply.py
@@ -15,6 +15,7 @@ class ColorCorrectLUTapply:
"image": ("IMAGE", ), #
"LUT": (LUT_LIST,), # LUT文件
"color_space": (color_space_list,),
+ "strength": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}),
},
"optional": {
}
@@ -25,14 +26,14 @@ class ColorCorrectLUTapply:
FUNCTION = 'color_correct_LUTapply'
CATEGORY = '😺dzNodes/LayerColor'
- def color_correct_LUTapply(self, image, LUT, color_space):
+ def color_correct_LUTapply(self, image, LUT, color_space, strength):
ret_images = []
for i in image:
i = torch.unsqueeze(i, 0)
_image = tensor2pil(i)
lut_file = LUT_DICT[LUT]
- ret_image = apply_lut(_image, lut_file, log=(color_space == 'log'))
+ ret_image = apply_lut(_image, lut_file=lut_file, colorspace=color_space, strength=strength)
if _image.mode == 'RGBA':
ret_image = RGB2RGBA(ret_image, _image.split()[-1])
diff --git a/py/imagefunc.py b/py/imagefunc.py
index 3015126..ceb400f 100644
--- a/py/imagefunc.py
+++ b/py/imagefunc.py
@@ -1077,29 +1077,79 @@ def gamma_trans(image:Image, gamma:float) -> Image:
_corrected = cv2.LUT(cv2_image,gamma_table)
return cv22pil(_corrected)
-def apply_lut(image:Image, lut_file:str, log:bool=False) -> Image:
- from colour.io.luts.iridas_cube import read_LUT_IridasCube, LUT3D, LUT3x1D
- lut: Union[LUT3x1D, LUT3D] = read_LUT_IridasCube(lut_file)
- lut.name = os.path.splitext(os.path.basename(lut_file))[0] # use base filename instead of internal LUT name
+# def apply_lut(image:Image, lut_file:str, log:bool=False) -> Image:
+# from colour.io.luts.iridas_cube import read_LUT_IridasCube, LUT3D, LUT3x1D
+# lut: Union[LUT3x1D, LUT3D] = read_LUT_IridasCube(lut_file)
+# lut.name = os.path.splitext(os.path.basename(lut_file))[0] # use base filename instead of internal LUT name
+#
+# im_array = np.asarray(image.convert('RGB'), dtype=np.float32) / 255
+# is_non_default_domain = not np.array_equal(lut.domain, np.array([[0., 0., 0.], [1., 1., 1.]]))
+# dom_scale = None
+# if is_non_default_domain:
+# dom_scale = lut.domain[1] - lut.domain[0]
+# im_array = im_array * dom_scale + lut.domain[0]
+# if log:
+# im_array = im_array ** (1 / 2.2)
+# im_array = lut.apply(im_array)
+# if log:
+# im_array = im_array ** (2.2)
+# if is_non_default_domain:
+# im_array = (im_array - lut.domain[0]) / dom_scale
+# im_array = im_array * 255
+# ret_image = Image.fromarray(np.uint8(im_array))
+#
+# return ret_image
- im_array = np.asarray(image.convert('RGB'), dtype=np.float32) / 255
+def apply_lut(image:Image, lut_file:str, colorspace:str, strength:int, clip_values:bool=True) -> Image:
+ """
+ Apply a LUT to an image.
+ :param image: Image to apply the LUT to.
+ :param lut_file: LUT file to apply.
+ :param colorspace: Colorspace to convert the image to before applying the LUT.
+ :param clip_values: Clip the values of the LUT to the domain of the LUT.
+ :param strength: Strength of the LUT.
+ :return: Image with the LUT applied.
+ """
+ log_colorspace = False
+ if colorspace == "log":
+ log_colorspace = True
+
+ from colour.io.luts.iridas_cube import read_LUT_IridasCube
+
+ lut = read_LUT_IridasCube(lut_file)
+ lut.name = lut_file
+
+ if clip_values:
+ if lut.domain[0].max() == lut.domain[0].min() and lut.domain[1].max() == lut.domain[1].min():
+ lut.table = np.clip(lut.table, lut.domain[0, 0], lut.domain[1, 0])
+ else:
+ if len(lut.table.shape) == 2: # 3x1D
+ for dim in range(3):
+ lut.table[:, dim] = np.clip(lut.table[:, dim], lut.domain[0, dim], lut.domain[1, dim])
+ else: # 3D
+ for dim in range(3):
+ lut.table[:, :, :, dim] = np.clip(lut.table[:, :, :, dim], lut.domain[0, dim], lut.domain[1, dim])
+
+ img = pil2tensor(image)
+ lut_img = img.numpy().copy()
is_non_default_domain = not np.array_equal(lut.domain, np.array([[0., 0., 0.], [1., 1., 1.]]))
dom_scale = None
if is_non_default_domain:
dom_scale = lut.domain[1] - lut.domain[0]
- im_array = im_array * dom_scale + lut.domain[0]
- if log:
- im_array = im_array ** (1 / 2.2)
- im_array = lut.apply(im_array)
- if log:
- im_array = im_array ** (2.2)
+ lut_img = lut_img * dom_scale + lut.domain[0]
+ if log_colorspace:
+ lut_img = lut_img ** (1/2.2)
+ lut_img = lut.apply(lut_img)
+ if log_colorspace:
+ lut_img = lut_img ** (2.2)
if is_non_default_domain:
- im_array = (im_array - lut.domain[0]) / dom_scale
- im_array = im_array * 255
- ret_image = Image.fromarray(np.uint8(im_array))
-
- return ret_image
+ lut_img = (lut_img - lut.domain[0]) / dom_scale
+ lut_img = torch.from_numpy(lut_img)
+ if strength < 100:
+ strength /= 100
+ lut_img = strength * lut_img + (1 - strength) * img
+ return tensor2pil(lut_img)
def color_adapter(image:Image, ref_image:Image) -> Image:
image = pil2cv2(image)