Bhinish Dhiman

Como converter imagem para base64 (data URI), e quando não fazer isso

Traduzido do original em inglês. Ler o original

Solte o arquivo no conversor de data URI, veja o tamanho em Inlined e copie o trecho Data URI, CSS ou HTML. O base64 escreve cada 3 bytes como 4 caracteres, então o arquivo cresce um terço antes mesmo de entrar o prefixo data:. Embuta só arquivos pequenos: a ferramenta aprova até 4 096 bytes e, acima disso, recomenda uma referência normal ao arquivo, porque uma cópia embutida é baixada de novo com cada documento ou folha de estilo que a contém.

Transformar um arquivo em data URI sempre dá certo. Esse é justamente o problema: nada na conversão avisa que colar uma foto de 200 KB numa folha de estilo acabou de deixar mais lenta cada página que a carrega. A codificação leva segundos. A decisão de usar ou não é a parte que vale acertar.

Dois termos antes de tudo

Um data URI é um URI que carrega os bytes de um arquivo dentro de si, em vez de apontar para um arquivo em outro lugar. Ele é escrito como data:, o tipo MIME do arquivo, ;base64, e depois os bytes codificados, então um PNG começa com data:image/png;base64,.

Base64 é a codificação que torna dados binários seguros para entrar num texto. Ela pega o arquivo de três em três bytes, divide esses 24 bits em quatro grupos de 6 e escreve cada grupo como um caractere de um alfabeto de 64 (2⁶ = 64). Entram três bytes, saem quatro caracteres, seja qual for o conteúdo.

Convertendo o arquivo

  1. Abra o conversor de data URI e pressione “Choose a file” (escolher um arquivo), ou solte o arquivo em qualquer lugar da página. Ele aceita qualquer coisa: imagens, SVG, fontes. Código SVG colado fora de uma caixa de texto também funciona, e “Try a sample” (experimentar um exemplo) carrega um ícone pequeno.
  2. Leia os três números que aparecem: “File” (o original), “Inlined” (o data URI completo, com o prefixo) e “Overhead” (a diferença, em porcentagem).
  3. Leia a linha abaixo deles. Ela diz “Reasonable to inline.” (pode embutir) ou “Use a normal file reference instead.” (use uma referência normal ao arquivo), seguida dos motivos.
  4. Copie uma das três caixas pelo link de cópia: “Data URI” (a string pura), “CSS” (uma declaração background-image com o URI entre aspas, já que o base64 pode conter uma barra) ou “HTML” (uma tag <img> para imagens, um link de download para o resto). Você também pode escolher o trecho em “Copy as” (copiar como) e copiá-lo com o botão grande embaixo, ou baixá-lo como arquivo .txt pela barra de baixo.

O trecho HTML escreve alt="", o que diz aos leitores de tela que a imagem é decorativa. Se a imagem tem significado, troque isso por uma descrição antes de colar.

Para onde vai o terço a mais

A proporção 4:3 é fixa, então o base64 de qualquer arquivo é previsível: quatro caracteres para cada três bytes, arredondando para cima até um grupo inteiro de quatro. O número “Inlined” da ferramenta também conta o prefixo, e é por isso que o overhead aparece cerca de um ponto acima de 33% em arquivos pequenos: data:image/png;base64, sozinho tem 22 caracteres.

Arquivo Bytes Só o base64 Data URI completo Overhead exibido O que a ferramenta diz
Ícone PNG 3 072 4 096 4 118 +34% Reasonable to inline
Ícone SVG 3 072 4 096 4 122 +34% Reasonable to inline
PNG, um byte acima do limite 4 097 5 464 5 486 +34% Use a normal file reference instead
Foto JPEG 204 800 273 068 273 091 +33% Use a normal file reference instead, com três motivos

Cada linha é aritmética: 4 × ⌈3 072 ÷ 3⌉ = 4,096, e 4 096 + 22 = 4 118. O prefixo do SVG, data:image/svg+xml;base64,, tem 26 caracteres; o do JPEG, 23.

A compressão do servidor recupera parte desse terço durante a transferência, mas menos do que você esperaria, porque o base64 embaralha os padrões de bytes repetidos de que um compressor depende.

O limite de 4 096 bytes, e o que custa ultrapassá-lo

O veredito é decidido pelo tamanho do arquivo original. Até 4 096 bytes, a ferramenta aprova embutir: uma requisição a menos, nada para gerenciar em cache. Com 4 097 bytes ela passa para “Use a normal file reference instead”, e os motivos se acumulam conforme o arquivo cresce.

  • Cache, para todo arquivo acima do limite. Um arquivo externo é baixado uma vez e reaproveitado em todas as páginas. Um arquivo embutido viaja dentro do arquivo que o contém, então é baixado de novo com cada documento ou folha de estilo que o incorpora.
  • Imagens responsivas, para imagens acima do limite. Um data URI não tem uma URL sobre a qual o navegador possa negociar, então você perde o srcset, o carregamento lento (lazy loading) e qualquer otimização de imagem que uma CDN aplicaria. Uma fonte acima do limite recebe o aviso de cache, mas não este.
  • Bloqueio de renderização, acima de 32 768 bytes (8 × 4 096). Numa folha de estilo, o base64 precisa chegar antes que a página possa ser renderizada, e uma única edição de CSS sem relação nenhuma invalida a cópia em cache de todos os recursos embutidos junto.

A foto de 200 KB da tabela esbarra nos três. A própria frase da ferramenta para ela diz “At 200 KB this becomes roughly 267 KB inlined” (com 200 KB, isso vira cerca de 267 KB embutido), e esses 267 KB vão junto com a folha de estilo em toda visita em que ela ainda não estiver em cache.

Quando um data URI é a escolha certa

Pequeno, usado num só lugar e autossuficiente: um único ícone dentro de um bloco de estilo inline é o caso clássico. Deixe o arquivo o menor possível antes de codificá-lo, porque cada 3 bytes economizados tiram 4 caracteres do resultado. Um SVG pode passar antes pelo otimizador de SVG, e um PNG pelo compressor de imagens, que o regrava sem mudar um pixel.

O conversor de data URI O comando base64 Um codificador online simples
O arquivo sai do seu computador Não Não Depende do serviço
Prefixo data: e tipo MIME Escritos para você Você acrescenta Varia
Tamanho exibido com o prefixo Sim, como “Inlined” Não Varia
Recomendação sobre embutir ou não Sim, com motivos Não Raramente

Outras formas de fazer isso

Na linha de comando, a ferramenta base64 faz a codificação:

base64 -i icon.png        # macOS
base64 -w0 icon.png       # GNU/Linux

A saída é a string base64 pura. Para usá-la como data URI, coloque data:image/png;base64, na frente, com o tipo MIME correspondente ao arquivo; se o tipo estiver errado, o arquivo pode não ser exibido: os navegadores deduzem alguns tipos de imagem pelos bytes, mas um SVG precisa estar rotulado como image/svg+xml.

Conferindo que nada foi enviado

O arquivo é lido na memória do seu navegador e codificado ali, o que também significa que não há limite de tamanho além da sua própria memória. Para confirmar, abra as ferramentas de desenvolvedor do navegador na aba Network (rede) antes de soltar o arquivo: a codificação não gera nenhuma requisição.

Faça a conversão, e a decisão, no conversor de data URI. Se o veredito for não embutir, reduzir o arquivo com o compressor de imagens e servi-lo normalmente costuma ser a melhor troca.