Skip to content

Instantly share code, notes, and snippets.

@TheLukeGuy
Last active November 14, 2021 21:26
Show Gist options
  • Save TheLukeGuy/9fd755f208fa1185e7456bf71654f21a to your computer and use it in GitHub Desktop.
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.
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