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:
- 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).
- 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.
- Carregamento
na Memória: Alocação do recurso GD (imagecreatefromjpeg, imagecreatefrompng,
etc.).
- Redimensionamento
Proporcional: Cálculo do ratio para redimensionar a imagem
mantendo a proporção exata, utilizando imagecopyresampled().
- Preservação
de Transparência: Configuração de imagealphablending(false) e imagesavealpha(true)
para evitar que áreas transparentes fiquem pretas.
- Conversão
e Salvamento: Execução de imagewebp() com qualidade recomendada de 82%.
- 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
Postar um comentário
Para comentar e interagir neste post, clique no botão abaixo. Uma janela segura será aberta com o seu perfil e o campo de texto para digitar e publicar:
Fazer login com o Google para comentar ↗