Skip to content

Methodology

Metodologia de formatos de imagem

Canvas API + codificadores nativos do navegador. A imagem nunca sai do seu dispositivo.

By Published

O cluster de Imagem converte entre PNG, JPG e WebP usando a Canvas API nativa do navegador. Não há etapa de upload, sem processamento do lado do servidor e sem serviço de imagem de terceiros no caminho — o que tem implicações para privacidade e qualidade.

O pipeline de conversão

  1. O usuário escolhe um arquivo via arrastar e soltar ou seletor de arquivo.
  2. O arquivo é lido como um ImageBitmap via createImageBitmap(file).
  3. Um canvas offscreen é criado nas dimensões nativas do bitmap.
  4. O bitmap é desenhado no canvas.
  5. O canvas é exportado via canvas.toBlob(callback, mimeType, quality) — qualidade aplica-se apenas a destinos com perdas.
  6. O Blob resultante é oferecido como download.

Cada etapa é executada no navegador. O arquivo não é enviado para lugar nenhum — não há fetch, FormData ou upload XHR. O mesmo se aplica à ferramenta Imagem para Base64, que usa a FileReader API em vez do canvas, mas segue o mesmo princípio exclusivo do navegador.

Tratamento de qualidade

Sem perdas → com perdas (PNG/WebP → JPG)

Ao ir de um formato sem perdas para JPG, expomos um controle deslizante de qualidade (padrão 0,85) que controla a agressividade de quantização do codificador JPG. Em 0,85, o arquivo é tipicamente 80-95% menor que o PNG de origem sem diferença visual perceptível para fotografias. Abaixo de 0,7, os artefatos tornam-se visíveis; limitamos o valor mínimo em 0,5 para evitar produzir acidentalmente uma saída visivelmente degradada.

Com perdas → sem perdas (JPG → PNG)

Ir de JPG para PNG não restaura a qualidade que o JPG já descartou. A saída é bit-perfeita do que o JPG decodificou, mas as perdas de arredondamento do JPG estão incorporadas. Isso raramente é útil na prática; o melhor caminho é encontrar uma fonte de maior qualidade.

Com perdas → com perdas (JPG → WebP, etc.)

Cada salvamento com perdas introduz novos erros de quantização sobre os existentes na fonte. Para arquivos que passaram por vários salvamentos, isso pode causar degradação composta visível. Sempre recodifique a partir da fonte de mais alta qualidade que você tiver.

O que não tratamos

  • HEIC / HEIF. O padrão da Apple desde o iOS 11. O suporte do navegador é essencialmente zero fora do ecossistema Apple, portanto precisaríamos incluir um decodificador de 1+ MB. Não vale a pena.
  • Formatos RAW (DNG, CR2, NEF, ARW). Mesmo problema — decodificadores pesados para pouco público. Use Lightroom / darktable / RawTherapee.
  • SVG ↔ rasterização. Possível via canvas, mas vetor → raster perde escalabilidade e o inverso perde fidelidade. Uma conversa diferente.
  • Conversão em lote. Nossa interface lida com um arquivo por vez. Para uso em lote, use o endpoint REST ou uma ferramenta de desktop.

O pipeline do codificador, em código

A conversão é curta o suficiente para ser escrita. Dado um File de uma entrada de arquivo, o pipeline completo roda em cerca de seis linhas:

const bitmap = await createImageBitmap(file);
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
const ctx = canvas.getContext("2d");
ctx.drawImage(bitmap, 0, 0);
const blob = await canvas.convertToBlob({ type: "image/webp", quality: 0.85 });
// blob é a saída convertida, pronta para download

Cada etapa é nativa do navegador: createImageBitmap decodifica o formato de origem (definido no HTML Living Standard), OffscreenCanvas fornece uma superfície de desenho sem renderização, e convertToBlob invoca o codificador WebP / JPEG / PNG integrado do navegador com o parâmetro de qualidade definido na especificação (0-1 para formatos com perdas, ignorado para PNG). O mesmo codificador é o que o Chrome usa para salvar canvases via toDataURL; nós apenas roteamos o resultado para um download em vez de uma string. Não há WASM, biblioteca de terceiros ou chamada de rede — o pipeline completo roda em aproximadamente 40-200 ms para uma entrada 4K em um laptop de 2023, com o gargalo mudando entre decodificação (fontes PNG) e codificação (saídas WebP em qualidade 0,85+).

Premissas e limitações

  • Um arquivo por vez. A interface aceita um único arquivo por sessão. A recodificação em lote precisa de um script contra a API REST ou uma ferramenta de desktop.
  • Codificadores nativos do navegador.A qualidade de saída depende do navegador do usuário. O codificador WebP do Chromium é libwebp; o Firefox usa o seu próprio. Diferenças sutis de artefatos por motor existem em qualidade < 0,7.
  • Sem decodificação HEIC/HEIF/RAW. Entradas nesses formatos não podem ser abertas via createImageBitmap na maioria dos navegadores sem um shim WASM que não fornecemos.
  • Sem codificação AVIF. A leitura é suportada em navegadores modernos; a escrita requer WASM (libaom), o que empurraria o pacote além do tamanho aceitável.
  • Sem perdas ↔ com perdas é unidirecional. Recodificar um JPG para PNG não restaura informações; o PNG recodificado é bit-perfeito do JPG decodificado, com suas perdas de quantização incorporadas.
  • Perfil ICC preservado apenas para reescrita no mesmo formato. A conversão entre formatos (PNG → JPG) pode descartar o perfil ICC incorporado dependendo da implementação do navegador.
  • Limite de memória. Entradas muito grandes (40+ megapixels) podem causar OOM no Safari para dispositivos móveis.

Suporte mínimo de navegador

A codificação WebP via canvas.toBlobrequer Chromium 23+, Firefox 65+, Safari 14+, Edge 79+. Em 2026 isso cobre >97% do tráfego global. A codificação AVIF não é suportada na Canvas API do navegador; precisaríamos de um codificador WASM para disponibilizar esse destino, o que é material de roadmap.

Frequently asked questions

Como o Convertitive converte entre formatos de imagem?
O pipeline: (1) carrega o arquivo de origem em um elemento Image do navegador; (2) desenha-o em um Canvas HTML nas dimensões de destino; (3) chama canvas.toBlob(callback, mimeType, quality) com o formato e parâmetro de qualidade desejados. O codec integrado do navegador lida com a codificação real. Isso significa que o suporte a formatos depende do dispositivo: a decodificação WebP requer Chrome/Firefox/Edge (Safari 14+); AVIF requer Chrome 85+/Firefox 93+.
Qual algoritmo de compressão o codificador JPEG usa?
JPEG usa compressão com perdas de Transformada Discreta de Cosseno (DCT), conforme especificado em ISO/IEC 10918-1:1994 (linha de base JPEG). O parâmetro de qualidade do codificador do navegador mapeia para o escalonamento da tabela de quantização DCT — qualidade=1,0 usa quantização mínima (quase sem perdas), qualidade=0 usa quantização máxima (muito com perdas). As tabelas de quantização exatas são específicas de implementação conforme a especificação HTML canvas.toBlob() (WHATWG HTML §15.4.13).
A conversão de imagem é sem perdas para PNG para PNG?
PNG usa compressão sem perdas DEFLATE (RFC 2083, §2.1). Recodificar um PNG através da Canvas API re-executa o DEFLATE, que pode produzir um arquivo maior ou menor que o original, dependendo da implementação DEFLATE do navegador e das configurações de nível de compressão. Os valores de pixel são idênticos; apenas o tamanho do arquivo compactado muda. Os dados do canal alfa são preservados exatamente.
A imagem sai do meu dispositivo?
Não. Todo o processamento de imagem usa a Canvas API e a FileReader API do navegador — JavaScript puramente do lado do cliente, sem solicitações ao servidor. A guia Rede no DevTools do navegador mostra zero solicitações de saída ao converter imagens. Isso é verificável de forma independente; o código-fonte é público em github.com/convertitive.
Quais são as limitações de precisão e qualidade do conversor de imagem?
Três limitações: (1) perfil de cor: o Canvas desenha imagens no espaço de cor interno do navegador (sRGB na maioria dos dispositivos), portanto perfis ICC incorporados em imagens de origem podem ser descartados; (2) EXIF/metadados: canvas.toBlob() remove todos os metadados EXIF, IPTC e XMP — orientação, GPS, modelo da câmera são perdidos; (3) a qualidade é subjetiva — o parâmetro de qualidade mapeia de forma diferente nas implementações de codificador JPEG e WebP dos navegadores, portanto um JPEG quality=0,8 do Chrome pode diferir em tamanho e aparência de um gerado pelo Firefox na mesma configuração.

Related

Published May 14, 2026