This repository has been archived on 2025-01-28. You can view files and clone it, but cannot push or open issues or pull requests.

141 lines
4.6 KiB
Python

import string
from urllib.request import urlopen, urlretrieve
from PIL import Image, ImageDraw, ImageFont
from sys import argv
import random
import requests
import os
from multiprocessing import Pool
CACHE_FOLDER = "cache/fonts"
# Créer le dossier de cache s'il n'existe pas
if not os.path.exists(CACHE_FOLDER):
os.makedirs(CACHE_FOLDER, exist_ok=True)
def get_font_path(font_url):
"""
Check if the font is already cached locally. If not, download it.
:param font_url: URL of the TTF font file.
:return: Path to the locally cached TTF file.
"""
font_name = font_url.split("/")[-1] # Extract the font filename from the URL
local_path = os.path.join(CACHE_FOLDER, font_name)
if not os.path.exists(local_path):
print(f"Downloading font: {font_name}")
urlretrieve(font_url, local_path) # Download and save the file locally
else:
print(f"Using cached font: {font_name}")
return local_path
def getRandomFont(apiKey: str, usedFont: list = None) -> str:
"""
Function to fetch a random font from a list of available fonts
provided by Google Font
:param apiKey: API Key used to connect to Google Fonts.
:param usedFont: List of already used fonts. Set to None by default
:return: Local path to the cached TTF file.
"""
if usedFont is None:
usedFont = []
url = f"https://www.googleapis.com/webfonts/v1/webfonts?key={apiKey}"
response = requests.get(url)
if response.status_code != 200:
raise Exception(f"Failed to fetch fonts: {response.status_code} - {response.reason}")
fonts_data = response.json()
if "items" not in fonts_data:
raise Exception("No fonts found in the API response.")
available_fonts = fonts_data["items"]
unused_fonts = [font for font in available_fonts if font["family"] not in usedFont]
if not unused_fonts:
raise Exception("No unused fonts available to select from.")
chosen_font = random.choice(unused_fonts)
usedFont.append(chosen_font["family"])
font_files = chosen_font.get("files", {})
ttf_link = font_files.get("regular") or next(iter(font_files.values()), None)
if not ttf_link:
raise Exception(f"No TTF link found for the font: {chosen_font['family']}")
print(f"Selected font: {chosen_font['family']}")
return get_font_path(ttf_link)
def create_letter_image(letter, output_path, font_path):
"""
Function to create an image for a letter passed as an argument
:param letter: the letter
:param output_path: the path to save the image
:param font_path: local path to the TTF font file
:return: print a message and save the image
"""
width, height = 13, 13
font_size = 12
image = Image.new('L', (width, height), color=255) # Fond blanc
draw = ImageDraw.Draw(image)
try:
font = ImageFont.truetype(font_path, font_size)
except IOError:
raise Exception(f"Cannot load font file: {font_path}")
bbox = draw.textbbox((0, 0), letter, font=font)
text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]
text_x = (width - text_width) // 2
text_y = (height - text_height) // 2
draw.text((text_x, text_y), letter, fill=0, font=font) # Texte noir
image.save(output_path)
print(f"Image saved at {output_path}")
def createImageForEachLetter(args):
"""
Function to create an image for each of the letters passed as an argument
:param args: Tuple containing output folder, font path, and index
"""
output_folder, font_path, index = args
alphabet = string.ascii_letters # Inclut à la fois les lettres minuscules et majuscules
os.makedirs(output_folder, exist_ok=True) # Ensure base output folder exists
for element in alphabet:
letter_folder = os.path.join(output_folder, element)
os.makedirs(letter_folder, exist_ok=True)
create_letter_image(element, f"{letter_folder}/{element}-{index}.png", font_path)
if __name__ == "__main__":
if len(argv) < 3:
raise Exception("Usage: " + argv[0] + " <number-of-iterations> <api-key>")
if input(f"This script will generate {argv[1]} images for each letter in the alphabet. Continue? Y/n ") != "Y":
print("Exiting...")
exit(0)
# Configuration
num_iterations = int(argv[1])
api_key = argv[2]
usedFont = []
# Fetch fonts and cache them
fonts = [getRandomFont(api_key, usedFont) for _ in range(num_iterations)]
# Prepare arguments for multiprocessing
args = [("dataset", fonts[i], i) for i in range(num_iterations)]
# Use multiprocessing pool
with Pool() as pool:
pool.map(createImageForEachLetter, args)