Intervention devinsto
Thème :
Junior
1 vues ·3/8 leçons

03 - Le Cœur du Système : ImageProcessingService

J’ai centralisé toute l’intelligence du traitement dans un service unique pour garantir la réutilisabilité et la propreté de votre code.

Le Code Source Complet

Voici l’implémentation exacte de app/Services/ImageProcessingService.php :

<?php

declare(strict_types=1);

namespace App\Services;

use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Laravel\Facades\Image;
use Intervention\Image\Typography\FontFactory;

class ImageProcessingService
{
    public function processBlogCover(string $path): void
    {
        $fullPath = storage_path('app/public/' . $path);

        if (! file_exists($fullPath)) {
            return;
        }

        // 1. Chargement (v4 API)
        $image = Image::decode($fullPath);

        // 2. Filigrane répétitif
        $this->addRepeatingWatermark($image, 'www.devinsto.com');

        // 3. Logo Branding
        $this->addLogo($image);

        // 4. Sauvegarde optimisée (80% qualité)
        $image->save($fullPath, quality: 80);
    }

    private function addRepeatingWatermark(ImageInterface $image, string $text): void
    {
        $width = $image->width();
        $height = $image->height();

        // J'ai créé un motif de 300x200px pour une répétition harmonieuse
        $tileWidth = 300;
        $tileHeight = 200;

        $tile = Image::createImage($tileWidth, $tileHeight);
        $fontPath = base_path('resources/font/Nunito-Regular.ttf');

        $tile->text($text, (int) ($tileWidth / 2), (int) ($tileHeight / 2), function (FontFactory $font) use ($fontPath) {
            if (file_exists($fontPath)) {
                $font->file($fontPath);
            }
            $font->size(20);
            $font->color('ffffff44'); // Blanc avec 44% d'opacité
            $font->align('center', 'center'); // Correction API v3/v4 : pas de valign()
            $font->angle(45);
        });

        // J'insère le motif en boucle sur toute l'image
        for ($x = 0; $x < $width; $x += $tileWidth) {
            for ($y = 0; $y < $height; $y += $tileHeight) {
                $image->insert($tile, $x, $y, 'top-left');
            }
        }
    }

    private function addLogo(ImageInterface $image): void
    {
        $logoPath = public_path('android-chrome-512x512.png');

        if (file_exists($logoPath)) {
            $logo = Image::decode($logoPath);

            // Redimensionnement dynamique à 8% de la largeur
            $logoWidth = (int) ($image->width() * 0.08);
            $logo->scale(width: $logoWidth);

            // Insertion au centre à droite avec marge de 40px
            $image->insert($logo, 40, 0, 'right');
        }
    }
}

Décryptage de mes choix techniques

1. La gestion de la police (Nunito)

J’ai choisi de pointer vers resources/font/Nunito-Regular.ttf. J’ai ajouté une vérification file_exists pour éviter que le script ne plante si la police est absente (dans ce cas, Intervention utilise la police système par défaut).

2. Le calcul du Logo

J’ai utilisé $logo->scale(width: $logoWidth). Pourquoi ? Contrairement à resize(), scale() conserve l’aspect ratio automatiquement sans que j’aie besoin de spécifier la hauteur. C’est plus sûr pour votre logo.

3. L’alignement du texte

J’ai utilisé $font->align('center', 'center'). C’est une spécificité de la nouvelle API Intervention Image. L’ancien valign() n’existe plus, tout se passe maintenant dans la méthode align().

Prêt à passer à la suite ?

Vous avez terminé cette leçon sur 03 - Le Cœur du Système : ImageProcessingService. Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.