""" 🌈 HDR Creator Pro - Ultimate Version Cria imagens HDR com assinaturas visuais extremas e comparação lado a lado. Autor: Daniel251 Versão: 1.2.0 Data: 2026 """ import gradio as gr from PIL import Image, ImageEnhance, ImageFilter, ImageOps import numpy as np import cv2 import tempfile import time import os import warnings import traceback warnings.filterwarnings("ignore") # ========== CONFIGURAÇÃO ========== MAX_IMAGE_SIZE = 1200 HDR_MODES = { "standard_hdr": "🌈 HDR Padrão (Equilibrado)", "natural_hdr": "🌿 HDR Natural (Fiel à Realidade)", "dramatic_hdr": "🎭 HDR Dramático (Alto Contraste/Cinema)", "artistic_hdr": "🎨 HDR Artístico (Efeito Orton/Sonho)", "vibrant_hdr": "💥 HDR Vibrante (Explosão de Cores)", "monochrome_hdr": "⚫ HDR Noir (P&B Profundo)", "infrared_hdr": "🔴 HDR Surreal (Infravermelho Falso)", "cyberpunk_hdr": "🌆 HDR Cyberpunk (Neon/Noite)", "vintage_hdr": "🎞️ HDR Vintage (Filme Antigo)", "single_image": "📷 HDR de Uma Imagem" } # ========== FUNÇÕES DE LOG ========== def log_event(level, message, context="SYSTEM"): timestamp = time.strftime("%Y-%m-%d %H:%M:%S") print(f"[{timestamp}] [{level}] [{context}] {message}") # ========== PROCESSAMENTO CORE ========== def validate_and_resize(image_path): try: img = Image.open(image_path).convert('RGB') if max(img.size) > MAX_IMAGE_SIZE: ratio = MAX_IMAGE_SIZE / max(img.size) new_size = (int(img.width * ratio), int(img.height * ratio)) img = img.resize(new_size, Image.Resampling.LANCZOS) return img except Exception as e: log_event("ERROR", f"Erro ao carregar imagem: {str(e)}") return None def align_images_cv2(images): if len(images) < 2: return images log_event("INFO", "Alinhando múltiplas exposições...", "ALIGN") img_arrays = [np.array(img) for img in images] ref_gray = cv2.cvtColor(img_arrays[0], cv2.COLOR_RGB2GRAY) aligned = [images[0]] for i in range(1, len(img_arrays)): try: warp_matrix = np.eye(2, 3, dtype=np.float32) _, warp_matrix = cv2.findTransformECC( ref_gray, cv2.cvtColor(img_arrays[i], cv2.COLOR_RGB2GRAY), warp_matrix, cv2.MOTION_AFFINE ) w_img = cv2.warpAffine( img_arrays[i], warp_matrix, (img_arrays[0].shape[1], img_arrays[0].shape[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP ) aligned.append(Image.fromarray(w_img.astype(np.uint8))) except: aligned.append(images[i]) return aligned # ========== TONEMAPPING AVANÇADO (ESTILO PHOTOSHOP) ========== def apply_tonemap(hdr_array, mode, strength): """Aplica tonemapping avançado baseado no modo selecionado""" # Normalizar para 0-1 hdr_norm = hdr_array.astype(float) / 255.0 if mode == "standard_hdr": # Curva S suave - padrão Photoshop gamma = 1.0 / (0.7 + strength * 0.3) result = np.power(hdr_norm, gamma) # Pequeno aumento de contraste result = (result - 0.5) * 1.1 + 0.5 elif mode == "natural_hdr": # Preserva tons médios, comprime altas luzes gamma = 1.0 / (0.9 + strength * 0.1) result = np.power(hdr_norm, gamma) # Curva mais linear mask = result > 0.5 result[mask] = 0.5 + (result[mask] - 0.5) * 0.8 elif mode == "dramatic_hdr": # Curva agressiva - tons escuros mais escuros, claros preservados gamma = 1.0 / (0.5 + strength * 0.5) result = np.power(hdr_norm, gamma) # Aumento significativo de contraste result = (result - 0.5) * 1.8 + 0.5 elif mode == "artistic_hdr": # Comprime dinâmica para criar efeito dreamy gamma = 1.0 / (0.8 + strength * 0.2) result = np.power(hdr_norm, gamma) # Achatamento de contraste result = (result - 0.5) * 0.7 + 0.5 elif mode == "vibrant_hdr": # Curva que aumenta saturação nos tons médios gamma = 1.0 / (0.6 + strength * 0.4) result = np.power(hdr_norm, gamma) # Leve aumento de contraste result = (result - 0.5) * 1.2 + 0.5 else: # Padrão para outros modos gamma = 1.0 / (0.8 + strength * 0.2) result = np.power(hdr_norm, gamma) return np.clip(result * 255, 0, 255).astype(np.uint8) def apply_base_hdr(images, strength, mode): """Processa HDR base com alinhamento e tonemapping específico""" if len(images) == 1: # Para imagem única, simula múltiplas exposições img_array = np.array(images[0]).astype(float) # Gera 3 exposições virtuais under = np.clip(img_array * 0.3, 0, 255) normal = img_array over = np.clip(img_array * 2.0, 0, 255) # Combinação ponderada hdr = under * 0.3 + normal * 0.4 + over * 0.3 else: # Para múltiplas imagens aligned = align_images_cv2(images) arrs = [np.array(img).astype(float) for img in aligned] # Combinação baseada no modo if mode in ["dramatic_hdr", "monochrome_hdr"]: hdr = np.max(arrs, axis=0) # Preserva detalhes nas sombras elif mode == "natural_hdr": hdr = np.median(arrs, axis=0) # Reduz ruído else: # Média ponderada com ênfase nas exposições médias weights = [0.3, 0.4, 0.3] if len(arrs) == 3 else [1.0/len(arrs)] * len(arrs) hdr = np.sum([arr * w for arr, w in zip(arrs, weights[:len(arrs)])], axis=0) # Aplica tonemapping específico return apply_tonemap(hdr, mode, strength) # ========== ASSINATURAS VISUAIS ESPECÍFICAS ========== def create_standard(images, s): """HDR Padrão - Equilibrado como Photoshop""" base = apply_base_hdr(images, s, "standard_hdr") img = Image.fromarray(base) # Ajustes finais img = ImageEnhance.Contrast(img).enhance(1.15) img = ImageEnhance.Color(img).enhance(1.05) img = ImageEnhance.Sharpness(img).enhance(1.1) return img, "HDR Padrão: Equilíbrio tonal perfeito, detalhes naturais preservados." def create_natural(images, s): """HDR Natural - Minimalista e realista""" base = apply_base_hdr(images, s * 0.7, "natural_hdr") # Menor intensidade img = Image.fromarray(base) # Ajustes sutis img = ImageEnhance.Color(img).enhance(0.9) img = ImageEnhance.Contrast(img).enhance(1.05) img = ImageEnhance.Sharpness(img).enhance(1.05) # Redução de ruído (suave) img = img.filter(ImageFilter.MedianFilter(size=1)) return img, "HDR Natural: Cores orgânicas, dinâmica preservada, sem artificialidade." def create_dramatic(images, s): """HDR Dramático - Alto contraste, estilo cinematográfico""" base = apply_base_hdr(images, s * 1.3, "dramatic_hdr") img = Image.fromarray(base) # Ajustes agressivos img = ImageEnhance.Contrast(img).enhance(1.8 + s * 0.5) img = ImageEnhance.Color(img).enhance(0.85) # Dessaturação leve para drama img = ImageEnhance.Sharpness(img).enhance(1.3) # Máscara de nitidez para realçar bordas img = img.filter(ImageFilter.UnsharpMask(radius=2, percent=180, threshold=3)) # Aumento seletivo de brilho nas altas luzes enhancer = ImageEnhance.Brightness(img) img = enhancer.enhance(1.05) return img, "HDR Dramático: Contraste cinematográfico, sombras profundas, texturas realçadas." def create_artistic(images, s): """HDR Artístico - Efeito Orton/Sonho""" base = apply_base_hdr(images, s * 0.8, "artistic_hdr") img = Image.fromarray(base) # Efeito Orton: sobreposição de blur blur_amount = int(5 + s * 10) blurred = img.filter(ImageFilter.GaussianBlur(radius=blur_amount)) # Mistura para efeito dreamy blend_amount = 0.3 + s * 0.3 img = Image.blend(img, blurred, blend_amount) # Ajustes de cor img = ImageEnhance.Brightness(img).enhance(1.1) img = ImageEnhance.Color(img).enhance(1.25) img = ImageEnhance.Contrast(img).enhance(0.9) # Contraste reduzido return img, "HDR Artístico: Efeito Orton etéreo, atmosfera onírica, cores suavizadas." def create_vibrant(images, s): """HDR Vibrante - Cores saturadas e vivas""" base = apply_base_hdr(images, s, "vibrant_hdr") img = Image.fromarray(base) # Aumento agressivo de saturação img = ImageEnhance.Color(img).enhance(2.0 + s * 1.0) # Contraste moderado img = ImageEnhance.Contrast(img).enhance(1.25) # Brilho ajustado img = ImageEnhance.Brightness(img).enhance(1.05) # Nitidez para realçar detalhes img = ImageEnhance.Sharpness(img).enhance(1.2) return img, "HDR Vibrante: Saturação máxima, cores intensas, energia visual explosiva." def create_monochrome(images, s): """HDR Noir - P&B profundo com textura""" base = apply_base_hdr(images, s * 1.2, "monochrome_hdr") img = Image.fromarray(base) # Conversão para P&B com canal de luminância img_gray = ImageOps.grayscale(img).convert("RGB") # Contraste extremo img = ImageEnhance.Contrast(img_gray).enhance(2.0 + s * 0.5) # Brilho ajustado img = ImageEnhance.Brightness(img).enhance(0.9) # Textura adicionada arr = np.array(img).astype(float) noise = np.random.normal(0, 8 * s, arr.shape) arr = np.clip(arr + noise, 0, 255).astype(np.uint8) img = Image.fromarray(arr) return img, "HDR Noir: Preto e branco profundo, contraste dramático, textura cinematográfica." def create_infrared(images, s): """HDR Surreal - Efeito infravermelho falso""" img, _ = create_standard(images, s * 0.7) # Separa canais r, g, b = img.split() # Efeito infravermelho: troca de canais # Canal vermelho recebe verde (folhagens ficam claras) new_r = g.point(lambda x: min(x * 1.5, 255)) # Canal azul escurecido new_b = b.point(lambda x: x * 0.7) # Canal verde com vermelho new_g = r.point(lambda x: x * 0.8) img = Image.merge("RGB", (new_r, new_g, new_b)) # Ajustes finais img = ImageEnhance.Contrast(img).enhance(1.3) img = ImageEnhance.Color(img).enhance(1.2) return img, "HDR Surreal: Espectro infravermelho simulado, folhagens brancas, céu escuro." def create_cyberpunk(images, s): """HDR Cyberpunk - Estética neon futurista""" img, _ = create_standard(images, s) # Separa canais para ajustes individuais r, g, b = img.split() # Realça azuis e vermelhos (neon) new_r = ImageEnhance.Brightness(r).enhance(1.6 + s * 0.5) new_b = ImageEnhance.Brightness(b).enhance(1.8 + s * 0.7) new_g = ImageEnhance.Brightness(g).enhance(0.8) # Verdes reduzidos img = Image.merge("RGB", (new_r, new_g, new_b)) # Ajustes gerais img = ImageEnhance.Brightness(img).enhance(0.85) # Escurece img = ImageEnhance.Contrast(img).enhance(1.4) img = ImageEnhance.Color(img).enhance(1.5) # Adiciona leve vinheta width, height = img.size arr = np.array(img).astype(float) # Cria máscara de vinheta x = np.linspace(-1, 1, width) y = np.linspace(-1, 1, height) X, Y = np.meshgrid(x, y) vignette = 1 - np.sqrt(X**2 + Y**2) * 0.3 vignette = vignette[:, :, np.newaxis] arr = arr * vignette img = Image.fromarray(np.clip(arr, 0, 255).astype(np.uint8)) return img, "HDR Cyberpunk: Estética Neon-Noir futurista, cores sintéticas, atmosfera noturna." def create_vintage(images, s): """HDR Vintage - Filme antigo com grão""" img, _ = create_standard(images, s * 0.6) # Dessaturação e tom sépia img = ImageEnhance.Color(img).enhance(0.65) # Aplica sépia sepia_base = ImageOps.colorize( ImageOps.grayscale(img), "#3d2b1f", # Sombra "#fff5e6", # Destaque "#8b6b42" # Meio-tom ) img = Image.blend(img, sepia_base, 0.7) # Adiciona grão de filme arr = np.array(img).astype(float) grain = np.random.normal(0, 12 * s, arr.shape) arr = np.clip(arr + grain, 0, 255) # Adiciona leve vinheta height, width = arr.shape[0], arr.shape[1] x = np.linspace(-1, 1, width) y = np.linspace(-1, 1, height) X, Y = np.meshgrid(x, y) vignette = 1 - np.sqrt(X**2 + Y**2) * 0.4 vignette = vignette[:, :, np.newaxis] arr = arr * vignette img = Image.fromarray(np.clip(arr, 0, 255).astype(np.uint8)) # Contraste suave img = ImageEnhance.Contrast(img).enhance(1.1) return img, "HDR Vintage: Visual de filme analógico desgastado, grão natural, tons sépia." def create_single(image, s): """HDR de imagem única - Recuperação de detalhes""" # Converte para array img_arr = np.array(image).astype(float) # Cria múltiplas exposições virtuais exp1 = np.clip(img_arr * 0.25, 0, 255) # Subexposta exp2 = img_arr # Normal exp3 = np.clip(img_arr * 2.2, 0, 255) # Superexposta # Mapeamento de tons local (similar ao Photoshop) # Combina detalhes das sombras (exp1), tons médios (exp2) e altas luzes (exp3) # Máscara para sombras luminance = 0.299 * exp2[:,:,0] + 0.587 * exp2[:,:,1] + 0.114 * exp2[:,:,2] shadow_mask = np.clip((0.5 - luminance) * 2, 0, 1)[:,:,np.newaxis] # Máscara para altas luzes highlight_mask = np.clip((luminance - 0.7) * 3, 0, 1)[:,:,np.newaxis] # Máscara para tons médios midtone_mask = 1 - shadow_mask - highlight_mask midtone_mask = np.clip(midtone_mask, 0, 1) # Combinação ponderada hdr = exp1 * shadow_mask + exp2 * midtone_mask + exp3 * highlight_mask # Ajuste de contraste local result = np.clip(hdr, 0, 255).astype(np.uint8) img = Image.fromarray(result) # Ajustes finais img = ImageEnhance.Contrast(img).enhance(1.3 + s * 0.3) img = ImageEnhance.Sharpness(img).enhance(1.2) img = ImageEnhance.Color(img).enhance(1.1) return img, "HDR Simulado: Detalhes recuperados de uma única foto, dinâmica expandida." # ========== INTERFACE GRADIO ========== def create_interface(): custom_css = """ .gradio-container { max-width: 1400px !important; margin: 0 auto !important; background-color: #0f172a; color: #f8fafc; } .header { text-align: center; padding: 30px; background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-bottom: 2px solid #334155; margin-bottom: 20px; } .header h1 { font-size: 3em; margin: 0; background: linear-gradient(to right, #38bdf8, #818cf8); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .header p { color: #94a3b8; font-size: 1.2em; margin-top: 10px; } .status-box { padding: 15px; border-radius: 8px; text-align: center; margin: 15px 0; font-weight: bold; font-size: 1.1em; } .status-success { background: #065f46; color: #34d399; border: 1px solid #059669; } .status-info { background: #1e3a8a; color: #93c5fd; border: 1px solid #2563eb; } .status-warning { background: #7c2d12; color: #fdba74; border: 1px solid #ea580c; } .status-error { background: #7f1d1d; color: #fca5a5; border: 1px solid #dc2626; } .image-container { border: 2px solid #334155; border-radius: 12px; overflow: hidden; background: #1e293b; padding: 10px; } .image-label { font-weight: bold; color: #cbd5e1; margin-bottom: 5px; text-align: center; } button#component-4 { background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important; } button#component-4:hover { background: linear-gradient(135deg, #4338ca 0%, #6d28d9 100%) !important; } .slider-container { padding: 15px; background: #1e293b; border-radius: 8px; margin: 10px 0; } .output-image { max-width: 100% !important; height: auto !important; } """ with gr.Blocks(css=custom_css, title="HDR Creator Pro Ultra") as demo: gr.HTML("""
Motor de Renderização HDR com Assinaturas Visuais de Alta Precisão | Versão 1.2.0
Para HDR verdadeiro: Carregue 2+ imagens com diferentes exposições
Para HDR de imagem única: Carregue 1 imagem e selecione "Single Image"