{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acd5fb0e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ⚙️ Conseils d'exécution\n",
    "# - Mets un fichier \"photo.jpg\" dans les fichiers de l'activité (Capytale > Fichiers).\n",
    "# - Si tu n'as pas \"photo.jpg\", le notebook fabriquera une image de test automatiquement.\n",
    "# - Exécute les cellules dans l'ordre (Ctrl+Entrée)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c89b94c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"SNT — Images : pixels, résolution, compression et métadonnées\")\n",
    "print(\"Objectif : mesurer l'effet de la résolution et de la compression sur la taille du fichier,\")\n",
    "print(\"et lire des métadonnées EXIF simples.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "416ec274",
   "metadata": {},
   "outputs": [],
   "source": [
    "from PIL import Image, ImageOps\n",
    "import os, io\n",
    "\n",
    "IMG_NAME = \"photo.jpg\"\n",
    "\n",
    "def ensure_image():\n",
    "    if os.path.exists(IMG_NAME):\n",
    "        return IMG_NAME\n",
    "    # Secours : on génère une mire synthétique 800x533\n",
    "    import numpy as np\n",
    "    w, h = 800, 533\n",
    "    x = np.linspace(0, 255, w).astype('uint8')\n",
    "    grad = np.tile(x, (h,1))\n",
    "    # Mire RVB: dégradé + bandes\n",
    "    arr = np.zeros((h, w, 3), dtype='uint8')\n",
    "    arr[...,0] = grad\n",
    "    arr[...,1] = grad[:, ::-1]\n",
    "    arr[...,2] = (grad//2)\n",
    "    img = Image.fromarray(arr, 'RGB')\n",
    "    img.save(IMG_NAME, format=\"JPEG\", quality=90)\n",
    "    return IMG_NAME\n",
    "\n",
    "img_path = ensure_image()\n",
    "img = Image.open(img_path).convert(\"RGB\")\n",
    "display(img)\n",
    "print(\"Fichier utilisé :\", img_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2c919d0c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "width, height = img.size\n",
    "file_size_kb = os.path.getsize(img_path) / 1024\n",
    "\n",
    "print(f\"Dimensions en pixels : {width} × {height}\")\n",
    "print(f\"Taille du fichier     : {file_size_kb:.1f} Ko\")\n",
    "\n",
    "# Rappel utile pour le compte-rendu\n",
    "print(\"\\nRappel :\")\n",
    "print(\"- Plus il y a de pixels (L×H), plus l'image contient d'information.\")\n",
    "print(\"- Le JPEG est une compression AVEC pertes : plus on compresse, plus on dégrade.\")\n",
    "print(\"- Le PNG compresse SANS pertes, souvent meilleur pour schémas/captures, pas pour photos.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bcc54d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "small = img.resize((width//2, height//2))  # réduction 50 %\n",
    "display(small)\n",
    "\n",
    "small_png_path = \"photo_small.png\"\n",
    "small.save(small_png_path, format=\"PNG\")\n",
    "size_small_png_kb = os.path.getsize(small_png_path)/1024\n",
    "print(f\"PNG (50% dimensions) : {size_small_png_kb:.1f} Ko\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45bc2cf2",
   "metadata": {},
   "outputs": [],
   "source": [
    "qualities = [95, 60, 30]\n",
    "sizes = []\n",
    "\n",
    "for q in qualities:\n",
    "    out = f\"photo_q{q}.jpg\"\n",
    "    small.save(out, format=\"JPEG\", quality=q, optimize=True)\n",
    "    kb = os.path.getsize(out)/1024\n",
    "    sizes.append((q, kb))\n",
    "\n",
    "print(\"Comparatif JPEG sur l'image réduite à 50% :\")\n",
    "for q, kb in sizes:\n",
    "    print(f\"  - JPEG q={q:<2} → {kb:>6.1f} Ko\")\n",
    "\n",
    "from IPython.display import display as disp\n",
    "imgs = []\n",
    "for q,_ in sizes:\n",
    "    imgs.append(Image.open(f\"photo_q{q}.jpg\"))\n",
    "for im in imgs:\n",
    "    disp(im)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5824f53b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from PIL import ImageOps\n",
    "\n",
    "gray = ImageOps.grayscale(small)\n",
    "display(gray)\n",
    "\n",
    "hist = gray.histogram()  # 256 valeurs\n",
    "plt.figure()\n",
    "plt.title(\"Histogramme niveaux de gris (0 à 255)\")\n",
    "plt.xlabel(\"Niveau de gris\")\n",
    "plt.ylabel(\"Nombre de pixels\")\n",
    "plt.plot(hist)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "074f7f97",
   "metadata": {},
   "outputs": [],
   "source": [
    "from PIL.ExifTags import TAGS\n",
    "\n",
    "exif = getattr(img, \"_getexif\", lambda: None)()\n",
    "infos = {}\n",
    "if exif:\n",
    "    for k,v in exif.items():\n",
    "        tag = TAGS.get(k,k)\n",
    "        if tag in (\"Make\",\"Model\",\"DateTime\",\"Software\",\"ExifVersion\",\"LensModel\",\"DateTimeOriginal\"):\n",
    "            infos[tag] = v\n",
    "\n",
    "if infos:\n",
    "    print(\"EXIF détectées :\")\n",
    "    for k,v in infos.items():\n",
    "        print(f\"  - {k}: {v}\")\n",
    "else:\n",
    "    print(\"Pas d'EXIF détectées dans cette image (ou lecture impossible).\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bead7d18",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Bilan — réponds en 3 à 5 lignes :\")\n",
    "print(\"1) Quel compromis observes-tu entre qualité visuelle et taille du fichier (JPEG 95/60/30) ?\")\n",
    "print(\"2) Dans quel cas privilégierais-tu PNG plutôt que JPEG ?\")\n",
    "print(\"3) Citer une règle simple de droit à l'image (ex : publication d'un visage, cadre scolaire, etc.).\")"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 5
}
