darkmedia-x-api / engine /src /renderer.rs
cybermedia's picture
Upload folder using huggingface_hub
343eed9 verified
pub mod image_processor;
pub mod vfx;
pub mod depth;
pub mod animation;
pub mod postprocessing;
use crate::error::Result;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone)]
pub struct RenderContext {
pub scene_id: usize,
pub prompt: String,
pub text_overlay: String,
pub vfx_profile: VfxProfile,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum VfxProfile {
Grain,
Blur,
Glitch,
Vignette,
CinematicDark,
None,
}
impl VfxProfile {
pub fn from_env_string(s: &str) -> Self {
match s.to_lowercase().as_str() {
"blur" => Self::Blur,
"glitch" => Self::Glitch,
"vignette" => Self::Vignette,
"cinematic_dark" => Self::CinematicDark,
"none" => Self::None,
_ => Self::Grain,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Blur => "blur",
Self::Glitch => "glitch",
Self::Vignette => "vignette",
Self::CinematicDark => "cinematic_dark",
Self::None => "none",
Self::Grain => "grain",
}
}
}
pub struct Renderer {
pub base_dir: PathBuf,
pub vfx_profile: VfxProfile,
}
impl Renderer {
pub fn new(base_dir: PathBuf, vfx_profile: VfxProfile) -> Self {
Self { base_dir, vfx_profile }
}
/// Rendre une image avec texte overlay et effets VFX
pub async fn render_image(
&self,
input_image: &Path,
output_image: &Path,
text_overlay: &str,
_scene_id: usize,
) -> Result<()> {
// 1. Charger l'image
let mut image = image_processor::load_image(input_image)?;
// 2. Appliquer les VFX
image = vfx::apply_vfx(image, self.vfx_profile)?;
// 3. Ajouter le texte overlay
if !text_overlay.is_empty() {
image = image_processor::render_text_overlay(image, text_overlay)?;
}
// 4. Sauvegarder
image_processor::save_image(&image, output_image)?;
Ok(())
}
/// Générer une depth map pour le zoom 3D
pub async fn generate_depth_map(&self, image_path: &Path, depth_path: &Path) -> Result<()> {
depth::generate_depth_anything(image_path, depth_path).await
}
/// Rendre une scène complète (image + depth + overlay)
pub async fn render_scene(
&self,
source_image: &Path,
scene_id: usize,
text_overlay: &str,
output_dir: &Path,
) -> Result<()> {
let img_file = output_dir.join(format!("scene_{}.png", scene_id));
let depth_file = output_dir.join("..").join("depths").join(format!("scene_{}.png", scene_id));
// Rendre l'image avec texte et VFX
self.render_image(source_image, &img_file, text_overlay, scene_id).await?;
// Générer la depth map (optionnel, non-bloquant)
if let Err(e) = self.generate_depth_map(&img_file, &depth_file).await {
eprintln!(" ⚠️ Depth map non disponible: {}", e);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vfx_profile_parsing() {
assert_eq!(matches!(VfxProfile::from_env_string("grain"), VfxProfile::Grain), true);
assert_eq!(matches!(VfxProfile::from_env_string("blur"), VfxProfile::Blur), true);
assert_eq!(matches!(VfxProfile::from_env_string("glitch"), VfxProfile::Glitch), true);
assert_eq!(matches!(VfxProfile::from_env_string("unknown"), VfxProfile::Grain), true);
}
}