Last active
June 12, 2025 10:04
-
-
Save hackolite/64f5e4ac1d109bb0199ebc84d78d36b3 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 PIL import Image, ImageDraw | |
import qrcode | |
def create_qr_with_black_center(data): | |
"""Crée un QR code avec centre noir (ou le plus proche), en image noir et blanc""" | |
# Paramètres | |
box_size = 10 | |
border = 2 | |
# QR brut | |
qr = qrcode.QRCode( | |
version=1, | |
error_correction=qrcode.constants.ERROR_CORRECT_L, | |
box_size=box_size, | |
border=border, | |
) | |
qr.add_data(data) | |
qr.make(fit=True) | |
modules = qr.modules | |
module_count = len(modules) | |
# Coordonnées du centre | |
center_module_x = module_count // 2 | |
center_module_y = module_count // 2 | |
# Si centre blanc, on prend le module noir le plus proche | |
if not modules[center_module_y][center_module_x]: | |
black_modules = [ | |
(x, y, abs(x - center_module_x) + abs(y - center_module_y)) | |
for y in range(module_count) | |
for x in range(module_count) | |
if modules[y][x] | |
] | |
black_modules.sort(key=lambda t: t[2]) | |
center_module_x, center_module_y, _ = black_modules[0] | |
center_pixel_x = (center_module_x + border) * box_size | |
center_pixel_y = (center_module_y + border) * box_size | |
img_size = (module_count + 2 * border) * box_size | |
# Mode 'RGB' pour compatibilité maximale | |
img = Image.new('RGB', (img_size, img_size), 'white') # Fond blanc | |
draw = ImageDraw.Draw(img) | |
# Dessin des modules noirs | |
for row in range(module_count): | |
for col in range(module_count): | |
if modules[row][col]: | |
x0 = (col + border) * box_size | |
y0 = (row + border) * box_size | |
x1 = x0 + box_size | |
y1 = y0 + box_size | |
draw.rectangle([x0, y0, x1, y1], fill='black') | |
return img, box_size, (center_pixel_x, center_pixel_y) | |
def insert_qr_in_its_own_center(qr_img, box_size, center_pixel_x, center_pixel_y, scale_factor=5, output_path="qr_mise_en_abyme.png"): | |
""" | |
Agrandit le QR code, insère une version miniature dans son pixel central | |
""" | |
# Taille de l'image agrandie | |
new_size = (qr_img.width * scale_factor, qr_img.height * scale_factor) | |
enlarged_qr = qr_img.resize(new_size, Image.NEAREST) | |
# Nouveau box_size et coordonnées du centre | |
new_box_size = box_size * scale_factor | |
new_center_x = center_pixel_x * scale_factor | |
new_center_y = center_pixel_y * scale_factor | |
# Réduction du QR original à la taille d'un seul module | |
mini_qr = qr_img.resize((new_box_size, new_box_size), Image.LANCZOS) | |
# Insertion dans le centre de l'image agrandie | |
enlarged_qr.paste(mini_qr, (new_center_x, new_center_y)) | |
# Sauvegarde en PNG optimisé (plus léger) | |
enlarged_qr.save(output_path, format='PNG', optimize=True) | |
print(f"✅ QR inséré dans son pixel central (agrandi ×{scale_factor}) : {output_path}") | |
return enlarged_qr, scale_factor, new_box_size, (new_center_x, new_center_y) | |
def main(): | |
coordinates = "14.66778,-17.39722" | |
print("🎯 Génération QR Code Fractal") | |
print("=" * 40) | |
# 1. Création du QR de base | |
print("1️⃣ Création du QR de base...") | |
img, box_size, (px, py) = create_qr_with_black_center(coordinates) | |
img.save("qr_base.png", format='PNG', optimize=True) | |
print(f" ✅ QR de base sauvé (taille: {img.size})") | |
print(f" 📍 Centre: pixel ({px}, {py}), box_size: {box_size}") | |
# 2. Premier niveau d'imbrication | |
print("\n2️⃣ Premier niveau d'imbrication...") | |
result1, scale1, box1, (cx1, cy1) = insert_qr_in_its_own_center( | |
img, box_size, px, py, scale_factor=10, output_path="qr_level1.png" | |
) | |
print(f" 📊 Scale: {scale1}, Box size: {box1}, Center: ({cx1}, {cy1})") | |
# 3. Deuxième niveau d'imbrication | |
print("\n3️⃣ Deuxième niveau d'imbrication...") | |
result2, scale2, box2, (cx2, cy2) = insert_qr_in_its_own_center( | |
result1, box1, cx1, cy1, scale_factor=10, output_path="qr_level2.png" | |
) | |
print(f" 📊 Scale: {scale2}, Box size: {box2}, Center: ({cx2}, {cy2})") | |
# 4. Version ultra-légère en noir et blanc | |
print("\n4️⃣ Création version ultra-légère...") | |
# Convertir en noir et blanc pur pour réduire la taille | |
bw_img = result2.convert('1') # 1 bit par pixel | |
bw_img.save("qr_fractal_light.png", format='PNG', optimize=True) | |
print("\n🎉 Génération terminée!") | |
print("📁 Fichiers créés:") | |
print(" - qr_base.png (QR de base)") | |
print(" - qr_level1.png (Premier niveau)") | |
print(" - qr_level2.png (Deuxième niveau)") | |
print(" - qr_fractal_light.png (Version ultra-légère)") | |
# Afficher les tailles de fichiers | |
import os | |
files = ["qr_base.png", "qr_level1.png", "qr_level2.png", "qr_fractal_light.png"] | |
print("\n📊 Tailles des fichiers:") | |
for file in files: | |
if os.path.exists(file): | |
size = os.path.getsize(file) | |
print(f" {file}: {size} bytes ({size/1024:.1f} KB)") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment