Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added automatic text size selection #15

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/fonts/Gidole-Regular.ttf
Binary file not shown.
45 changes: 36 additions & 9 deletions src/storage/watermark.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from pathlib import Path
import random
from io import BytesIO

from PIL import Image, ImageDraw, ImageFont


def draw_text_with_outline(draw, position, text, font, text_colour, outline_colour):
x, y = position
# Draw outline
Expand Down Expand Up @@ -40,22 +42,37 @@ def calculate_corners(img_w, img_h, text_bbox, margin) -> list:

return corners

def check_font_size(text, font_path, image, width_ratio):
breakpoint = width_ratio * image.size[0]
fontsize = 20
learning_rate = 5
font = ImageFont.truetype(font_path, fontsize)
while True:
if font.getlength(text) < breakpoint:
fontsize += learning_rate
else:
learning_rate = learning_rate // 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если честно я не понимаю, зачем тут бесконечный цикл и такой сложный алгоритм. Разве нельзя по размеру картинки прикинуть размер шрифта?

Copy link
Contributor Author

@Antohhin Antohhin Jan 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. шрифт — величина относительная (12, 18, 75 не понятно нифига это много или мало для картинки).
    поэтому, в моем видении, этот алгоритм занимается как раз прикидкой размера шрифта под размер картинки.
  2. по поводу while True — могу предложить другой вариант:
    сделать маленькое значение font и идти только на увеличение текста while font.getlength(text) < breakpoint
    будет работать быстрее, если мы как-то ограничены сверху по времени

fontsize -= learning_rate
font = ImageFont.truetype(font_path, fontsize)
if learning_rate <= 1:
break
return font

def draw_corner_watermark(
image_bytes: BytesIO,
text: str,
text_size: int = 14,
font_family: str = "Gidole-Regular.ttf",
margin: int = 24
) -> Image:
with Image.open(image_bytes).convert("RGBA") as base:
txt = Image.new("RGBA", base.size, (255, 255, 255, 0))

# try:
# fnt = ImageFont.truetype('Arial.ttf', text_size)
# except IOError:
# fnt = ImageFont.load_default()

fnt = ImageFont.load_default()
d = ImageDraw.Draw(txt)

width_ratio = .15 # Portion of the image the text width should be (between 0 and 1)
font_path = str(Path(Path.home(), "src", "fonts", font_family))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не уверен, что этот способ работы с путями сработает. Посмотри, как я с путями работаю в localizer, когда считываю yml файлы из папки static.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ага, понял
вообще я через докер поднимал, как в описании, тестил через Ipython и работало.
правильно понял, ты предлагаешь переписать через контекстный менеджер?

with open(localization_file, "r") as f:
            localizations |= yaml.safe_load(f)

fnt = check_font_size(text, font_path, base, width_ratio)
# fnt = ImageFont.load_default()
# calculate size of textbox
text_bbox = d.textbbox((0, 0), text, font=fnt)
# choose a random corner for the text
Expand Down Expand Up @@ -88,8 +105,18 @@ def add_watermark(image_content: bytes) -> BytesIO | None:
return None

buff = BytesIO()
buff.name = 'image.jpeg'
buff.name = 'image_x.jpeg'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

почему поменял?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тестил, забыл убрать

image.save(buff, 'JPEG')
buff.seek(0)

return buff
return buff#image

# if __name__ == '__main__':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

закомментрированное нужно убрать


# # image_path = Path(Path.home(), "src", "test1.jpeg") # Adjust the path if necessary
# image_path = Path(Path.home(), "src", "test1.jpeg") # Adjust the path if necessary
# with open(image_path, 'rb') as image_file:
# image_bytes = image_file.read()
# watermarked_image = add_watermark(image_bytes)
# watermarked_image.save('/src/image_3x.jpg')