fx 完善
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-12-02 14:45:07 +08:00
parent 8e6131473d
commit 40be5ce335
5 changed files with 313 additions and 25 deletions

View File

@ -1,15 +1,167 @@
from PIL import Image, ImageFilter
from PIL import ImageEnhance
class ImageFilterUtils:
from konabot.plugins.fx_process.color_handle import ColorHandle
import math
class ImageFilterImplement:
@staticmethod
def apply_blur(image: Image.Image, radius: float = 5) -> Image.Image:
"""对图像应用模糊效果
def apply_blur(image: Image.Image, radius: float = 10) -> Image.Image:
return image.filter(ImageFilter.GaussianBlur(radius))
# 马赛克
@staticmethod
def apply_mosaic(image: Image.Image, pixel_size: int = 10) -> Image.Image:
if pixel_size <= 0:
pixel_size = 1
# 缩小图像
small_image = image.resize(
(image.width // pixel_size, image.height // pixel_size),
Image.Resampling.NEAREST
)
# 放大图像
return small_image.resize(image.size, Image.Resampling.NEAREST)
@staticmethod
def apply_contour(image: Image.Image) -> Image.Image:
return image.filter(ImageFilter.CONTOUR)
@staticmethod
def apply_sharpen(image: Image.Image) -> Image.Image:
return image.filter(ImageFilter.SHARPEN)
@staticmethod
def apply_edge_enhance(image: Image.Image) -> Image.Image:
return image.filter(ImageFilter.EDGE_ENHANCE)
@staticmethod
def apply_emboss(image: Image.Image) -> Image.Image:
return image.filter(ImageFilter.EMBOSS)
@staticmethod
def apply_find_edges(image: Image.Image) -> Image.Image:
return image.filter(ImageFilter.FIND_EDGES)
@staticmethod
def apply_smooth(image: Image.Image) -> Image.Image:
return image.filter(ImageFilter.SMOOTH)
# 反色
@staticmethod
def apply_invert(image: Image.Image) -> Image.Image:
# 确保图像是RGBA模式保留透明度通道
if image.mode != 'RGBA':
image = image.convert('RGBA')
r, g, b, a = image.split()
r = r.point(lambda i: 255 - i)
g = g.point(lambda i: 255 - i)
b = b.point(lambda i: 255 - i)
return Image.merge('RGBA', (r, g, b, a))
# 黑白灰度
@staticmethod
def apply_black_white(image: Image.Image) -> Image.Image:
# 保留透明度通道
if image.mode != 'RGBA':
image = image.convert('RGBA')
r, g, b, a = image.split()
gray = Image.merge('RGB', (r, g, b)).convert('L')
return Image.merge('RGBA', (gray, gray, gray, a))
# 阈值
@staticmethod
def apply_threshold(image: Image.Image, threshold: int = 128) -> Image.Image:
# 保留透明度通道
if image.mode != 'RGBA':
image = image.convert('RGBA')
r, g, b, a = image.split()
gray = Image.merge('RGB', (r, g, b)).convert('L')
bw = gray.point(lambda x: 255 if x >= threshold else 0, '1')
return Image.merge('RGBA', (bw.convert('L'), bw.convert('L'), bw.convert('L'), a))
# 对比度
@staticmethod
def apply_contrast(image: Image.Image, factor: float = 1.5) -> Image.Image:
enhancer = ImageEnhance.Contrast(image)
return enhancer.enhance(factor)
# 亮度
@staticmethod
def apply_brightness(image: Image.Image, factor: float = 1.5) -> Image.Image:
enhancer = ImageEnhance.Brightness(image)
return enhancer.enhance(factor)
# 色彩
@staticmethod
def apply_color(image: Image.Image, factor: float = 1.5) -> Image.Image:
enhancer = ImageEnhance.Color(image)
return enhancer.enhance(factor)
# 三色调
@staticmethod
def apply_to_color(image: Image.Image, color: str = 'rgb(255,0,0)') -> Image.Image:
if image.mode != 'RGBA':
image = image.convert('RGBA')
# 转为灰度图
gray = image.convert('L')
# 获取目标颜色的RGB值
rgb_color = ColorHandle.parse_color(color)
# 高光默认为白色,阴影默认为黑色
highlight = (255, 255, 255)
shadow = (0, 0, 0)
# 创建新的图像
new_image = Image.new('RGBA', image.size)
width, height = image.size
for x in range(width):
for y in range(height):
lum = gray.getpixel((x, y))
# 计算新颜色
new_r = int((rgb_color[0] * lum + shadow[0] * (highlight[0] - lum)) / 255)
new_g = int((rgb_color[1] * lum + shadow[1] * (highlight[1] - lum)) / 255)
new_b = int((rgb_color[2] * lum + shadow[2] * (highlight[2] - lum)) / 255)
a = image.getpixel((x, y))[3] # 保留原图的透明度
new_image.putpixel((x, y), (new_r, new_g, new_b, a))
return new_image
# 缩放
@staticmethod
def apply_resize(image: Image.Image, scale: float = 1.5) -> Image.Image:
if scale <= 0:
scale = 1.0
new_size = (int(image.width * scale), int(image.height * scale))
return image.resize(new_size, Image.Resampling.LANCZOS)
# 波纹
@staticmethod
def apply_wave(image: Image.Image, amplitude: float = 5, wavelength: float = 20) -> Image.Image:
width, height = image.size
new_image = Image.new('RGBA', (width, height))
for x in range(width):
for y in range(height):
offset_x = int(amplitude * math.sin(2 * math.pi * y / wavelength))
offset_y = int(amplitude * math.cos(2 * math.pi * x / wavelength))
new_x = x + offset_x
new_y = y + offset_y
if 0 <= new_x < width and 0 <= new_y < height:
new_image.putpixel((x, y), image.getpixel((new_x, new_y)))
else:
new_image.putpixel((x, y), (0, 0, 0, 0)) # 透明像素
return new_image
参数:
image: 要处理的Pillow图像对象
radius: 模糊半径,值越大模糊效果越明显
返回:
处理后的Pillow图像对象
"""
return image.filter(ImageFilter.GaussianBlur(radius))
def apply_color_key(image: Image.Image, target_color: str = 'rgb(255,0,0)', tolerance: int = 60) -> Image.Image:
if image.mode != 'RGBA':
image = image.convert('RGBA')
target_rgb = ColorHandle.parse_color(target_color)
width, height = image.size
new_image = Image.new('RGBA', (width, height))
for x in range(width):
for y in range(height):
r, g, b, a = image.getpixel((x, y))
# 计算与目标颜色的距离
distance = math.sqrt((r - target_rgb[0]) ** 2 + (g - target_rgb[1]) ** 2 + (b - target_rgb[2]) ** 2)
if distance <= tolerance:
new_image.putpixel((x, y), (r, g, b, 0)) # 设置为透明
else:
new_image.putpixel((x, y), (r, g, b, a)) # 保留原像素
return new_image