diff --git a/.gitignore b/.gitignore index acb2aac..90527b9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ *.ini *.json *.mp3 -*.ogg \ No newline at end of file +*.ogg +*.png diff --git a/TaikoWiiUSongTextureTool/README.md b/TaikoWiiUSongTextureTool/README.md index c9f0540..d0205af 100644 --- a/TaikoWiiUSongTextureTool/README.md +++ b/TaikoWiiUSongTextureTool/README.md @@ -2,7 +2,5 @@ Tool to generate song textures for Taiko no Tatsujin Wii U 1-3, using a modern wordlist.json file. Only supports Japanese text for now. -Any song names that are too long will be cut-off. -Output images will be in .png format, use other tools to convert them to .NUT. Usage: python generate.py song_id genreNo diff --git a/TaikoWiiUSongTextureTool/generate.py b/TaikoWiiUSongTextureTool/generate.py index 4b15cab..e509322 100644 --- a/TaikoWiiUSongTextureTool/generate.py +++ b/TaikoWiiUSongTextureTool/generate.py @@ -8,9 +8,27 @@ rotated_chars = { '「': '﹁', '」': '﹂', '『': '﹃', '』': '﹄', '(': '︵', ')': '︶', - '[': '﹇', ']': '﹈' + '[': '﹇', ']': '﹈', + '〝': '﹁', '〟': '﹂', + '{': '︷', '}': '︸', + '⦅': '︹', '⦆': '︺', + '<': '︿', '>': '﹀', + '《': '︽', '》': '︾', + '〈': '︿', '〉': '﹀', + '【': '︻', '】': '︼', + '〔': '︹', '〕': '︺', + '「': '﹁', '」': '﹂', + '『': '﹃', '』': '﹄', + '(': '︵', ')': '︶', + '[': '﹇', ']': '﹈', + '{': '︷', '}': '︸', + '〈': '︿', '〉': '﹀', + '《': '︽', '》': '︾', + '【': '︻', '】': '︼', + '〔': '︹', '〕': '︺' } + def get_text_bbox(draw, text, font): return draw.textbbox((0, 0), text, font=font) @@ -59,7 +77,7 @@ def generate_image(draw, text, font, rotated_font, size, position, alignment, st draw.text((text_position[0] - char_width / 2, y_offset), char, font=char_font, fill=fill, stroke_width=stroke_width, stroke_fill=stroke_fill) y_offset += char_height elif vertical_small: - y_offset = text_position[1] + y_offset = 5 for char in text: char_font = rotated_font if char in rotated_chars else font char = rotated_chars.get(char, char) @@ -77,6 +95,8 @@ def create_images(data, id, genreNo, font_path, rotated_font_path): font_size_medium = 27.3 font_size_small = 21.84 + img_3_5_height = 400 + folder_name = id os.makedirs(folder_name, exist_ok=True) @@ -137,25 +157,128 @@ def create_images(data, id, genreNo, font_path, rotated_font_path): generate_image(draw2, japanese_text, font_large, rotated_font, (720, 64), (0, 4), 'center', 5, 'black', 'white') img2.save(os.path.join(folder_name, '2.png')) - # Image 3.png + # Image 3.png + + img3_height = 400 + img3 = Image.new('RGBA', (96, 400), color=(0, 0, 0, 0)) + img3_1 = Image.new('RGBA', (96, 400), color=(0, 0, 0, 0)) + img3_2 = Image.new('RGBA', (96, 400), color=(0, 0, 0, 0)) draw3 = ImageDraw.Draw(img3) - generate_image(draw3, japanese_text, font_large, rotated_font, (96, 400), (89, 0), 'center', 5, 'black', 'white', vertical=True) - generate_image(draw3, japanese_sub_text, font_medium, rotated_font, (96, 400), (32, 156), 'center', 4, 'black', 'white', vertical_small=True) + + temp_img3 = Image.new('RGBA', (96, 1000), (0, 0, 0, 0)) # Temporary image with 1000px height + temp_draw3 = ImageDraw.Draw(temp_img3) + + temp_sub_img3 = Image.new('RGBA', (96, 1000), (0, 0, 0, 0)) # Temporary image with 1000px height + temp_sub_draw3 = ImageDraw.Draw(temp_sub_img3) + + generate_image(temp_draw3, japanese_text, font_large, rotated_font, (96, 1000), (89, 0), 'center', 5, 'black', 'white', vertical=True) + + # Crop the temporary image to the actual height of the text + y_offset = 0 + for char in japanese_text: + char_font = rotated_font if char in rotated_chars else font_large + char = rotated_chars.get(char, char) + text_bbox = get_text_bbox(temp_draw3, char, char_font) + char_height = 42 + y_offset += char_height + + # Crop the temporary image to the actual height of the text + temp_img3 = temp_img3.crop((0, 0, 96, y_offset)) + + # Resize the image if it exceeds the specified height + if y_offset > img3_height: + img3_1 = temp_img3.resize((96, img3_height), Image.Resampling.LANCZOS) + else: + img3_1 = temp_img3.crop((0, 0, 96, img3_height)) + + generate_image(temp_sub_draw3, japanese_sub_text, font_medium, rotated_font, (96, 1000), (32, 156), 'center', 4, 'black', 'white', vertical_small=True) + + # Crop the temporary image to the actual height of the text + y_offset = 0 + for char in japanese_sub_text: + char_font = rotated_font if char in rotated_chars else font_large + char = rotated_chars.get(char, char) + text_bbox = get_text_bbox(temp_sub_draw3, char, char_font) + char_height = 28 + y_offset += char_height + + # Crop the temporary image to the actual height of the text + temp_sub_img3 = temp_sub_img3.crop((0, 0, 96, y_offset)) + + # Resize the image if it exceeds the specified height + if y_offset > img3_height: + img3_2 = temp_sub_img3.resize((96, img3_height), Image.Resampling.LANCZOS) + else: + img3_2 = temp_sub_img3.crop((0, 0, 96, img3_height)) + + img3.paste(img3_1, (0, 0)) + img3.paste(img3_2, (0, 0), img3_2) img3.save(os.path.join(folder_name, '3.png')) # Image 4.png + img4_height = 400 + img4 = Image.new('RGBA', (56, 400), color=(0, 0, 0, 0)) draw4 = ImageDraw.Draw(img4) - generate_image(draw4, japanese_text, font_large, rotated_font, (56, 400), (48, 0), 'center', 5, genre_color, 'white', vertical=True) + + temp_img4 = Image.new('RGBA', (56, 1000), (0, 0, 0, 0)) # Temporary image with 1000px height + temp_draw4 = ImageDraw.Draw(temp_img4) + + generate_image(temp_draw4, japanese_text, font_large, rotated_font, (56, 400), (48, 0), 'center', 5, genre_color, 'white', vertical=True) + + # Crop the temporary image to the actual height of the text + y_offset = 0 + for char in japanese_text: + char_font = rotated_font if char in rotated_chars else font_large + char = rotated_chars.get(char, char) + text_bbox = get_text_bbox(temp_draw4, char, char_font) + char_height = 42 + y_offset += char_height + + # Crop the temporary image to the actual height of the text + temp_img4 = temp_img4.crop((0, 0, 56, y_offset)) + + # Resize the image if it exceeds the specified height + if y_offset > img4_height: + img4 = temp_img4.resize((56, img4_height), Image.Resampling.LANCZOS) + else: + img4 = temp_img4.crop((0, 0, 56, img4_height)) + img4.save(os.path.join(folder_name, '4.png')) # Image 5.png + img5_height = 400 + img5 = Image.new('RGBA', (56, 400), color=(0, 0, 0, 0)) draw5 = ImageDraw.Draw(img5) - generate_image(draw5, japanese_text, font_large, rotated_font, (56, 400), (48, 0), 'center', 5, 'black', 'white', vertical=True) + + temp_img5 = Image.new('RGBA', (56, 1000), (0, 0, 0, 0)) # Temporary image with 1000px height + temp_draw5 = ImageDraw.Draw(temp_img5) + + generate_image(temp_draw5, japanese_text, font_large, rotated_font, (56, 400), (48, 0), 'center', 5, 'black', 'white', vertical=True) + + # Crop the temporary image to the actual height of the text + y_offset = 0 + for char in japanese_text: + char_font = rotated_font if char in rotated_chars else font_large + char = rotated_chars.get(char, char) + text_bbox = get_text_bbox(temp_draw5, char, char_font) + char_height = 42 + y_offset += char_height + + # Crop the temporary image to the actual height of the text + temp_img5 = temp_img5.crop((0, 0, 56, y_offset)) + + # Resize the image if it exceeds the specified height + if y_offset > img5_height: + img5 = temp_img5.resize((56, img5_height), Image.Resampling.LANCZOS) + else: + img5 = temp_img5.crop((0, 0, 56, img5_height)) + img5.save(os.path.join(folder_name, '5.png')) + if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: generate.py ") @@ -172,7 +295,7 @@ if __name__ == "__main__": wordlist_path = 'resources/wordlist.json' font_path = 'resources/DFPKanTeiRyu-XB.ttf' - rotated_font_path = 'resources/KozGoPr6NRegular.otf' # Add the path to your rotated font here + rotated_font_path = 'resources/KozGoPr6NRegular.otf' if not os.path.isfile(wordlist_path): print(f"Error: {wordlist_path} not found")