Last active
November 14, 2021 21:26
-
-
Save TheLukeGuy/9fd755f208fa1185e7456bf71654f21a to your computer and use it in GitHub Desktop.
A script to split a Duolingo flag sheet up into individual PNG images.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from io import BytesIO | |
from pathlib import Path | |
from cairosvg import svg2png | |
from PIL import Image, ImageChops | |
# This likely only works with the old style of flags (flag-spriteXX.svg) | |
FLAG_SHEET = 'flags.svg' | |
OUTPUT_DIR = 'flags' | |
TARGET_FLAG_SIZE = 512 | |
def main(): | |
full_flag_size = TARGET_FLAG_SIZE + (TARGET_FLAG_SIZE / 64) | |
flag_sheet_size = (full_flag_size / 80) * 1000 | |
print('Rasterizing SVG...') | |
svg = Path(FLAG_SHEET).read_text() | |
png = svg2png(bytestring=svg, output_width=flag_sheet_size) | |
Image.MAX_IMAGE_PIXELS = None | |
image = Image.open(BytesIO(png)) | |
width, height = image.size | |
Path(OUTPUT_DIR).mkdir(parents=True, exist_ok=True) | |
flag_id = 0 | |
over_flag_y = False | |
print('Splitting flags...') | |
for y in range(height): | |
if image.getpixel((0, y))[3] == 0: | |
over_flag_y = False | |
continue | |
if over_flag_y: | |
continue | |
over_flag_x = False | |
for x in range(width): | |
if image.getpixel((x, y))[3] == 0: | |
over_flag_x = False | |
continue | |
if over_flag_x: | |
continue | |
print(f'{flag_id}: {(x, y)}') | |
flag = image.crop((x, y, x + full_flag_size, y + full_flag_size)) | |
background = Image.new(flag.mode, flag.size, (0, 0, 0, 0)) | |
difference = ImageChops.difference(flag, background) | |
bbox = difference.getbbox() | |
if bbox: | |
flag = flag.crop(bbox) | |
new_width, new_height = flag.size | |
if new_width != new_height: | |
final_size = new_width if new_width < new_height else new_height | |
left = (new_width - final_size) // 2 | |
top = (new_height - final_size) // 2 | |
right = (new_width + final_size) // 2 | |
bottom = (new_height + final_size) // 2 | |
flag = flag.crop((left, top, right, bottom)) | |
bottom_center_pixel = flag.getpixel((flag.size[0] // 2, flag.size[1] - 1)) | |
if bottom_center_pixel == (0, 0, 0, 0): | |
over_flag_x = True | |
flag_id += 1 | |
continue | |
flag.thumbnail((TARGET_FLAG_SIZE, TARGET_FLAG_SIZE), Image.ANTIALIAS) | |
flag.save(f'{OUTPUT_DIR}/flag_{flag_id}.png') | |
over_flag_x = True | |
flag_id += 1 | |
over_flag_y = True | |
print('Done!') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment