# Annexe : Application - Caméra

## Rôle et utilité
`apps/camera/app.py` est une application utilitaire permettant de visualiser le flux vidéo d'une webcam branchée à l'ordinateur, et d'enregistrer des photos. C'est une démonstration brillante de la capacité de GrimOS à s'interfacer avec du matériel externe.

## Implémentation technique

*   **La bibliothèque `cv2` (OpenCV)** : Cette application est l'une des rares à nécessiter une dépendance lourde externe. Elle utilise `cv2.VideoCapture(0)` pour capturer le flux matériel de la première caméra détectée par le système Linux (`/dev/video0`).
*   **Conversion d'image en temps réel** : Tkinter ne sait pas afficher un flux vidéo brut. Le script doit donc, dans une boucle très rapide (`window.after(15)`), capturer l'image de la webcam, convertir ses couleurs de BGR (le format d'OpenCV) vers RGB, puis transformer cette matrice en une image compatible avec l'interface via `ImageTk.PhotoImage`.
*   **Nettoyage mémoire** : Le flux vidéo consommant beaucoup de ressources, l'application veille à libérer l'accès à la caméra (`cap.release()`) lorsque l'utilisateur ferme la fenêtre, évitant ainsi un crash matériel persistant.

## Pistes de modification

*   **Mode Enregistrement Vidéo** : L'application actuelle ne prend que des photos. En exploitant la classe `cv2.VideoWriter`, on pourrait ajouter un bouton rouge "REC" permettant d'enregistrer des vidéos au format MP4 directement sur le disque.
*   **Filtres en direct** : Toujours grâce à OpenCV, on pourrait ajouter une barre d'outils offrant des effets amusants en temps réel (Noir et Blanc, effet miroir, détection de contours) avant l'affichage dans le cadre Tkinter.


## Code Source

```python
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
import os
import datetime

def start(window, app_manager=None, **kwargs):
    # Essayons d'importer cv2. S'il n'est pas là, on affiche un message d'erreur clair.
    try:
        import cv2
    except ImportError:
        tk.Label(window, text="La librairie OpenCV n'est pas installée.\n\nVeuillez exécuter :\nsudo apt-get install python3-opencv\n\npuis relancez l'application.", fg="red", font=("Arial", 12)).pack(expand=True)
        return

    top_frame = tk.Frame(window, bg="lightgray", height=40)
    top_frame.pack(side="top", fill="x")

    icon_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "icons")
    window.icons = getattr(window, "icons", {})
    if 'btn_camera' not in window.icons:
        ipath = os.path.join(icon_dir, "btn_camera.png")
        if os.path.exists(ipath):
            window.icons['btn_camera'] = tk.PhotoImage(file=ipath)
    
    video_container = tk.Frame(window, bg="black")
    video_container.pack(fill="both", expand=True)
    
    video_lbl = tk.Label(video_container, bg="black")
    video_lbl.pack(expand=True)
    
    try:
        cap = cv2.VideoCapture(0)
    except Exception as e:
        messagebox.showerror("Erreur", f"Impossible d'accéder à la webcam : {e}")
        return
        
    if not cap.isOpened():
        messagebox.showerror("Erreur", "Aucune webcam détectée sur /dev/video0.")
        return

    def update_frame():
        if not window.winfo_exists():
            cap.release()
            return
            
        ret, frame = cap.read()
        if ret:
            # OpenCV utilise BGR, ImageTk nécessite RGB
            frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = Image.fromarray(frame_rgb)
            imgtk = ImageTk.PhotoImage(image=img)
            
            video_lbl.imgtk = imgtk # garder la référence
            video_lbl.configure(image=imgtk)
            
        window.after(30, update_frame)
        
    def take_photo():
        ret, frame = cap.read()
        if ret:
            img_dir = os.path.expanduser("~/Images")
            os.makedirs(img_dir, exist_ok=True)
            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"photo_{timestamp}.jpg"
            filepath = os.path.join(img_dir, filename)
            
            cv2.imwrite(filepath, frame)
            
            if app_manager and hasattr(app_manager, 'desktop'):
                app_manager.desktop.show_toast(f"Photo sauvegardée :\n{filepath}")
                
    btn_photo = tk.Button(top_frame, text=" Prendre une photo", image=window.icons.get('btn_camera'), compound="left", font=("Arial", 11, "bold"), bg="#4CAF50", fg="white", relief="flat", command=take_photo)
    btn_photo.pack(side="left", padx=10, pady=5)
    
    def on_destroy(event):
        if str(event.widget) == str(window):
            if cap.isOpened():
                cap.release()
                
    window.bind("<Destroy>", on_destroy)
    update_frame()
```
