-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththumbnail_generator.py
More file actions
111 lines (88 loc) · 3.63 KB
/
thumbnail_generator.py
File metadata and controls
111 lines (88 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# thumbnail_generator.py
from PIL import Image, UnidentifiedImageError
from pathlib import Path
import os
import hashlib
import cv2
import rawpy
THUMBNAIL_SIZE = (128, 128)
def get_cache_dir():
"""
Determina la ruta de caché correcta según el sistema.
"""
base_dir = os.path.dirname(os.path.abspath(__file__))
# 1. MODO PORTABLE / DEV (Si podemos escribir junto al script)
if os.access(base_dir, os.W_OK):
path = Path(base_dir) / "visagevault_cache" / "local_snapshot_cache"
else:
# 2. MODO INSTALADO (Linux / AUR) -> ~/.cache/visagevault
user_home = Path.home()
path = user_home / ".cache" / "visagevault" / "local_snapshot_cache"
path.mkdir(parents=True, exist_ok=True)
return path
def get_thumbnail_path(original_filepath: str) -> Path:
"""Genera la ruta donde se guardará la miniatura."""
thumb_dir = get_cache_dir()
file_hash = hashlib.sha256(original_filepath.encode('utf-8')).hexdigest()
return thumb_dir / f"{file_hash}.jpg"
def generate_image_thumbnail(original_filepath: str) -> str | None:
original_filepath = Path(original_filepath)
if not original_filepath.is_file(): return None
# Usamos la nueva función dinámica
thumbnail_path = get_thumbnail_path(str(original_filepath))
if thumbnail_path.exists():
return str(thumbnail_path)
try:
img_to_process = None
try:
img_pil = Image.open(original_filepath)
img_pil.load()
img_to_process = img_pil
except (UnidentifiedImageError, IOError):
try:
with rawpy.imread(str(original_filepath)) as raw:
rgb = raw.postprocess(use_camera_wb=True)
img_to_process = Image.fromarray(rgb)
except Exception:
return None
if not img_to_process: return None
if img_to_process.mode in ('RGBA', 'LA') or (img_to_process.mode == 'P' and 'transparency' in img_to_process.info):
background = Image.new('RGB', img_to_process.size, (255, 255, 255))
if img_to_process.mode == 'P':
img_to_process = img_to_process.convert('RGBA')
background.paste(img_to_process, mask=img_to_process.split()[3])
img_to_process = background
elif img_to_process.mode != 'RGB':
img_to_process = img_to_process.convert('RGB')
# Redimensionar antes de guardar para ahorrar espacio
img_to_process.thumbnail(THUMBNAIL_SIZE)
img_to_process.save(thumbnail_path, "JPEG", quality=80)
img_to_process.close()
return str(thumbnail_path)
except Exception as e:
print(f"Error thumbnail imagen: {e}")
return None
def generate_video_thumbnail(original_filepath: str) -> str | None:
original_filepath = Path(original_filepath)
if not original_filepath.is_file(): return None
thumbnail_path = get_thumbnail_path(str(original_filepath))
if thumbnail_path.exists():
return str(thumbnail_path)
try:
cap = cv2.VideoCapture(str(original_filepath))
success, frame = cap.read()
cap.release()
if not success: return None
h, w = frame.shape[:2]
if h > w:
new_h = THUMBNAIL_SIZE[1]
new_w = int(w * (new_h / h))
else:
new_w = THUMBNAIL_SIZE[0]
new_h = int(h * (new_w / w))
resized_frame = cv2.resize(frame, (new_w, new_h), interpolation=cv2.INTER_AREA)
cv2.imwrite(str(thumbnail_path), resized_frame)
return str(thumbnail_path)
except Exception as e:
print(f"Error thumbnail vídeo: {e}")
return None