Spaces:
Running
Running
ikeda
translate items printed in Japanese into English on Historic Site Card in other languages version
0ab59c6
| 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) | |
| DIFFICULTY_LT_XY_EN = (424, 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["史跡種類"]}' if option_dict["language"] == 'ja' else f'Type: {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 = ('訪問難度:' if option_dict["language"] == 'ja' else 'Difficulty: ') \ | |
| + '☆' * difficulty + '★' * (5 - difficulty) | |
| difficulty_font = ImageFont.truetype(font_sanselif_path, 40) | |
| temp_difficulty_lt_xy = DIFFICULTY_LT_XY if option_dict["language"] == 'ja' else DIFFICULTY_LT_XY_EN | |
| card_imgdraw.text(temp_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 | |