zhenxun_bot/plugins/update_pic.py

251 lines
12 KiB
Python
Raw Normal View History

2021-05-20 18:37:51 +08:00
from nonebot import on_command
from PIL import Image, ImageFilter
from util.init_result import image
from configs.path_config import IMAGE_PATH
from services.log import logger
from nonebot.rule import to_me
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.typing import T_State
from util.utils import get_message_imgs
import aiofiles
import aiohttp
from util.utils import is_number, get_message_text
from util.img_utils import CreateImg, pic2b64
import cv2
import numpy as np
__plugin_name__ = '图片'
__plugin_usage__ = '''图片用法(目前):
可以输入 指定操作 序号 来进行选择
1.修改尺寸 (x) (y) 图片(在文字后跟图片即可)
示例小真寻修改图片 修改尺寸 200 300 图片(在文字后跟图片即可)
2.等比压缩 比例(x) 图片(在文字后跟图片即可)
示例小真寻修改图片 等比压缩 2 图片(在文字后跟图片即可)
3.旋转图片 角度(x) 图片(在文字后跟图片即可)
示例小真寻修改图片 旋转图片 45 图片(在文字后跟图片即可)
4.水平翻转
示例小真寻修改图片 水平翻转 图片
5.铅笔滤镜
示例小真寻修改图片 铅笔滤镜 图片
6.模糊效果
示例小真寻修改图片 模糊效果 图片
7.锐化效果
示例小真寻修改图片 锐化效果 图片
8.高斯模糊
示例小真寻修改图片 高斯模糊 图片
9.边缘检测
示例小真寻修改图片 边缘检测 图片
10.底色替换 颜色 颜色 图片 不专业支持->绿
示例小真寻修改图片 底色替换 蓝色 红色 图片'''
# IMAGE_LOCAL = IMAGE_PATH + "temp/{}_update.png"
method_flag = ''
update_img = on_command("修改图片", aliases={'图片', '操作图片', '改图'}, priority=5, rule=to_me(), block=True)
method_list = ['修改尺寸', '等比压缩', '旋转图片', '水平翻转', '铅笔滤镜', '模糊效果', '锐化效果', '高斯模糊', '边缘检测', '底色替换']
method_str = ''
method_oper = []
for i in range(len(method_list)):
method_str += f'\n{i + 1}.{method_list[i]}'
method_oper.append(method_list[i])
method_oper.append(str(i + 1))
update_img_help = CreateImg(960, 700, font_size=24)
update_img_help.text((10, 10), __plugin_usage__)
update_img_help.save(IMAGE_PATH + 'update_img_help.png')
@update_img.args_parser
async def _(bot: Bot, event: MessageEvent, state: T_State):
global method_flag
if str(event.get_message()) in ['取消', '算了']:
await update_img.finish("已取消操作..", at_sender=True)
if state["_current_key"] in ['method']:
if str(event.get_message()) not in method_oper:
await update_img.reject(f"操作不正确,请重新输入!{method_str}")
state[state["_current_key"]] = str(event.get_message())
method_flag = str(event.get_message())
if method_flag in ['1', '修改尺寸']:
if state["_current_key"] == 'x':
if not is_number(str(event.get_message())):
await update_img.reject("宽度不正确!请重新输入数字...")
state[state["_current_key"]] = str(event.get_message())
if state["_current_key"] == 'y':
if not is_number(str(event.get_message())):
await update_img.reject("长度不正确!请重新输入数字...")
state[state["_current_key"]] = str(event.get_message())
elif method_flag in ['2', '等比压缩', '3', '旋转图片']:
if state["_current_key"] == 'x':
if not is_number(str(event.get_message())):
await update_img.reject("比率不正确!请重新输入数字...")
state[state["_current_key"]] = str(event.get_message())
state['y'] = ''
elif method_flag in ['4', '水平翻转', '5', '铅笔滤镜', '6', '模糊效果', '7', '锐化效果', '8', '高斯模糊', '9', '边缘检测']:
state['x'] = ''
state['y'] = ''
elif method_flag in ['10', '底色替换']:
if state["_current_key"] == 'x':
if str(event.get_message()) not in ['红色', '蓝色', '', '']:
await update_img.reject('请输入支持的被替换的底色:\n红色 蓝色')
state['x'] = str(event.get_message())
if state["_current_key"] == 'y':
if str(event.get_message()) not in ['红色', '白色', '蓝色', '绿色', '黄色', '', '', '', '绿', '']:
await update_img.reject('请输入支持的替换的底色:\n红色 蓝色 白色 绿色')
state['y'] = str(event.get_message())
if state["_current_key"] == 'imgs':
if not get_message_imgs(event.json()):
await update_img.reject("没图?没图?没图?来图速来!")
state[state["_current_key"]] = get_message_imgs(event.json())
@update_img.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if str(event.get_message()) in ['帮助']:
await update_img.finish(image('update_img_help.png'))
raw_arg = get_message_text(event.json())
img_list = get_message_imgs(event.json())
if raw_arg:
args = raw_arg.split("[")[0].split(" ")
print(args)
state['method'] = args[0]
if len(args) == 2:
if args[0] in ["等比压缩", '旋转图片']:
if is_number(args[1]):
state['x'] = args[1]
state['y'] = ''
elif len(args) > 2:
if args[0] in ["修改尺寸"]:
if is_number(args[1]):
state['x'] = args[1]
if is_number(args[2]):
state['y'] = args[2]
if args[0] in ['底色替换']:
if args[1] in ['红色', '蓝色', '', '']:
state['x'] = args[1]
if args[2] in ['红色', '白色', '蓝色', '绿色', '黄色', '', '', '', '绿', '']:
state['y'] = args[2]
if args[0] in ['水平翻转', '铅笔滤镜', '模糊效果', '锐化效果', '高斯模糊', '边缘检测']:
state['x'] = ''
state['y'] = ''
if img_list:
state['imgs'] = img_list
@update_img.got("method", prompt=f"要使用图片的什么操作呢?{method_str}")
@update_img.got("x", prompt="[宽度? 比率? 旋转角度? 底色?]")
@update_img.got("y", prompt="[长度? 0 0 底色?]")
@update_img.got("imgs", prompt="图呢图呢图呢图呢GKD")
async def _(bot: Bot, event: MessageEvent, state: T_State):
method = state['method']
x = state['x'] if state['x'] else ''
y = state['y'] if state['y'] else ''
img_list = state['imgs']
if is_number(x):
x = float(x)
if is_number(y):
y = int(y)
index = 0
result = ''
async with aiohttp.ClientSession() as session:
for img_url in img_list:
async with session.get(img_url, timeout=7) as response:
if response.status == 200:
async with aiofiles.open(IMAGE_PATH + f'temp/{event.user_id}_{index}_update.png', 'wb') as f:
await f.write(await response.read())
index += 1
else:
logger.warning(f"USER {event.user_id} GROUP "
f"{event.group_id if event.message_type != 'private' else 'private'} "
f"使用 {method} 时下载图片超时")
await update_img.finish("获取图片超时了...", at_sender=True)
if index == 0:
return
if method in ['修改尺寸', '1']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png')
img = img.convert('RGB')
img = img.resize((int(x), int(y)), Image.ANTIALIAS)
result += image(b64=pic2b64(img))
await update_img.finish(result, at_sender=True)
if method in ['等比压缩', '2']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png')
width, height = img.size
img = img.convert('RGB')
if width * x < 8000 and height * x < 8000:
img = img.resize((int(x * width), int(x * height)))
result += image(b64=pic2b64(img))
else:
await update_img.finish('小真寻不支持图片压缩后宽或高大于8000的存在')
if method in ['旋转图片', '3']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png')
img = img.rotate(x)
result += image(b64=pic2b64(img))
if method in ['水平翻转', '4']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png')
img = img.transpose(Image.FLIP_LEFT_RIGHT)
result += image(b64=pic2b64(img))
if method in ['铅笔滤镜', '5']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png').filter(ImageFilter.CONTOUR)
result += image(b64=pic2b64(img))
if method in ['模糊效果', '6']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png').filter(ImageFilter.BLUR)
result += image(b64=pic2b64(img))
if method in ['锐化效果', '7']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png').filter(ImageFilter.EDGE_ENHANCE)
result += image(b64=pic2b64(img))
if method in ['高斯模糊', '8']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png').filter(ImageFilter.GaussianBlur)
result += image(b64=pic2b64(img))
if method in ['边缘检测', '9']:
for i in range(index):
img = Image.open(IMAGE_PATH + f'temp/{event.user_id}_{i}_update.png').filter(ImageFilter.FIND_EDGES)
result += image(b64=pic2b64(img))
if method in ['底色替换', '10']:
if x in ['蓝色', '']:
lower = np.array([90, 70, 70])
upper = np.array([110, 255, 255])
if x in ['红色', '']:
lower = np.array([0, 135, 135])
upper = np.array([180, 245, 230])
if y in ['蓝色', '']:
color = (255, 0, 0)
if y in ['红色', '']:
color = (0, 0, 255)
if y in ['白色', '']:
color = (255, 255, 255)
if y in ['绿色', '绿']:
color = (0, 255, 0)
if y in ['黄色', '']:
color = (0, 255, 255)
for k in range(index):
img = cv2.imread(IMAGE_PATH + f'temp/{event.user_id}_{k}_update.png')
img = cv2.resize(img, None, fx=0.3, fy=0.3)
rows, cols, channels = img.shape
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
# erode = cv2.erode(mask, None, iterations=1)
dilate = cv2.dilate(mask, None, iterations=1)
for i in range(rows):
for j in range(cols):
if dilate[i, j] == 255:
img[i, j] = color
cv2.imwrite(IMAGE_PATH + f'temp/{event.user_id}_{k}_ok_update.png', img)
for i in range(index):
result += image(f'{event.user_id}_{i}_ok_update.png', 'temp')
if is_number(method):
method = method_list[int(method) - 1]
logger.info(
f"(USER {event.user_id}, GROUP"
f" {event.group_id if event.message_type != 'private' else 'private'}) 使用{method}")
await update_img.finish(result, at_sender=True)