File size: 3,523 Bytes
bac55b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO

from src.constants import front_card_img_dict

# カード画像各領域のピクセル位置情報
# 写真
PICTURE_LT_XY = (65, 188)
PICTURE_RB_XY = (802, 925)
PICTURE_SIZE = (PICTURE_RB_XY[0] - PICTURE_LT_XY[0], PICTURE_RB_XY[1] - PICTURE_LT_XY[1])

# タイトル
# ある程度の余白を作る。
TITLE_LT_XY = (65, 45) 
TITLE_RB_XY = (647, 132) # マーク挿入部分と重ならないような位置
TITLE_SIZE = (TITLE_RB_XY[0] - TITLE_LT_XY[0], TITLE_RB_XY[1] - TITLE_LT_XY[1])

# 説明文本体
DESCRIPTION_LT_XY = (46, 972)
DESCRIPTION_RB_XY = (810, 1174)
DESCRIPTION_SIZE = (DESCRIPTION_RB_XY[0] - DESCRIPTION_LT_XY[0], DESCRIPTION_RB_XY[1] - DESCRIPTION_LT_XY[1])

# フォント関連
# 明朝体
font_selif_path = 'data/fonts/SourceHanSerif-Bold.otf'
# ゴシック体
font_sanselif_path = 'data/fonts/SourceHanSans-Bold.otf'

def crop_center(pil_img, crop_width, crop_height):
    img_width, img_height = pil_img.size
    return pil_img.crop(((img_width - crop_width) // 2,
                         (img_height - crop_height) // 2,
                         (img_width + crop_width) // 2,
                         (img_height + crop_height) // 2))
    
def crop_max_square(pil_img):
    return crop_center(pil_img, min(pil_img.size), min(pil_img.size))
    
def create_card_image(model_no, img_bytearray, option_dict):

    # 画像の読み込みとトリミング
    picture_img = Image.open(img_bytearray)
    picture_img = crop_max_square(picture_img)
    picture_img = picture_img.resize(PICTURE_SIZE)

    # カードの読み込み
    card_img = Image.open(front_card_img_dict[model_no])

    # 写真の埋め込み
    card_img.paste(picture_img, PICTURE_LT_XY)

    # 各種書き込み準備
    card_imgdraw = ImageDraw.Draw(card_img)

    # タイトル埋め込み
    # (複数行対応は必要ならば対応)
    title_font_size = 100
    while True:
        title_font = ImageFont.truetype(font_selif_path, title_font_size)
        title_bbox = card_imgdraw.textbbox(TITLE_LT_XY , option_dict['タイトル'], title_font)
        
        if (title_bbox[2] <= TITLE_RB_XY[0] and title_bbox[3] <= TITLE_RB_XY[1]) or title_font_size <= 30:
            break
        title_font_size -= 1

    card_imgdraw.text((TITLE_LT_XY[0], int((TITLE_LT_XY[1] + TITLE_RB_XY[1]) / 2)), option_dict['タイトル'], fill='black', font=title_font, anchor='lm')

    # 説明文埋め込み
    description_font = ImageFont.truetype(font_sanselif_path, 40)

    description_list = []
    description_length = len(option_dict['説明文'])
    temp_start = 0
    for i in range(description_length):
        temp_end = i
        description_line_bbox = card_imgdraw.textbbox((0, 0), option_dict['説明文'][temp_start:temp_end+1], description_font)
        if description_line_bbox[2] > DESCRIPTION_SIZE[0]:
            description_list.append(option_dict['説明文'][temp_start:temp_end])
            temp_start = i

    description_list.append(option_dict['説明文'][temp_start:])
    description_display = '\n'.join(description_list)

    card_imgdraw.text(DESCRIPTION_LT_XY, description_display, fill='black', font=description_font)

    # バイナリデータの出力
    output_img_bytearray = BytesIO()
    card_img.convert('RGB').save(output_img_bytearray, "JPEG", quality=95)
    output_img_bytearray.seek(0) # 画像の先頭にシークしないと空データになってしまう。

    return output_img_bytearray