Análises Profundas

Nascimento do WebP: VP8 como formato de imagem

koboshiCo-founder
·21 min de leitura
Nascimento do WebP: VP8 como formato de imagem
Resumo

O WebP é um container baseado em RIFF que encapsula frames de vídeo VP8 para imagens estáticas. A Google anunciou-o em 2010 com a promessa de ficheiros 25-34% mais pequenos que o JPEG e o PNG. Aqui está a história técnica completa, da assinatura do ficheiro à lacuna de adoção no mundo real.

Se abrires um ficheiro WebP num editor hexadecimal, os primeiros doze bytes são estes:

52 49 46 46 ?? ?? ?? ?? 57 45 42 50

Trata-se do cabeçalho de um contentor no estilo RIFF/WAVE. 52 49 46 46 soletra "RIFF" em ASCII. Os quatro bytes seguintes são o tamanho do ficheiro em uint32 little-endian. 57 45 42 50 soletra "WEBP". Um ficheiro WebP não é um fluxo de bits em bruto. É um contentor, tal como o áudio WAV ou o vídeo AVI, construído a partir da mesma especificação RIFF que a Microsoft introduziu em 1991. Dentro desse contentor está um fotograma de vídeo VP8, reaproveitado para uma imagem estática. Usar um códec de vídeo para fotografias é a ideia central do WebP.

A Google anunciou o WebP a 30 de setembro de 2010. A proposta era simples: a mesma qualidade visual que o JPEG, mas 25-34% mais pequeno. Para o PNG, a afirmação era ainda mais ousada, 26% mais pequeno para imagens sem perda. Numa web onde os bytes de imagem representam cerca de metade de todos os dados transferidos, esses números pareciam suficientes para uma adoção em massa. Não foram.

A aquisição que criou o WebP

O WebP não nasceu num laboratório de imagens. Nasceu de um códec de vídeo.

Em fevereiro de 2010, a Google adquiriu a On2 Technologies por aproximadamente 124 milhões de dólares. A On2 era uma empresa de compressão de vídeo com uma longa história. Os seus códecs alimentavam o vídeo Flash, as chamadas de vídeo do Skype e o streaming da AOL. O seu produto de topo era o VP8, um códec de vídeo concebido para competir com o H.264 sem royalties de patentes.

A Google tornou o VP8 open-source em maio de 2010 sob o nome WebM, agrupando-o com o códec de áudio Vorbis e o contentor Matroska. O objetivo era construir uma stack de vídeo livre de patentes para desafiar o conjunto de licenciamento H.264 da MPEG-LA, que começava a exigir royalties do streaming de vídeo na web.

Mas a Google tinha outra aplicação em mente. A compressão intra-fotograma do VP8 (a compressão de um único fotograma de vídeo sem referência a outros) era essencialmente um códec de imagens estáticas. Os mesmos modos de predição, codificação por transformada e codificação entropica que tornavam o VP8 eficiente para vídeo também funcionavam para fotografias. A Google extraiu o modo intra-fotograma, encapsulou-o num contentor RIFF e chamou-lhe WebP.

O nome foi uma escolha de marketing. "Web" porque foi concebido para a web. "P" porque os formatos de imagem terminam em P: JPEG, PNG, BMP, TIFF. O resultado foi um formato que tecnicamente era um fotograma de vídeo a fazer-se passar por fotografia.

Porque construir um novo formato?

Em 2010, o JPEG tinha dezoito anos e o PNG tinha catorze. Ambos estavam consolidados. Por que se dar ao trabalho?

O JPEG tinha limitações conhecidas. Não tinha transparência. Um pixel JPEG era totalmente opaco ou precisava de uma máscara separada. Não suportava animação como padrão. A especificação base não tinha modo sem perda (o JPEG-LS e o JPEG 2000 existiam, mas nenhum era compatível com a web). A profundidade de cor ficava nos 8 bits por canal, o que excluía gamut alargado ou HDR na base. A grelha DCT de 8 x 8 deixava artefactos de bloco visíveis em definições de qualidade abaixo de 75.

O PNG também tinha limitações reais. Era sempre sem perda. Uma fotografia de 12 MP em PNG ocupava 15-25 MB. A compressão DEFLATE do PNG não conseguia competir com o descarte psico-visual baseado em DCT. E não tinha animação na especificação base; o APNG existia, mas demorou anos a ganhar suporte nos navegadores.

A Google viu uma oportunidade: um único formato com compressão com perda e sem perda, transparência e animação, tudo em ficheiros mais pequenos. Essa era a proposta do WebP.

Como o WebP funciona de facto

O WebP tem dois formatos internos fundamentalmente diferentes: WebP com perda (VP8 intra-fotograma) e WebP sem perda (um códec separado, também derivado da pesquisa VP8).

WebP com perda: VP8 Intra

O modo com perda do WebP armazena um fluxo de bits VP8 dentro de um contentor RIFF. O pipeline de codificação assemelha-se ao JPEG, mas com diferenças importantes:

EtapaJPEGWebP com perda
TransformadaDCT 8 x 8Transformada tipo DCT inteira 4 x 4 ou 16 x 16
PrediçãoNenhuma (apenas intra)4 modos de predição intra por bloco 4 x 4
Chroma subsampling4:2:0 por omissão4:2:0 por omissão
Codificação entropicaHuffmanBinary arithmetic coding
Profundidade de bits8-bit8-bit

A predição intra é a vantagem mais importante. O JPEG codifica cada bloco 8 x 8 independentemente. O WebP prediz cada bloco 4 x 4 a partir dos vizinhos já codificados (topo, esquerda, ou ambos) e depois codifica apenas o erro de predição. Para gradientes suaves e grandes regiões planas, o erro é mínimo, e o rácio de compressão melhora significativamente.

O codificador aritmético também é mais eficiente que a codificação de Huffman do JPEG, tipicamente 5-10% de poupança adicional para a mesma qualidade.

Os benchmarks da própria Google de 2010 afirmavam:

MétricaWebP vs JPEG
Redução média do tamanho do ficheiro25-34% em SSIM equivalente
Velocidade de codificação~8x mais lento que o libjpeg
Velocidade de decodificaçãoComparável ao libjpeg

A velocidade de codificação era o custo menos visível. Produzir um ficheiro WebP exigia significativamente mais CPU que o JPEG. Para fotógrafos a exportarem centenas de imagens, isso importava.

WebP sem perda

O modo sem perda do WebP usa um códec completamente diferente. Não é VP8. É um formato personalizado que combina codificação preditiva com 14 modos de predição espacial por pixel, uma cache de cor (uma tabela hash de cores vistas recentemente para aproveitar a repetição local), back-references LZ77 com consciência do espaço 2D, e codificação entropica híbrida Huffman + aritmética que se adapta às estatísticas locais.

A Google afirmava ficheiros 26% mais pequenos que o PNG em média. Na prática, as poupanças variam imenso. Gráficos simples com grandes regiões planas vêm pouco benefício, enquanto fotografias com textura fina podem ver reduções de 30-40%.

WebP expandido (VP8X)

O chunk VP8X estende o WebP com funcionalidades adicionais. Adiciona um canal alfa de 8 bits codificado separadamente e comprimido com o codificador entropico do WebP sem perda. Suporta animação com múltiplos fotogramas e metadados de temporização, o que é essencialmente um vídeo VP8 simplificado. Também permite incluir metadados EXIF (dados da câmara e geolocalização), metadados XMP (instruções de processamento ao estilo Adobe) e um perfil de cor ICC para gestão de cor em gamut alargado ou HDR.

Um ficheiro VP8X começa com um cabeçalho de chunk VP8X, seguido de flags que indicam quais extensões estão presentes.

O formato do ficheiro

O WebP é um contentor RIFF. Compreender o layout de bytes é direto se conheceres o RIFF.

Estrutura do contentor RIFF

Bytes 0-3:   "RIFF" (0x52 0x49 0x46 0x46)
Bytes 4-7:   Tamanho do ficheiro - 8 (uint32 little-endian)
Bytes 8-11:  "WEBP" (0x57 0x45 0x42 0x50)
Bytes 12-15: Chunk FourCC: "VP8 ", "VP8L", ou "VP8X"
Bytes 16-19: Tamanho do chunk (uint32 little-endian)
Bytes 20+:   Dados do chunk

Cabeçalho expandido VP8X

Se o FourCC nos bytes 12-15 for "VP8X" (0x56 0x50 0x38 0x58):

Bytes 20-23: Tamanho do chunk = 10 (uint32 little-endian)
Bytes 24:    Byte de flags
             Bit 0: Animação presente
             Bit 1: Metadados XMP presentes
             Bit 2: Metadados EXIF presentes
             Bit 3: Alpha channel presente
             Bit 4: Perfil ICC presente
             Bits 5-7: Reservados
Bytes 25-27: Largura do canvas - 1 (uint24 little-endian)
Bytes 28-30: Altura do canvas - 1 (uint24 little-endian)

As dimensões do canvas são armazenadas como largura - 1 e altura - 1, por isso uma imagem de 1200 x 675 armazena 1199 e 674. O tamanho máximo do canvas é 16.777.215 x 16.777.215 pixels.

Tipos de chunk

FourCCConteúdoCompressão
VP8 Fluxo de bits VP8 (com perda)VP8 intra
VP8LFluxo de bits VP8L (sem perda)Sem perda personalizado
VP8XCabeçalho expandido + flagsNenhuma
ALPHDados do alpha channelEntropia do WebP sem perda
ANMFFotograma de animaçãoVP8/VP8L por fotograma
ICCPPerfil de cor ICCNenhuma
EXIFMetadados EXIFNenhuma
XMP Metadados XMPNenhuma

Detetar WebP ao ler a assinatura do ficheiro

Não confies na extensão .webp. Lê os primeiros 16 bytes e analisa o cabeçalho RIFF.

Layout exato de bytes de um WebP com perda simples:

Bytes 0-3:   "RIFF"
Bytes 4-7:   Tamanho do ficheiro (uint32 little-endian)
Bytes 8-11:  "WEBP"
Bytes 12-15: "VP8 " (com perda) ou "VP8L" (sem perda) ou "VP8X" (expandido)

TypeScript no navegador:

interface WebPInfo {
  valid: boolean
  type: "lossy" | "lossless" | "extended" | "unknown"
  width?: number
  height?: number
  hasAlpha?: boolean
  isAnimated?: boolean
}

async function inspectWebP(file: File): Promise<WebPInfo> {
  const buffer = await file.slice(0, 30).arrayBuffer()
  const bytes = new Uint8Array(buffer)

  if (bytes.length < 12) return { valid: false, type: "unknown" }

  const riff = String.fromCharCode(...bytes.slice(0, 4))
  const webp = String.fromCharCode(...bytes.slice(8, 12))
  if (riff !== "RIFF" || webp !== "WEBP") {
    return { valid: false, type: "unknown" }
  }

  const type = String.fromCharCode(...bytes.slice(12, 16))

  if (type === "VP8 ") {
    // Lossy: width/height at bytes 26-29
    const w = bytes[26] | (bytes[27] << 8)
    const h = bytes[28] | (bytes[29] << 8)
    return { valid: true, type: "lossy", width: w, height: h, hasAlpha: false }
  }

  if (type === "VP8L") {
    // Lossless: dimensions packed in bits of bytes 21-24
    const bits =
      bytes[21] | (bytes[22] << 8) | (bytes[23] << 16) | (bytes[24] << 24)
    const w = (bits & 0x3fff) + 1
    const h = ((bits >> 14) & 0x3fff) + 1
    const alpha = ((bits >> 28) & 0x01) !== 0
    return {
      valid: true,
      type: "lossless",
      width: w,
      height: h,
      hasAlpha: alpha,
    }
  }

  if (type === "VP8X") {
    const flags = bytes[20]
    const w = (bytes[24] | (bytes[25] << 8) | (bytes[26] << 16)) + 1
    const h = (bytes[27] | (bytes[28] << 8) | (bytes[29] << 16)) + 1
    return {
      valid: true,
      type: "extended",
      width: w,
      height: h,
      hasAlpha: (flags & 0x10) !== 0,
      isAnimated: (flags & 0x02) !== 0,
    }
  }

  return { valid: false, type: "unknown" }
}

Python

import struct
from typing import TypedDict

class WebPInfo(TypedDict):
    valid: bool
    type: str
    width: int | None
    height: int | None
    has_alpha: bool | None
    is_animated: bool | None

def inspect_webp(path: str) -> WebPInfo:
    with open(path, "rb") as f:
        header = f.read(30)

    if len(header) < 12:
        return {"valid": False, "type": "unknown"}

    if header[:4] != b"RIFF" or header[8:12] != b"WEBP":
        return {"valid": False, "type": "unknown"}

    chunk_type = header[12:16]

    if chunk_type == b"VP8 ":
        w, h = struct.unpack("<HH", header[26:30])
        return {"valid": True, "type": "lossy", "width": w, "height": h,
                "has_alpha": False, "is_animated": None}

    if chunk_type == b"VP8L":
        bits = struct.unpack("<I", header[21:25])[0]
        w = (bits & 0x3FFF) + 1
        h = ((bits >> 14) & 0x3FFF) + 1
        alpha = ((bits >> 28) & 0x01) != 0
        return {"valid": True, "type": "lossless", "width": w, "height": h,
                "has_alpha": alpha, "is_animated": None}

    if chunk_type == b"VP8X":
        flags = header[20]
        w = struct.unpack("<I", header[24:27] + b"\x00")[0] + 1
        h = struct.unpack("<I", header[27:30] + b"\x00")[0] + 1
        return {"valid": True, "type": "extended", "width": w, "height": h,
                "has_alpha": bool(flags & 0x10), "is_animated": bool(flags & 0x02)}

    return {"valid": False, "type": "unknown"}

Opção de nível superior com Pillow:

from PIL import Image

with Image.open("image.webp") as img:
    print(img.format)      # WEBP
    print(img.mode)        # RGB or RGBA
    print(img.size)        # (width, height)
    print(img.is_animated) # True if animated

Ou com a biblioteca webp:

import webp

info = webp.WebPInfo("image.webp")
print(info.width, info.height, info.has_alpha)

Go

package main

import (
	"encoding/binary"
	"fmt"
	"os"
)

type WebPInfo struct {
	Valid       bool
	Type        string
	Width       int
	Height      int
	HasAlpha    bool
	IsAnimated  bool
}

func inspectWebP(path string) (WebPInfo, error) {
	f, err := os.Open(path)
	if err != nil {
		return WebPInfo{}, err
	}
	defer f.Close()

	buf := make([]byte, 30)
	if _, err := f.Read(buf); err != nil {
		return WebPInfo{}, err
	}

	if string(buf[:4]) != "RIFF" || string(buf[8:12]) != "WEBP" {
		return WebPInfo{Valid: false, Type: "unknown"}, nil
	}

	typeStr := string(buf[12:16])
	switch typeStr {
	case "VP8 ":
		w := int(binary.LittleEndian.Uint16(buf[26:28]))
		h := int(binary.LittleEndian.Uint16(buf[28:30]))
		return WebPInfo{Valid: true, Type: "lossy", Width: w, Height: h, HasAlpha: false}, nil
	case "VP8L":
		bits := binary.LittleEndian.Uint32(buf[21:25])
		w := int(bits&0x3FFF) + 1
		h := int((bits>>14)&0x3FFF) + 1
		alpha := ((bits >> 28) & 0x01) != 0
		return WebPInfo{Valid: true, Type: "lossless", Width: w, Height: h, HasAlpha: alpha}, nil
	case "VP8X":
		flags := buf[20]
		w := int(binary.LittleEndian.Uint32(append(buf[24:27], 0))) + 1
		h := int(binary.LittleEndian.Uint32(append(buf[27:30], 0))) + 1
		return WebPInfo{
			Valid: true, Type: "extended", Width: w, Height: h,
			HasAlpha: (flags & 0x10) != 0, IsAnimated: (flags & 0x02) != 0,
		}, nil
	}

	return WebPInfo{Valid: false, Type: "unknown"}, nil
}

PHP

function inspectWebP(string $path): array {
    $header = file_get_contents($path, false, null, 0, 30);
    if (strlen($header) < 12) {
        return ["valid" => false, "type" => "unknown"];
    }

    if (substr($header, 0, 4) !== "RIFF" || substr($header, 8, 4) !== "WEBP") {
        return ["valid" => false, "type" => "unknown"];
    }

    $type = substr($header, 12, 4);

    if ($type === "VP8 ") {
        $w = unpack("v", substr($header, 26, 2))[1];
        $h = unpack("v", substr($header, 28, 2))[1];
        return ["valid" => true, "type" => "lossy", "width" => $w, "height" => $h, "has_alpha" => false];
    }

    if ($type === "VP8L") {
        $bits = unpack("V", substr($header, 21, 4))[1];
        $w = ($bits & 0x3FFF) + 1;
        $h = (($bits >> 14) & 0x3FFF) + 1;
        $alpha = (($bits >> 28) & 0x01) !== 0;
        return ["valid" => true, "type" => "lossless", "width" => $w, "height" => $h, "has_alpha" => $alpha];
    }

    if ($type === "VP8X") {
        $flags = ord($header[20]);
        $w = unpack("V", substr($header, 24, 3) . "\x00")[1] + 1;
        $h = unpack("V", substr($header, 27, 3) . "\x00")[1] + 1;
        return [
            "valid" => true, "type" => "extended",
            "width" => $w, "height" => $h,
            "has_alpha" => (bool)($flags & 0x10),
            "is_animated" => (bool)($flags & 0x02),
        ];
    }

    return ["valid" => false, "type" => "unknown"];
}

Com fileinfo:

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('image.webp');
// image/webp

ImageMagick CLI

magick identify -verbose image.webp | grep "Format:"
# Format: WEBP (WebP Image Format)

Extração completa de metadados:

magick identify -verbose image.webp

Isto devolve largura, altura, profundidade de cor, presença de alpha, tipo de compressão e informação do perfil ICC.

Ou simplesmente:

file image.webp
# image.webp: RIFF (little-endian) data, Web/P image

Os pontos fortes

O WebP é forte em algumas dimensões específicas.

Os ficheiros são mais pequenos. No corpus de referência da Google, o WebP com perda médio era 25-34% mais pequeno que o JPEG no mesmo SSIM. O WebP sem perda médio era 26% mais pequeno que o PNG. Para sites de alto tráfego, essas poupanças traduzem-se em custos de largura de banda e em carregamentos de página mais rápidos.

Também consolida funcionalidades. Um formato substitui tanto o JPEG como o PNG para a maioria dos casos de uso. Modo com perda para fotografias, modo sem perda para gráficos, canal alfa para transparência, animação para sequências curtas. Um programador web precisa de conhecer um formato em vez de três.

A decodificação nativa no navegador é outra vantagem. O Chrome, Firefox, Safari e Edge incluem todos descodificadores WebP acelerados por hardware ou altamente otimizados por software. A velocidade de decodificação é comparável ao JPEG no desktop e dentro de 10-20% no telemóvel.

O WebP suporta decodificação progressiva. A exibição incremental à medida que os dados chegam funciona de forma semelhante ao modo progressivo do JPEG. Para ligações lentas, uma imagem reconhecível aparece após receber cerca de 30% do ficheiro.

A animação também é forte. Ficheiros WebP animados são tipicamente 60-80% mais pequenos que GIFs animados em qualidade visual equivalente, com cor a 24 bits e alfa de 8 bits por fotograma.

Os pontos fracos

Os problemas do WebP têm menos a ver com tecnologia e mais a ver com ecossistema.

A velocidade de codificação é um deles. Em 2010, a codificação WebP era aproximadamente 8x mais lenta que o libjpeg. A lacuna estreitou; o libwebp em 2026 é cerca de 2-3x mais lento que o libjpeg-turbo. Ainda assim, importa para fluxos de trabalho em lote. Um fotógrafo a exportar 1.000 imagens esperará notoriamente mais tempo.

Outra limitação é a ausência de suporte a 16 bits ou HDR. O WebP é estritamente 8 bits por canal. Para fotografia de gamut alargado, imagens médicas ou conteúdo HDR, o WebP é inutilizável. O HEIC, AVIF e JPEG XL suportam todas profundidades de bits superiores.

Também não existe recompressão sem perda de JPEG. O JPEG XL pode pegar num JPEG existente e recompressá-lo sem perda para cerca de 20% de poupança. O WebP não consegue. Converter um JPEG para WebP exige recodificação completa, o que introduz generation loss.

As ferramentas também demoraram. O Photoshop não suportou WebP nativamente até 2022. O suporte WebP do ImageMagick exigia compilação de um plugin libwebp, que muitas distribuições omitiam por omissão. Muitos sistemas de gestão de conteúdo ainda geram JPEG/PNG por omissão.

Por fim, há a nuvem de patentes do VP8. A Google lançou o VP8 com uma promessa de indemnização de patentes, mas o panorama de patentes do códec nunca foi tão limpo como o do PNG ou do JPEG. Algumas organizações evitaram o WebP precisamente porque não confiavam que o escudo legal da Google se sustentasse em tribunal.

Porque o formato "inferior" venceu

O JPEG tem trinta e quatro anos. Não tem transparência, animação, modo sem perda, e apresenta artefactos visíveis em qualidade 75. O WebP vence-o em quase todas as métricas. Ainda assim, o Web Almanac de 2025 coloca o JPEG em cerca de 46% de todas as imagens web contra 19% do WebP.

A explicação não está na tecnologia. Está nos efeitos de rede e nos custos de mudança.

O JPEG é o QWERTY dos formatos de imagem. Cada câmara guarda JPEG por omissão. Cada telemóvel mostra JPEG nativamente. Cada impressora aceita JPEG. Cada rede social, CMS, CDN e cliente de email processa JPEG sem plugins, códecs ou conversão. O formato é tão universal que "imagem" e "JPEG" são funcionalmente sinónimos para a maioria dos utilizadores.

A curva de adoção do WebP conta a história:

AnoMarco
2010Google anuncia o WebP (Chrome 8)
2012Chrome 23 adiciona suporte sem perda e alfa
2013Chrome adiciona WebP animado
2014Android 4.0+ adiciona suporte WebP nativo
2015Facebook converte todas as fotos mobile para WebP
2016Safari 14 adiciona suporte WebP
2020Suporte universal nos navegadores alcançado
2022Photoshop adiciona exportação WebP nativa
2025WebP em 19% das imagens web segundo o Web Almanac

O Chrome promoveu o WebP de forma agressiva porque a Google controlava o navegador e o formato. O Facebook adotou-o porque poupava petabytes de largura de banda. Mas a cauda longa da web (blogs WordPress, pequenos sites de comércio eletrónico, implantações empresariais de CMS, newsletters por email) moveu-se lentamente, ou nem se moveu.

O ponto de falha crítico foi o ecossistema da Apple. Os iPhones guardavam HEIC por omissão, não WebP. O Preview do macOS não suportou WebP até ao macOS 11 Big Sur (2020). O menu de partilha do iOS não oferecia exportação WebP. Para fotógrafos, designers e criadores de redes sociais que trabalham principalmente em dispositivos Apple, o WebP era invisível.

Entretanto, o AVIF chegou em 2019 com melhor compressão que o WebP e licenciamento livre de royalties da Alliance for Open Media. O Chrome, Firefox e Safari incluem todos AVIF. A Cloudflare e a Cloudinary servem AVIF automaticamente. O WebP tornou-se um degrau, melhor que o JPEG, mas já a ser ultrapassado pela próxima geração.

Onde o WebP se situa hoje

O WebP acabou por ser um sucesso parcial.

Para programadores web a construir projetos novos em 2026, o WebP é a escolha pragmática por omissão para imagens que precisam de transparência ou animação. É mais pequeno que o PNG para gráficos sem perda e mais pequeno que o JPEG para fotografias. O suporte nos navegadores é universal. As ferramentas de codificação são maduras.

Mas o WebP não substituiu o JPEG. Esculpiu um nicho ao lado dele, o mesmo nicho que o PNG já ocupava, apenas com ficheiros mais pequenos. A ideia de "um formato para todas as imagens" não se concretizou.

Em 2026, a escolha prática é mais ou menos esta:

Caso de usoMelhor formatoPorquê
Fotografias (legado)JPEGUniversal, codificação rápida, suficientemente pequeno
Fotografias (novo)AVIF30% mais pequeno que o WebP, livre de royalties
Fotografias (fallback)WebP25% mais pequeno que o JPEG, suporte universal
Gráficos sem perdaWebP ou PNGWebP é mais pequeno; PNG é o fallback seguro
TransparênciaWebP ou PNGWebP tem ficheiros mais pequenos; PNG é o fallback seguro
AnimaçãoWebP ou AVIFAmbos vencem o GIF em 60-80%; AVIF é mais recente
Gamut alargado / HDRAVIF ou JPEG XLProfundidade de 10+ bits, suporte ICC/ICC v4
Fluxos de trabalho de impressãoTIFF ou JPEG XLCMYK, 16-bit, recompressão sem perda de JPEG

O WebP provou que a web pode adotar novos formatos de imagem quando um grande fornecedor de navegadores empurra com força suficiente. Tornou o caminho mais fácil para o AVIF, forçou a Apple a suportar formatos não-JPEG/PNG nativamente, e mostrou que transparência e animação pertencem num único contentor.

Mas também provou que ter a tecnologia mais avançada não chega. A ubiquidade, a inércia e o alinhamento do ecossistema importam mais que os rácios de compressão. O JPEG sobreviverá ao WebP não porque seja melhor, mas porque já está em todo o lado.

Conclusão

O WebP foi construído a partir de um códec de vídeo para resolver um problema de largura de banda. Resolveu esse problema para a Google, para o Facebook e para qualquer site disposto a converter o pipeline de imagens. A compressão é real, as funcionalidades são úteis, e o suporte nos navegadores é completo.

Mas a web não muda de formato porque um white paper diz que o novo é 25% mais pequeno. Muda quando o novo formato é mais fácil de usar do que o antigo, ou quando o antigo falha de forma tão grave que a migração é inevitável. O JPEG não falhou o suficiente. O WebP não foi fácil o suficiente. Quando o WebP finalmente se tornou fácil, o AVIF já tinha chegado com melhores números na ficha técnica.

O WebP assemelha-se ao Betamax dos formatos de imagem: tecnicamente sólido, bem suportado, mas ultrapassado por algo que chegou pouco depois com melhor marketing e apoio mais amplo. Não vai desaparecer, mas vai coexistir com o JPEG, PNG, AVIF e o que vier a seguir, desempenhando o mesmo papel que o PNG desempenha hoje: o fallback seguro e capaz que funciona em todo o lado.

Se tens ficheiros PNG que precisam de pegadas mais pequenas para a web, PNG to WebP converte-os localmente no teu navegador, sem uploads nem processamento no servidor. Para JPEGs que precisam de transparência ou animação, JPG to WebP trata da conversão com controlo de qualidade. E quando precisas do fallback universal, WebP to PNG e WebP to JPG trazem ficheiros WebP de volta a formatos que abrem em todos os visualizadores.

Mais posts do blog