File size: 6,483 Bytes
bac55b4
 
 
6810bed
 
 
bac55b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6810bed
 
bac55b4
 
 
 
6810bed
 
bac55b4
6810bed
bac55b4
 
6810bed
bac55b4
 
 
6810bed
bac55b4
 
6810bed
bac55b4
 
6810bed
bac55b4
 
 
 
6810bed
 
bac55b4
6810bed
bac55b4
 
 
 
 
 
 
 
 
 
 
 
 
 
6810bed
bac55b4
 
 
 
6810bed
bac55b4
 
6810bed
1c5bad2
 
 
bac55b4
6810bed
bac55b4
 
6810bed
bac55b4
 
6810bed
bac55b4
 
 
 
 
6810bed
bac55b4
 
6810bed
 
bac55b4
 
 
 
 
 
 
 
 
 
 
6810bed
bac55b4
 
 
 
6810bed
bac55b4
 
 
 
 
 
6810bed
bac55b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6810bed
bac55b4
 
6810bed
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO

# Card image information

# Historic Site Card files
card_frame_path_dict = {
    '橙': 'data/cards/史跡カードフレーム(橙).png',
    '白': 'data/cards/史跡カードフレーム(白).png',
    '紫': 'data/cards/史跡カードフレーム(紫).png',
    '緑': 'data/cards/史跡カードフレーム(緑).png',
    '茶': 'data/cards/史跡カードフレーム(茶).png',
    '赤': 'data/cards/史跡カードフレーム(赤).png',
    '青': 'data/cards/史跡カードフレーム(青).png',
    '黄': 'data/cards/史跡カードフレーム(黄).png',
    '黒': 'data/cards/史跡カードフレーム(黒).png'
}
card_mark_path_dict = {
    '区指定': 'data/cards/史跡カード指定マーク(区指定).png',
    '国指定': 'data/cards/史跡カード指定マーク(国指定).png',
    '市指定': 'data/cards/史跡カード指定マーク(市指定).png',
    '府指定': 'data/cards/史跡カード指定マーク(府指定).png',
    '村指定': 'data/cards/史跡カード指定マーク(村指定).png',
    '町指定': 'data/cards/史跡カード指定マーク(町指定).png',
    '県指定': 'data/cards/史跡カード指定マーク(県指定).png',
    '道指定': 'data/cards/史跡カード指定マーク(道指定).png',
    '都指定': 'data/cards/史跡カード指定マーク(都指定).png'
}

# Pixel position information for each area of the card image
# Picture
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
# Create some margin
TITLE_LT_XY = (65, 45) 
TITLE_RB_XY = (647, 132) # Position to avoid overlapping with the marker insertion point
TITLE_SIZE = (TITLE_RB_XY[0] - TITLE_LT_XY[0], TITLE_RB_XY[1] - TITLE_LT_XY[1])

# Explanation Section Divider
DESCRIPTION_LINE_L_XY = (52, 1024)
DESCRIPTION_LINE_R_XY = (816, 1024)

# Historic Site Type
HS_TYPE_LT_XY = (56, 972)

# Difficulty of Visit
DIFFICULTY_LT_XY = (444, 972)

# Main Body of Description
DESCRIPTION_LT_XY = (46, 1024)
DESCRIPTION_RB_XY = (810, 1174)
DESCRIPTION_SIZE = (DESCRIPTION_RB_XY[0] - DESCRIPTION_LT_XY[0], DESCRIPTION_RB_XY[1] - DESCRIPTION_LT_XY[1])

# Font information
# Ming Typeface
font_selif_path = 'data/fonts/SourceHanSerif-Bold.otf'
# Gothic Typeface
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_historic_site_card_image(img_bytearray, option_dict):

    # Loading and Cropping of Picture
    picture_img = Image.open(img_bytearray)
    picture_img = crop_max_square(picture_img)
    picture_img = picture_img.resize(PICTURE_SIZE)

    # Loading of Card Frame
    card_img = Image.open(card_frame_path_dict[option_dict['色']])

    # Adding a Marker
    if option_dict['マーク'] in card_mark_path_dict:
        mark_image = Image.open(card_mark_path_dict[option_dict['マーク']])
        card_img.paste(mark_image, mask=mark_image)

    # Embedding a Picture in the Card
    card_img.paste(picture_img, PICTURE_LT_XY)

    # Preparing for editting the card image
    card_imgdraw = ImageDraw.Draw(card_img)

    # Adding a Border to the Card
    card_imgdraw.line(( (0, 0), (card_img.size[0], 0) ), fill='black', width=15)
    card_imgdraw.line(( (0, 0), (0, card_img.size[1]) ), fill='black', width=15)
    card_imgdraw.line(( (card_img.size[0], 0),  card_img.size), fill='black', width=15)
    card_imgdraw.line(( (0, card_img.size[1]),  card_img.size), fill='black', width=15)

    # Adding a Divider Line to the Explanation Section
    card_imgdraw.line((DESCRIPTION_LINE_L_XY, DESCRIPTION_LINE_R_XY), fill='black', width=3)

    # Embedding the Title
    # (Support for multiple lines if needed)
    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')

    # Embedding the Historic Site Type
    hs_type_display = f'種類:{option_dict["史跡種類"]}'
    hs_typefont = ImageFont.truetype(font_sanselif_path, 40)
    card_imgdraw.text(HS_TYPE_LT_XY, hs_type_display, fill='black', font=hs_typefont, anchor='lt')

    # Embedding the Difficulty of Visit
    difficulty = int(option_dict['訪問難度'])
    difficulty = 1 if difficulty < 1 else 5 if difficulty > 5 else difficulty
    difficulty_display = '訪問難度:' + '☆' * difficulty + '★' * (5 - difficulty)
    difficulty_font = ImageFont.truetype(font_sanselif_path, 40)
    card_imgdraw.text(DIFFICULTY_LT_XY, difficulty_display, fill='black', font=difficulty_font, anchor='lt')

    # Embedding the Description Text
    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)

    # Outputting Binary Data
    output_img_bytearray = BytesIO()
    card_img.convert('RGB').save(output_img_bytearray, "JPEG", quality=95)
    output_img_bytearray.seek(0) # Seek to the beginning of the image, otherwise it results in empty data

    return output_img_bytearray