diff --git a/README.MD b/README.MD
index fb30542..55afa70 100644
--- a/README.MD
+++ b/README.MD
@@ -12,6 +12,7 @@ Nodes are divided into four groups according to their functions: LayerStyle, Lay
[中文说明点这里](./README_CN.MD)
## Update
+* Commit [ChannelShake](#ChannelShake) node, that is filter, can produce channel dislocation effect similar like Tiktok logo.
* Commit [MaskGradient](#MaskGradient) node, can create a gradient in the mask.
* Commit [GetColorTone](#GetColorTone) node, can obtain the main color or average color of the image.
Commit [MaskGrow](#MaskGrow) and [MaskEdgeShrink](#MaskEdgeShrink) nodes.
@@ -386,6 +387,16 @@ This node allows any type of input.

+### ChannelShake
+Channel misalignment. similar to the effect of Tiktok logo.
+
+
+Node options:
+
+* distance: Distance of channel separation.
+* angle: Angle of channel separation.
+* mode: Channel shift arrangement order.
+
### MotionBlur
Make the image motion blur

diff --git a/image/channel_shake_example.png b/image/channel_shake_example.png
new file mode 100644
index 0000000..51412e2
Binary files /dev/null and b/image/channel_shake_example.png differ
diff --git a/image/channel_shake_node.png b/image/channel_shake_node.png
new file mode 100644
index 0000000..e7a2391
Binary files /dev/null and b/image/channel_shake_node.png differ
diff --git a/py/channel_shake.py b/py/channel_shake.py
new file mode 100644
index 0000000..35784b8
--- /dev/null
+++ b/py/channel_shake.py
@@ -0,0 +1,60 @@
+import math
+
+from .imagefunc import *
+
+class ChannelShake:
+
+ def __init__(self):
+ pass
+
+ @classmethod
+ def INPUT_TYPES(self):
+ channel_mode = ['RGB', 'RBG', 'BGR', 'BRG', 'GBR', 'GRB']
+ return {
+ "required": {
+ "image": ("IMAGE", ), #
+ "distance": ("INT", {"default": 20, "min": 1, "max": 999, "step": 1}), # 距离
+ "angle": ("FLOAT", {"default": 40, "min": -360, "max": 360, "step": 0.01}), # 角度
+ "mode": (channel_mode,), # 模式
+ },
+ "optional": {
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE",)
+ RETURN_NAMES = ("image",)
+ FUNCTION = 'channel_shake'
+ CATEGORY = '😺dzNodes/LayerFilter'
+ OUTPUT_NODE = True
+
+ def channel_shake(self, image, distance, angle, mode, ):
+
+ _canvas = tensor2pil(image).convert('RGB')
+ R, G, B = _canvas.split()
+ x = int(math.cos(angle) * distance)
+ y = int(math.sin(angle) * distance)
+ if mode.startswith('R'):
+ R = shift_image(R.convert('RGB'), -x, -y).convert('L')
+ if mode.startswith('G'):
+ G = shift_image(G.convert('RGB'), -x, -y).convert('L')
+ if mode.startswith('B'):
+ B = shift_image(B.convert('RGB'), -x, -y).convert('L')
+ if mode.endswith('R'):
+ R = shift_image(R.convert('RGB'), x, y).convert('L')
+ if mode.endswith('G'):
+ G = shift_image(G.convert('RGB'), x, y).convert('L')
+ if mode.endswith('B'):
+ B = shift_image(B.convert('RGB'), x, y).convert('L')
+
+ ret_image = Image.merge('RGB', [R, G, B])
+ log('ChannelShake Processed.')
+
+ return (pil2tensor(ret_image),)
+
+NODE_CLASS_MAPPINGS = {
+ "LayerFilter: ChannelShake": ChannelShake
+}
+
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "LayerFilter: ChannelShake": "LayerFilter: ChannelShake"
+}
\ No newline at end of file
diff --git a/py/imagefunc.py b/py/imagefunc.py
index bb28468..34e1686 100644
--- a/py/imagefunc.py
+++ b/py/imagefunc.py
@@ -153,11 +153,9 @@ def __rotate_expand(image:Image, angle:float, SSAA:int=0, method:str="lanczos")
img_us_scaled = img.resize((width * SSAA, height * SSAA), resize_sampler)
img_rotated = img_us_scaled.rotate(angle, rotate_sampler, expand == "true", fillcolor=(0, 0, 0, 0))
img_down_scaled = img_rotated.resize((img_rotated.width // SSAA, img_rotated.height // SSAA), resize_sampler)
- # result = img_down_scaled.image_to_tensor()
result = pil2tensor(img_down_scaled)
else:
img_rotated = img.rotate(angle, rotate_sampler, expand == "true", fillcolor=(0, 0, 0, 0))
- # result = img_rotated.image_to_tensor()
result = pil2tensor(img_rotated)
return result