IDEIAS EM CONSTRUÇÃO PARA QUEM CRIA COM CÓDIGO VIBE CODE / IA / TECNOLOGIA

Leitura em foco

Aprender · testar · compartilhar

Conversão de Imagens para WebP: Como Automatizar o Processo e Otimizar sua Aplicação

André Bueno

 


As imagens representam, em média, 50% do peso total de uma página web. Em projetos de ecommerce, sites de notícias ou portais literários como o LiteraMundo que é um portal de livros sem direitos autorais desenvolvido e mantido por mim, o carregamento rápido de capas de livros, fotos de autores e banners é um fator determinante tanto para a experiência do usuário quanto para o ranqueamento nos motores de busca.

Neste artigo técnico detalhado, baseado nas diretrizes de engenharia e otimização do LiteraMundo, vamos explorar como implementar a conversão automática de imagens para o formato WebP utilizando PHP e a GD Library, garantindo máxima performance, economia de banda e excelente pontuação nos Core Web Vitals.

1. O que é o WebP e por que utilizá-lo?

Desenvolvido pelo Google e lançado em 2010, o WebP é um formato de imagem moderno que fornece compressão superior (tanto com perda quanto sem perda) para a web.

  • Compressão Lossy (Com perda): Imagens WebP são em média 25% a 35% menores que arquivos JPEG comparáveis, mantendo exatamente o mesmo índice de qualidade visual (SSIM).
  • Compressão Lossless (Sem perda): É cerca de 26% menor que arquivos PNG.
  • Canal Alfa (Transparencia): Suporta transparência completa, substituindo arquivos PNG pesados com alta eficiência.
  • Compatibilidade: Suportado por mais de 97% dos navegadores modernos (Chrome, Firefox, Safari, Edge).

2. O Fluxo Técnico da Conversão Automática

Para garantir que nenhuma imagem pesada entre no acervo do seu site, o pipeline de conversão no momento do upload segue sete etapas fundamentais:

  1. Validação de Arquivo: Verificação se o arquivo existe e é uma imagem real utilizando getimagesize() (nunca confiando apenas na extensão enviada pelo usuário).
  2. Detecção do Tipo MIME: Identificação do formato de origem (image/jpeg, image/png, image/gif, image/bmp) para carregar com a função GD correta.
  3. Carregamento na Memória: Alocação do recurso GD (imagecreatefromjpeg, imagecreatefrompng, etc.).
  4. Redimensionamento Proporcional: Cálculo do ratio para redimensionar a imagem mantendo a proporção exata, utilizando imagecopyresampled().
  5. Preservação de Transparência: Configuração de imagealphablending(false) e imagesavealpha(true) para evitar que áreas transparentes fiquem pretas.
  6. Conversão e Salvamento: Execução de imagewebp() com qualidade recomendada de 82%.
  7. Limpeza de Recursos: Destruição dos recursos da memória RAM com imagedestroy().

3. Implementação Prática em PHP

Abaixo está o motor central de otimização e conversão utilizado no projeto LiteraMundo, integrando a biblioteca nativa GD Library do PHP.

A Função Central: otimizar_imagem() e converter_arquivo_para_webp()

PHP

<?php

/**

 * Converte e otimiza qualquer imagem compatível para WebP.

 */

function converter_arquivo_para_webp($sourcePath, $destPath, $maxWidth = 800, $maxHeight = 1200, $quality = 82, $removerOrigem = false) {

    if (!file_exists($sourcePath) || !is_file($sourcePath)) return false;

    if (!function_exists("imagewebp")) return false;

 

    $ok = otimizar_imagem($sourcePath, $destPath, $maxWidth, $maxHeight, $quality, "webp");

 

    if ($ok && file_exists($destPath) && filesize($destPath) > 0) {

        if ($removerOrigem && realpath($sourcePath) !== realpath($destPath)) {

            @unlink($sourcePath);

        }

        return true;

    }

    return false;

}

 

function otimizar_imagem($sourcePath, $destPath, $maxWidth = 600, $maxHeight = 900, $quality = 82, $forceFormat = null) {

    $imageInfo = @getimagesize($sourcePath);

    if (!$imageInfo) return false;

 

    $origWidth = $imageInfo[0];

    $origHeight = $imageInfo[1];

    $mime = $imageInfo['mime'];

 

    // Carrega conforme MIME detectado

    switch ($mime) {

        case "image/jpeg": $img = @imagecreatefromjpeg($sourcePath); break;

        case "image/png":  $img = @imagecreatefrompng($sourcePath); break;

        case "image/webp": $img = @imagecreatefromwebp($sourcePath); break;

        case "image/gif": 

        case "image/bmp": 

            $img = @imagecreatefromgif($sourcePath);

            break;

        default: return false;

    }

 

    if (!$img) return false;

 

    // Redimensionamento proporcional

    $newW = $origWidth;

    $newH = $origHeight;

    if ($origWidth > $maxWidth || $origHeight > $maxHeight) {

        $ratio = min($maxWidth / $origWidth, $maxHeight / $origHeight);

        $newW = (int)round($origWidth * $ratio);

        $newH = (int)round($origHeight * $ratio);

    }

 

    $target = imagecreatetruecolor($newW, $newH);

 

    // Essencial para preservar transparência (Canal Alfa)

    imagealphablending($target, false);

    imagesavealpha($target, true);

    $transp = imagecolorallocatealpha($target, 255, 255, 255, 127);

    imagefilledrectangle($target, 0, 0, $newW, $newH, $transp);

 

    imagecopyresampled($target, $img, 0, 0, 0, 0, $newW, $newH, $origWidth, $origHeight);

 

    // Salva no formato WebP

    $success = imagewebp($target, $destPath, $quality);

 

    imagedestroy($img);

    imagedestroy($target);

 

    return $success;

}

4. Upload com Conversão Automática na Publicação

No fluxo de cadastro de livros do LiteraMundo, todo arquivo enviado via formulário passa por uma camada de sanitização e conversão instantânea:

PHP

function processar_upload_imagem($fileInput, $destDir, $baseName, $maxWidth = 600, $maxHeight = 900, $quality = 82) {

    if (empty($fileInput["tmp_name"]) || !is_uploaded_file($fileInput["tmp_name"])) return false;

    if (!is_dir($destDir)) mkdir($destDir, 0755, true);

 

    // Sanitiza o nome do arquivo baseado no slug

    $cleanName = preg_replace("/[^a-zA-Z0-9_-]/", "", $baseName);

    $fileName = $cleanName . ".webp";

    $destPath = rtrim($destDir, "/") . "/" . $fileName;

 

    $ok = otimizar_imagem($fileInput["tmp_name"], $destPath, $maxWidth, $maxHeight, $quality, "webp");

 

    if ($ok && file_exists($destPath)) {

        return $fileName;

    }

    return false;

}

Exemplo de Aplicação no Cadastro (cadastro_livro.php):

PHP

require_once "db/image_helper.php";

 

if (!empty($_FILES["capa"]["tmp_name"])) {

    $slug = gerar_slug($titulo_livro);

   

    $nomeArquivo = processar_upload_imagem(

        $_FILES["capa"],

        __DIR__ . "/uploads/capas",

        $slug,

        600, 900, 82

    );

 

    if ($nomeArquivo) {

        // Grava apenas o nome do arquivo otimizado (.webp) no banco de dados

        $stmt = $pdo->prepare("UPDATE livros SET capa = ? WHERE id = ?");

        $stmt->execute([$nomeArquivo, $livroId]);

    }

}

5. Conversão em Lote (Batch Converter) para Acervos Legados

Caso o seu projeto já possua um grande volume de imagens antigas em JPEG ou PNG, você pode criar um script executado via linha de comando (CLI) para converter todo o acervo de forma retroativa:

PHP

// Execução via terminal:

// php batch_converter.php /var/www/html/uploads 82 true

 

$diretorio = $argv[1] ?? __DIR__ . '/uploads';

$qualidade = isset($argv[2]) ? (int)$argv[2] : 82;

$removerOriginal = isset($argv[3]) ? filter_var($argv[3], FILTER_VALIDATE_BOOLEAN) : false;

 

$iterator = new RecursiveIteratorIterator(

    new RecursiveDirectoryIterator($diretorio, RecursiveDirectoryIterator::SKIP_DOTS)

);

 

$extsValidas = ["jpg", "jpeg", "png", "bmp"];

$estatisticas = ["total" => 0, "sucesso" => 0, "falhas" => 0];

 

foreach ($iterator as $item) {

    if ($item->isDir()) continue;

    $caminho = $item->getRealPath();

    $ext = strtolower(pathinfo($caminho, PATHINFO_EXTENSION));

 

    if (!in_array($ext, $extsValidas)) continue;

 

    $caminhoWebp = preg_replace("/\.(jpe?g|png|bmp)$/i", ".webp", $caminho);

 

    if (file_exists($caminhoWebp) && filemtime($caminhoWebp) > filemtime($caminho)) continue;

 

    $estatisticas["total"]++;

    $img = match($ext) {

        "jpg", "jpeg" => @imagecreatefromjpeg($caminho),

        "png", "bmp"  => @imagecreatefrompng($caminho),

        default       => null,

    };

 

    if (!$img) { $estatisticas["falhas"]++; continue; }

 

    if (@imagewebp($img, $caminhoWebp, $qualidade)) {

        $estatisticas["sucesso"]++;

        if ($removerOriginal) @unlink($caminho);

    } else {

        $estatisticas["falhas"]++;

    }

    imagedestroy($img);

}

 

echo "Conversão concluída! Sucessos: {$estatisticas['sucesso']} | Falhas: {$estatisticas['falhas']}\n";

6. Impacto Direto nos Core Web Vitals (LCP e CLS)

A conversão para WebP reflete diretamente nas métricas avaliadas pelo Google:

  • LCP (Largest Contentful Paint): Como as capas de livros costumam ser os elementos visuais principais (acima da dobra), imagens WebP menores baixam muito mais rápido, reduzindo drasticamente o tempo de LCP.
  • CLS (Cumulative Layout Shift): Sempre declare explicitamente as propriedades de largura e altura nas tags HTML para reservar o espaço correto antes mesmo de o arquivo carregar:

HTML

<img src="uploads/capas/o-ultimo-like.webp"

     alt="Capa do livro O Último Like"

     width="600"

     height="900"

     loading="lazy"

     decoding="async">

Conclusão

Implementar a conversão automática para WebP como feito no portal LiteraMundo reduz em torno de 30% o peso das imagens, economiza banda de servidor, acelera a entrega de conteúdo e melhora significativamente o ranqueamento orgânico do site.

Traga seu café, ajuste suas rotinas de upload e garanta máxima performance nos seus projetos web!

 


Comentários