Skip to content

Repository files navigation

image-variants-webp

Utilitaire Python pour générer des variantes d'images à partir d'un dossier source, selon une liste de breakpoints, puis les convertir en WEBP.

La version avancée du script génère également un manifest.json afin de faciliter l'exploitation des images responsive dans une application web, par exemple avec Symfony / Twig.


Fonctionnalités

  • Parcours récursif d'un dossier d'images
  • Génération de variantes responsive selon des breakpoints prédéfinis
  • Conversion en WEBP
  • Conservation du ratio
  • Pas d'upscale
  • Option pour générer aussi une version WEBP de l'original
  • Génération automatique d'un manifest.json
  • Métadonnées exploitables côté backend/frontend :
    • largeur
    • hauteur
    • poids du fichier
    • chemin de sortie
    • format

Dépendances

Le projet utilise :

  • Pillow

Installation

Globale avec pipx (recommandé pour utiliser image-to-webp partout)

pipx install git+https://github.com/DenZaiyy/image-compressor.git

La commande image-to-webp est ensuite disponible dans tout terminal :

image-to-webp images/ --keep-original-webp --pretty-manifest

Locale dans un projet (environnement virtuel)

Créer un environnement virtuel :

python3 -m venv .venv
source .venv/bin/activate

Installer les dépendances :

pip install -r requirements.txt

Scripts disponibles

1. Version simple

python3 image_variants_to_webp.py images

Cette version :

  • génère les variantes WEBP
  • ne produit pas de manifest

2. Version avancée avec manifest

python3 image_variants_to_webp.py images --keep-original-webp --pretty-manifest

Cette version :

  • génère les variantes WEBP
  • peut générer aussi l'original en WEBP
  • produit automatiquement un manifest.json

Exemples d'utilisation

Exemple simple

python3 image_variants_to_webp.py images

Générer aussi l'original en WEBP

python3 image_variants_to_webp.py images --keep-original-webp

Utiliser des breakpoints personnalisés

python3 image_variants_to_webp.py images -b 400 800 1200 1600

Définir un dossier de sortie

python3 image_variants_to_webp.py images -o generated_webp

Générer un manifest lisible

python3 image_variants_to_webp.py images --pretty-manifest

Ignorer les fichiers déjà générés

python3 image_variants_to_webp.py images --skip-existing

Forcer le mode lossless

python3 image_variants_to_webp.py images --lossless

Breakpoints par défaut

Le script utilise par défaut des breakpoints classiques :

  • 320
  • 480
  • 768
  • 1024
  • 1280
  • 1536
  • 1920

Exemple de structure d'entrée / sortie

Entrée

images/
├── hero/banner.jpg
└── products/gpu.png

Sortie

generated_webp/
├── hero/
│   ├── banner.webp
│   ├── banner-320w.webp
│   ├── banner-480w.webp
│   ├── banner-768w.webp
│   └── ...
├── products/
│   ├── gpu.webp
│   ├── gpu-320w.webp
│   ├── gpu-480w.webp
│   ├── gpu-768w.webp
│   └── ...
└── manifest.json

Exemple de manifest.json

{
  "meta": {
    "generator": "image_variants_to_webp.py",
    "breakpoints": [320, 480, 768, 1024, 1280, 1536, 1920],
    "quality": 85,
    "method": 6,
    "lossless": false,
    "keep_original_webp": true,
    "flatten_alpha": false,
    "images_count": 2
  },
  "images": {
    "products/gpu.png": {
      "source": "products/gpu.png",
      "source_filename": "gpu.png",
      "source_extension": ".png",
      "original_width": 1600,
      "original_height": 1600,
      "generated_original": {
        "width": 1600,
        "height": 1600,
        "path": "generated_webp/products/gpu.webp",
        "filename": "gpu.webp",
        "size_bytes": 123456,
        "format": "webp"
      },
      "variants": [
        {
          "width": 320,
          "height": 320,
          "path": "generated_webp/products/gpu-320w.webp",
          "filename": "gpu-320w.webp",
          "size_bytes": 8450,
          "format": "webp"
        }
      ]
    }
  }
}

Utilité du manifest

Le manifest.json sert de registre des images générées.

Il permet de :

  • retrouver automatiquement toutes les variantes d'une image
  • construire un srcset
  • éviter de recalculer les chemins à la main
  • préparer une intégration backend propre
  • servir de source de vérité pour les assets responsive

Exemple d'usage web : srcset

Le manifest peut ensuite être exploité pour produire un attribut HTML srcset :

<img
  src="/generated_webp/products/gpu.webp"
  srcset="
    /generated_webp/products/gpu-320w.webp 320w,
    /generated_webp/products/gpu-768w.webp 768w,
    /generated_webp/products/gpu-1280w.webp 1280w
  "
  sizes="(max-width: 768px) 100vw, 33vw"
  alt="GPU"
/>

Le navigateur choisira automatiquement la variante la plus pertinente selon :

  • la taille d'écran
  • la largeur réelle de rendu
  • la densité de pixels

Options utiles

Options communes

  • -o, --output-dir : dossier de sortie
  • -b, --breakpoints : liste de largeurs cibles
  • --quality : qualité WEBP
  • --method : niveau de compression WEBP
  • --lossless : export sans perte
  • --skip-existing : ignore les fichiers déjà présents
  • --flatten-alpha : aplatit la transparence sur fond blanc

Options avancées

  • --keep-original-webp : génère aussi l'original en WEBP
  • --manifest-name : personnalise le nom du manifest
  • --pretty-manifest : formate le manifest avec indentation

Intégrations

Les fichiers d'intégration complets se trouvent dans le dossier examples/.

Symfony / Twig

Flow complet :

  1. Le script génère les images et le manifest.json dans public/images/generated_webp/
  2. Un service Symfony charge le manifest
  3. Une extension Twig expose une fonction responsive_image()
  4. Tes templates appellent cette fonction avec la clé source

Fichiers fournis dans examples/symfony/ :

Fichier Rôle
src/Service/ImageManifestService.php Charge et expose le manifest
src/Twig/Extension/ImageManifestExtension.php Fonction Twig responsive_image()
templates/_components/responsive_image.html.twig Partial HTML de l'image
config/services.yaml Configuration du service

Usage dans un template Twig :

{{ responsive_image('products/gpu.png', 'GPU RTX 4090', '(max-width: 768px) 100vw, 50vw') }}

Avec des attributs supplémentaires :

{{ responsive_image('hero/banner.jpg', 'Bannière', '100vw', { class: 'hero__img', fetchpriority: 'high' }) }}

React

Fichiers fournis dans examples/react/ :

Fichier Rôle
useResponsiveImage.ts Hook qui lit le manifest et retourne src, srcset, dimensions
ResponsiveImage.tsx Composant <img> responsive prêt à l'emploi

Usage :

import { ResponsiveImage } from './ResponsiveImage';

// Utilisation directe du composant
<ResponsiveImage
  source="products/gpu.png"
  alt="GPU RTX 4090"
  sizes="(max-width: 768px) 100vw, 33vw"
  className="product__img"
/>

// Ou via le hook pour un usage custom
import { useResponsiveImage } from './useResponsiveImage';

const image = useResponsiveImage('products/gpu.png');
if (image) {
  // image.src, image.srcset, image.width, image.height
}

Le manifest.json doit être importable par le bundler (Vite, webpack…). Place-le dans src/ ou configure un alias.


Vue

Fichiers fournis dans examples/vue/ :

Fichier Rôle
useResponsiveImage.ts Composable réactif (accepte string ou ComputedRef<string>)
ResponsiveImage.vue Composant SFC prêt à l'emploi

Usage :

<script setup lang="ts">
import ResponsiveImage from './ResponsiveImage.vue';
</script>

<template>
  <ResponsiveImage
    source="products/gpu.png"
    alt="GPU RTX 4090"
    sizes="(max-width: 768px) 100vw, 33vw"
  />
</template>

Avec le composable seul :

import { useResponsiveImage } from './useResponsiveImage';

const { image } = useResponsiveImage('products/gpu.png');
// image.value?.src, image.value?.srcset, ...

Roadmap possible

  • Export AVIF en complément du WEBP
  • Génération d'un blur placeholder
  • Support de profils de presets par contexte (thumbnail, hero, product-card, etc.)
  • Publication sur PyPI

Licence

MIT LICENSE

About

Generate responsive image variants in WebP with automatic manifest.json generation.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages