mirc detection
This commit is contained in:
238
api/app/conversion.py
Normal file
238
api/app/conversion.py
Normal 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}"
|
||||
Reference in New Issue
Block a user