mirc detection

This commit is contained in:
2025-07-09 06:40:36 +02:00
parent a5e044d747
commit 386b34526b
7 changed files with 1918 additions and 128 deletions

238
api/app/conversion.py Normal file
View File

@@ -0,0 +1,238 @@
"""
Module de conversion pour les formats d'images modernes
Supporte les formats courants des appareils Android et iOS
"""
import os
import subprocess
from pathlib import Path
import tempfile
import shutil
import logging
from typing import List, Optional, Tuple
from .config import settings
# Configuration du logging
logger = logging.getLogger("cheque_scanner_api.conversion")
# Formats modernes pris en charge
MODERN_FORMATS = {
# Formats iPhone
"heic": "HEIC (High Efficiency Image Format) - iPhone",
"heif": "HEIF (High Efficiency Image Format) - iPhone",
# Formats Android haute qualité
"webp": "WebP - Android",
"dng": "DNG (Digital Negative) - Android RAW",
# Formats communs haute résolution
"cr2": "Canon RAW Format",
"arw": "Sony RAW Format",
"nef": "Nikon RAW Format",
"raw": "Format RAW générique",
}
# Mapping des extensions aux formats de sortie recommandés
FORMAT_MAPPING = {
"heic": "jpg",
"heif": "jpg",
"webp": "png",
"dng": "jpg",
"cr2": "jpg",
"arw": "jpg",
"nef": "jpg",
"raw": "jpg",
}
def is_modern_format(filename: str) -> bool:
"""
Vérifie si le fichier est dans un format moderne qui nécessite une conversion
Args:
filename (str): Nom du fichier à vérifier
Returns:
bool: True si le fichier est dans un format moderne, False sinon
"""
ext = Path(filename).suffix.lower().lstrip(".")
return ext in MODERN_FORMATS
def get_supported_input_formats() -> List[str]:
"""
Renvoie la liste des formats d'entrée pris en charge
Returns:
List[str]: Liste des extensions de fichiers pris en charge
"""
return list(MODERN_FORMATS.keys()) + list(settings.ALLOWED_EXTENSIONS)
def convert_heic_to_jpg(input_path: str, output_path: str) -> bool:
"""
Convertit un fichier HEIC en JPG en utilisant pillow-heif
Args:
input_path (str): Chemin du fichier HEIC
output_path (str): Chemin de sortie pour le fichier JPG
Returns:
bool: True si la conversion a réussi, False sinon
"""
try:
import pillow_heif
from PIL import Image
# Enregistrer le décodeur HEIF
pillow_heif.register_heif_opener()
# Ouvrir et convertir l'image
img = Image.open(input_path)
img.convert("RGB").save(output_path, format="JPEG", quality=95)
return True
except ImportError:
logger.warning("pillow-heif n'est pas installé, utilisation de la méthode alternative")
return _convert_with_imagemagick(input_path, output_path)
except Exception as e:
logger.error(f"Erreur lors de la conversion HEIC: {str(e)}")
return False
def convert_webp_to_png(input_path: str, output_path: str) -> bool:
"""
Convertit un fichier WebP en PNG
Args:
input_path (str): Chemin du fichier WebP
output_path (str): Chemin de sortie pour le fichier PNG
Returns:
bool: True si la conversion a réussi, False sinon
"""
try:
from PIL import Image
img = Image.open(input_path)
img.save(output_path, format="PNG")
return True
except Exception as e:
logger.error(f"Erreur lors de la conversion WebP: {str(e)}")
return _convert_with_imagemagick(input_path, output_path)
def _convert_with_imagemagick(input_path: str, output_path: str) -> bool:
"""
Méthode alternative utilisant ImageMagick pour la conversion
Args:
input_path (str): Chemin du fichier d'entrée
output_path (str): Chemin du fichier de sortie
Returns:
bool: True si la conversion a réussi, False sinon
"""
try:
# Vérifier si ImageMagick est installé
subprocess.run(["which", "convert"], check=True, capture_output=True)
# Conversion avec ImageMagick
result = subprocess.run(
["convert", input_path, output_path],
check=True,
capture_output=True
)
return result.returncode == 0
except subprocess.CalledProcessError as e:
logger.error(f"Erreur ImageMagick: {e.stderr.decode() if e.stderr else str(e)}")
return False
except Exception as e:
logger.error(f"Erreur lors de la conversion avec ImageMagick: {str(e)}")
return False
def convert_raw_to_jpg(input_path: str, output_path: str) -> bool:
"""
Convertit un fichier RAW (DNG, CR2, ARW, NEF, etc.) en JPG
Args:
input_path (str): Chemin du fichier RAW
output_path (str): Chemin de sortie pour le fichier JPG
Returns:
bool: True si la conversion a réussi, False sinon
"""
try:
# Essayer d'abord avec rawpy
import rawpy
import imageio
with rawpy.imread(input_path) as raw:
rgb = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=False)
imageio.imsave(output_path, rgb)
return True
except ImportError:
logger.warning("rawpy n'est pas installé, utilisation de la méthode alternative")
return _convert_with_imagemagick(input_path, output_path)
except Exception as e:
logger.error(f"Erreur lors de la conversion RAW: {str(e)}")
return _convert_with_imagemagick(input_path, output_path)
def convert_file(input_path: str, output_dir: str = None) -> Tuple[bool, Optional[str], Optional[str]]:
"""
Convertit un fichier d'un format moderne vers un format standard
Args:
input_path (str): Chemin du fichier à convertir
output_dir (str, optional): Répertoire de sortie pour le fichier converti
Si non spécifié, utilise le même répertoire que le fichier d'entrée
Returns:
Tuple[bool, Optional[str], Optional[str]]:
- Succès de la conversion (bool)
- Chemin du fichier converti (str ou None si échec)
- Message d'erreur (str ou None si succès)
"""
input_path = Path(input_path)
# Vérifier si le fichier existe
if not input_path.exists():
return False, None, f"Le fichier {input_path} n'existe pas"
# Obtenir l'extension du fichier
ext = input_path.suffix.lower().lstrip(".")
# Si l'extension est déjà dans les formats autorisés, pas besoin de conversion
if ext in settings.ALLOWED_EXTENSIONS:
return True, str(input_path), None
# Vérifier si le format est pris en charge
if ext not in MODERN_FORMATS:
return False, None, f"Format non pris en charge: {ext}"
# Déterminer le format de sortie
output_ext = FORMAT_MAPPING.get(ext, "jpg")
# Déterminer le chemin de sortie
if output_dir:
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
output_path = output_dir / f"{input_path.stem}.{output_ext}"
else:
output_path = input_path.with_suffix(f".{output_ext}")
# Effectuer la conversion en fonction du format
success = False
if ext in ["heic", "heif"]:
success = convert_heic_to_jpg(str(input_path), str(output_path))
elif ext == "webp":
success = convert_webp_to_png(str(input_path), str(output_path))
elif ext in ["dng", "cr2", "arw", "nef", "raw"]:
success = convert_raw_to_jpg(str(input_path), str(output_path))
else:
# Fallback sur ImageMagick pour les autres formats
success = _convert_with_imagemagick(str(input_path), str(output_path))
if success:
return True, str(output_path), None
else:
return False, None, f"Échec de la conversion du fichier {input_path}"