
Por que JPEGs pequenos aparecem diferentes no Chrome
Um ícone que parecia diferente no Chrome
Guillaume Técher percebeu que um logo em JPEG renderizado a 15px parecia mais “grosso” no Chrome do que no Firefox do colega, embora a imagem original fosse a mesma. Trocar por SVG resolvia visualmente, mas a dúvida sobre a causa permaneceu. A resposta não era um bug de renderização, e sim uma otimização específica do Chrome ao decodificar JPEGs em tamanhos pequenos.
Por que decodificar a imagem inteira pode ser desperdício
O caminho intuitivo seria descomprimir o JPEG completo em memória e só então reduzir a imagem. Para algo como uma imagem de 2000 × 2000 exibida a 20 × 20, isso é muito ineficiente: o bitmap completo ocupa cerca de 12 MB, enquanto o resultado final precisa de apenas ~1,2 KB. Além disso, ao reduzir drasticamente uma imagem, perde-se principalmente informação de alta frequência - detalhes finos como texturas e bordas muito pequenas - e não dados aleatórios.
Como o JPEG armazena a imagem
O JPEG divide a imagem em blocos de 8 × 8 e aplica a eles a DCT (Transformada Discreta de Cosseno), convertendo cada bloco para o domínio da frequência. A frequência mais baixa corresponde a uma cor uniforme; a mais alta parece um tabuleiro de xadrez. Os coeficientes indicam quanto de cada padrão está presente em cada bloco.
A otimização: partial IDCT scaling
Quando a imagem precisa ser reduzida por um fator de 8, cada bloco 8 × 8 pode corresponder a um único pixel na versão final. Nesse caso, dá para ignorar coeficientes de alta frequência e usar apenas os de baixa frequência, gerando uma versão reduzida sem descomprimir o JPEG inteiro. Isso economiza memória e acelera a decodificação. A técnica funciona para frações com denominador 8 e se chama “partial IDCT scaling” (escalonamento parcial da transformada inversa de cosseno). Uma correção adicionada depois observa que o algoritmo de redimensionamento posterior também influencia o resultado visual.
O papel do Chrome e a lição prática
O Chrome delega decodificação de imagens ao Skia, que usa libjpeg-turbo para JPEG. Essa biblioteca implementa partial IDCT scaling: o Chrome escolhe a fração mais próxima com denominador 8, decodifica já nessa escala menor e depois faz um downsampling tradicional até o tamanho desejado. No caso do ícone a 15px, a imagem foi decodificada em 1/8, preservando basicamente o componente constante e descartando suavizações de borda e gradientes, o que explicava a aparência mais espessa.
A conclusão prática do autor é direta: JPEG e suas otimizações foram pensados para fotografias, não para ícones ou elementos de interface. Para esses casos, formatos como SVG tendem a evitar esse tipo de artefato.