Files
Forge-Engine/auth/image_dimensions.py
T
williamandClaude Sonnet 5 559331f9cf
Build and deploy / test-python (push) Successful in 10m59s
Build and deploy / test-js (push) Successful in 1m27s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Enrichit les declencheurs/actions de scene (clic/survol/affichage, surbrillance/video/son/visibilite/indication/attendre) et fiabilise la pose d'un fond/decor importe
- Ajoute clic/survol/affichage-ecran comme declencheurs, et surbrillance,
  video, son, visibilite, indication, attendre comme actions, utilisables
  aussi bien par l'editeur manuel (menu lateral Objets/Ecran) que par
  Ruby (IA), avec blocs deplacables/supprimables dans une chaine.
- Corrige plusieurs variantes du bug "impossible de poser un objet hors
  du champ de la camera" (troncature du chainage d'actions a 4 maillons,
  fond importe pose a 128x128 au lieu de sa taille reelle, decalage du
  fond au vrai glisser-depose, redimensionnement manuel jamais propage
  au monde).
- Ajoute un vrai glisser-depose depuis la galerie vers la scene, la
  gestion complete de "Mes assets" (sous-sections Fonds/Decors/Sons/
  Videos, suppression, reclassement fond<->decor sans re-upload).
- Ajoute l'upload de son (limite 3 min) et de video (MP4 uniquement,
  limite 5 min), avec validation de la duree reelle du fichier, et une
  replique audio optionnelle dans une bulle de dialogue.
- Fixe la taille de pose d'un objet/decor importe a 200x200 avec une
  boite de collision de 150x150.
- Filtre le selecteur de fichier des actions son/video par type reel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 00:28:46 +02:00

72 lines
2.6 KiB
Python

import re
import struct
def image_dimensions(content):
"""Largeur/hauteur RÉELLES (en pixels) d'une image, lues directement
dans ses en-têtes — SANS dépendance externe (Pillow serait la solution
habituelle, mais un simple parsing des formats courants suffit ici et
évite d'ajouter une dépendance binaire lourde juste pour ça). Renvoie
None si le format n'est pas reconnu (ex. SVG vectoriel sans taille
fixe) — l'appelant retombe alors sur les valeurs par défaut du schéma
(voir screens/scenes/add_scene_object.py)."""
if content[:8] == b"\x89PNG\r\n\x1a\n":
if len(content) >= 24:
width, height = struct.unpack(">II", content[16:24])
return width, height
return None
if content[:6] in (b"GIF87a", b"GIF89a"):
if len(content) >= 10:
width, height = struct.unpack("<HH", content[6:10])
return width, height
return None
if content[:2] == b"BM":
if len(content) >= 26:
width, height = struct.unpack("<ii", content[18:26])
return abs(width), abs(height)
return None
if content[:4] == b"RIFF" and content[8:12] == b"WEBP":
return _webp_dimensions(content)
if content[:2] == b"\xff\xd8":
return _jpeg_dimensions(content)
return None
def _webp_dimensions(content):
chunk = content[12:16]
if chunk == b"VP8X" and len(content) >= 30:
width = 1 + (content[24] | (content[25] << 8) | (content[26] << 16))
height = 1 + (content[27] | (content[28] << 8) | (content[29] << 16))
return width, height
if chunk == b"VP8 " and len(content) >= 30:
width, height = struct.unpack("<HH", content[26:30])
return width & 0x3FFF, height & 0x3FFF
if chunk == b"VP8L" and len(content) >= 25:
b = content[21:25]
bits = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
width = (bits & 0x3FFF) + 1
height = ((bits >> 14) & 0x3FFF) + 1
return width, height
return None
def _jpeg_dimensions(content):
i = 2
n = len(content)
while i + 9 < n:
if content[i] != 0xFF:
i += 1
continue
marker = content[i + 1]
if marker in (0xD8, 0x01) or 0xD0 <= marker <= 0xD7:
i += 2
continue
if marker == 0xD9:
break
seg_len = struct.unpack(">H", content[i + 2:i + 4])[0]
if 0xC0 <= marker <= 0xCF and marker not in (0xC4, 0xC8, 0xCC):
height, width = struct.unpack(">HH", content[i + 5:i + 9])
return width, height
i += 2 + seg_len
return None