Наложение водяного знака в PIL
Имеется бот: задача бота: Пользователь отправляет первую фотографию на которую хочет наложить водяной знак. Далее отправляет второе изображение самого водяного знака. И далее бот отправляет пользователю первое фото с наложенным поверх водяным знаком (фото от пользователя номер два)
Далее загружаю изображение номер два(Водяной знак)
На выходе получается вот такое изображение
ЖЕЛАЕМЫЙ РЕЗУЛЬТАТ НА ВЫХОДЕ
Код снизу, какие параметры изменить и как это можно реализовать?
@dp.message_handler(content_types=['photo'], state=Groupuser.znak)
async def load_znak(message: types.Message, state: FSMContext):
async with state.proxy() as data:
data['znak'] = message.photo[2].file_id #Выбираем самое высокое разрешение
photo = requests.get(URI_INFO + data['photo']) #Отправляем гет запрос и получае данные о фото
photo_path = photo.json()['result']['file_path'] #Получаем путь файла
photo_content = requests.get(URI + photo_path) #Отправляем гет запрос и получаем фото
user_photo = Image.open(io.BytesIO(photo_content.content)).convert('RGBA') #Отправляем фото в буфер в байтах. Конвертируем в RGBA
photo_z = requests.get(URI_INFO + data['znak'])
photo_path_z = photo_z.json()['result']['file_path']
photo_content_z = requests.get(URI + photo_path_z)
user_photo_z = Image.open(io.BytesIO(photo_content_z.content)).resize((400,100)).convert('RGBA') #Указали размер водяного изображения
user_photo_z.putalpha(100) #Указали прозрачность
#Вставляем водяной знак
width, height = user_photo.size #Берем размер первого фото
transparent = Image.new('RGBA', (width, height), (0, 0, 0, 0)) #Создаем новое изображение и указываем размер, координаты
transparent.paste(user_photo, (0, 0)) #Вставляем наше первое фото, позиция 0,0
position = 50, 200 #Позиция для водяного знака
transparent.paste(user_photo_z, position, mask=user_photo_z) #Вставляем наш водяной знак и указываем прозрачность
transparent.save('Watemark.png', format='png') #Сохраняем наш итоговый результат
photo_send = open('Watemark.png', 'rb') #Открываем наш результат
await bot.send_photo(chat_id=message.chat.id, photo=photo_send)
os.remove('C:\тг бот тест\photo\Watemark.png')
await state.finish()
Ответы (1 шт):
Автор решения: gord1402
→ Ссылка
Вот функция для добавления watermark на изображение:
from PIL import Image
import numpy as np
def add_watermark(main_image: Image.Image, watermark: Image.Image, position: tuple) -> Image.Image:
res = main_image.copy().convert('RGBA')
watermark = watermark.convert('RGBA')
x = np.asarray(watermark).copy()
x[:, :, 3] = (100 * (np.sum(x[:, :, :3], axis=2) < 700)).astype(np.uint8)
watermark = Image.fromarray(x)
alpha = watermark.getchannel('A')
crop = alpha.getbbox()
watermark = watermark.crop(crop)
res.alpha_composite(watermark, position)
return res
Использование в вашем коде:
@dp.message_handler(content_types=['photo'], state=Groupuser.znak)
async def load_znak(message: types.Message, state: FSMContext):
async with state.proxy() as data:
data['znak'] = message.photo[2].file_id #Выбираем самое высокое разрешение
photo = requests.get(URI_INFO + data['photo']) #Отправляем гет запрос и получае данные о фото
photo_path = photo.json()['result']['file_path'] #Получаем путь файла
photo_content = requests.get(URI + photo_path) #Отправляем гет запрос и получаем фото
user_photo = Image.open(io.BytesIO(photo_content.content))
photo_z = requests.get(URI_INFO + data['znak'])
photo_path_z = photo_z.json()['result']['file_path']
photo_content_z = requests.get(URI + photo_path_z)
user_photo_z = Image.open(io.BytesIO(photo_content_z.content))
position = 50, 200 # Позиция для водяного знака
add_watermark(user_photo, user_photo_z, position).save('Watemark.png', format='png') #Сохраняем наш итоговый результат
photo_send = open('Watemark.png', 'rb') #Открываем наш результат
await bot.send_photo(chat_id=message.chat.id, photo=photo_send)
os.remove('C:\тг бот тест\photo\Watemark.png')
await state.finish()



