Códigos QR com dithering: como uma fotografia vira um código legível
A maioria dos códigos QR "artísticos" é uma imagem com um código carimbado por cima. Um código QR com dithering é outra coisa: há uma única imagem, e o código faz parte do grão dela. Este artigo explica do que um código realmente precisa, como funciona o dithering por difusão de erro, a única mudança que permite aos dois dividir um quadrado, as duas configurações que decidem o resultado, e as três formas como ele falha.
Comece pelo que um código QR realmente precisa
Um código QR é uma grade de módulos — pequenos quadrados que são escuros ou claros. Alguns são estruturais e não podem se mover: os três quadrados grandes nos cantos que permitem a um leitor encontrar e orientar o código, a linha fina alternada entre eles, os pequenos quadrados de alinhamento, e as faixas que codificam formato e versão. Todo o resto é dado mais bytes de correção de erro. Essa correção de erro é a brecha. No nível mais alto, cerca de 30% do código pode ser destruído e um leitor ainda vai recuperar o conteúdo. Então um código não precisa ser perfeito. Precisa ser perfeito onde importa, e próximo o suficiente em todo o resto. Guarde essa distinção, porque toda a técnica se apoia nela: os módulos estruturais são tratados como intocáveis, e a área de dados é tratada como algo que só precisa estar certo na média, na escala em que uma câmera a vê. Todo gerador que coloca uma imagem em um código está gastando parte desse orçamento de 30%; a questão é só com que cuidado ele o gasta, e se o olho consegue ver o custo.
Dithering, em um parágrafo
O dithering Floyd–Steinberg transforma uma fotografia em tons de cinza em preto e branco puros. Você percorre os pixels em ordem. Para cada um, escolhe o mais próximo entre preto e branco, depois pega o erro que acabou de cometer — a diferença entre o cinza que queria e o valor que colocou — e o empurra para os vizinhos que ainda não visitou, ponderado 7/16 para o pixel à direita e 3/16, 5/16 e 1/16 para os três pixels abaixo. Cada um desses vizinhos então parte de um valor ligeiramente ajustado quando chega a sua vez, de modo que o erro nunca se perde, só se move. A imagem sai como um campo de pontilhado cuja densidade local corresponde ao brilho original: uma região de cinza médio vira aproximadamente metade de pontos pretos, um realce vira pontos esparsos sobre branco, uma sombra vira pontos brancos esparsos sobre preto. Vista de longe, o olho faz a média do pontilhado de volta em tom, e é por isso que uma imagem com dithering é lida como uma fotografia mesmo que cada pixel nela seja uma de apenas duas cores. Essa média é a mesma coisa que uma câmera faz quando olha para uma impressão pequena, e é o que a técnica explora.
O truque
Renderize o código com um número fixo de pixels por módulo — o SWAPQR usa nove, então cada módulo é um bloco 9×9. Depois aplique o dithering à fotografia em todo o quadrado, com uma mudança: onde o código exige um valor específico, não aplique o limiar. Force o pixel para o que o código precisa, meça o erro que essa forçagem causou, e difunda-o exatamente como faria com qualquer outro erro. Essa última frase é a ideia inteira. Os pontos forçados não são pintados por cima da imagem; eles são pagos pelos pixels ao redor, que se deslocam para compensar. Eles caem dentro da mesma textura de sal e pimenta que tudo o mais, então o olho não tem como separá-los. Os módulos estruturais — localizadores, temporização, alinhamento, formato — são desenhados sólidos e intocados, porque um leitor precisa encontrar o código antes que a correção de erro possa ajudá-lo. A técnica descrita aqui segue a abordagem publicada por Andrew T., que documentou a geração de QR com dithering em 2026; a implementação do SWAPQR foi escrita a partir da descrição, e não portada do código-fonte dele.
Dois botões que decidem tudo
O primeiro é quanto de cada módulo é forçado. Force só o pixel central e a imagem fica quase intocada, mas o código é frágil: um pixel por módulo precisa sobreviver a cada etapa de reamostragem entre a impressora e o sensor da câmera. Force um bloco 7×7 dos 9×9 e o código é robusto e a imagem é tênue, porque a maior parte de cada módulo agora é sólida. O SWAPQR expõe isso diretamente como um balanço Foto ↔ Código, com posições Foto, Meio e Código, para que a troca seja uma escolha que você faz em vez de uma constante escondida no gerador. O segundo é o quanto cada módulo é empurrado. Antes do dithering, cada pixel de um módulo escuro é escurecido um pouco e cada pixel de um módulo claro é clareado um pouco. A imagem mantém seus detalhes, mas o tom médio do módulo pende para o lado certo — que é o que uma câmera vê quando olha para um código impresso pequeno do outro lado de uma sala. Juntas, as duas configurações decidem se o resultado é uma fotografia com um código tênue dentro ou um código com uma fotografia tênue dentro, e onde nessa linha uma dada impressão deve ficar depende de como ela será lida.
Onde ele quebra, e se vale a pena
Três modos de falha, todos reais, nenhum misterioso. Uma fotografia chapada: uma imagem iluminada uniformemente e de tom único vira, com o dithering, um tabuleiro de xadrez regular, que é exatamente a textura que compete com o código, então as imagens precisam de uma faixa genuína do claro ao escuro e o estúdio avisa quando uma não tem. Um link longo: mais caracteres significam mais módulos no mesmo quadrado, então cada módulo recebe menos imagem; depois de mais ou menos a versão 8 — 49×49 módulos — a fotografia não tem onde viver, e um link curto de redirecionamento é a solução. E o close extremo em alguns leitores, que é contraintuitivo o bastante para ter um artigo próprio neste guia. Um código artístico é sempre uma troca contra a confiabilidade. Ele merece seu lugar onde o código faz parte do design e alguém vai escaneá-lo deliberadamente — um cartaz, uma capa de disco, uma embalagem, um cartão de visita. Ele não pertence a uma placa de saída de emergência. Seja qual for o contexto, teste a peça impressa com um celular de verdade antes de encomendar mil delas; o estúdio diz a mesma coisa ao lado do botão de exportar, e está falando sério.
| Parte do código | Tratamento em um código com dithering | Por quê |
|---|---|---|
| Padrões localizadores (três quadrados nos cantos) | Desenhados sólidos, nunca com dithering | O leitor precisa localizar e orientar o código antes de qualquer outra coisa |
| Linha de temporização, quadrados de alinhamento, faixas de formato e versão | Desenhados sólidos, nunca com dithering | Estruturais; a correção de erro não consegue reparar um código que não é encontrado |
| Módulos de dados e de correção de erro | Um bloco central de cada módulo forçado, o resto carrega a foto | O tom médio do módulo é o que uma câmera vê à distância de leitura |
| Pixels ao redor de um bloco forçado | Deslocados pela difusão de erro para compensar | Mantém a média local correta para que os pontos forçados se escondam no pontilhado |
| Zona de silêncio | Clara, intocada | Os leitores usam a margem vazia para encontrar a borda do código |
Perguntas frequentes
A foto é simplesmente colocada atrás do código?
Não. O código e a foto são produzidos em uma única passagem: a imagem recebe o dithering, e onde o código precisa de um valor o pixel é forçado e o seu erro é difundido para os vizinhos. Há uma única imagem, não uma camada sobre outra.
Por que nove pixels por módulo?
Isso dá a cada módulo um bloco 9×9, grande o bastante para conter um núcleo forçado de tamanho variável e ainda deixar pixels para a imagem. A configuração de balanço decide quanto desse bloco é forçado.
Ele é lido por celulares comuns?
Sim, para os conteúdos e imagens para os quais foi projetado, e cada build é verificada contra dois decodificadores independentes em sete distâncias de câmera simuladas. Ainda é uma troca contra a confiabilidade, então imprima um e teste com o seu próprio celular.
Por que um link longo estraga a imagem?
Texto mais longo significa uma versão mais alta, portanto mais módulos e menores no mesmo quadrado. Cada módulo tem menos espaço para pixels de foto, e depois de aproximadamente 49×49 módulos a imagem desaparece. Use um link curto de redirecionamento.
Imprima o quadrado uma vez. Decida depois para onde ele leva. O SWAPQR cria códigos QR estáticos de graça, com todas as opções de estilo, sem conta e sem marca d'água. Um plano pago torna um código dinâmico: o quadrado impresso continua o mesmo enquanto você muda o destino dele, e você vê quantas vezes ele foi escaneado, por dia e por dispositivo.
Criar um código QR no navegador