Bhinish Dhiman· Atualizado 1 de outubro de 2026

Quanto a compressão de PDF sem perda realmente economiza, medido em onze arquivos

Traduzido do original em inglês. Ler o original

A compressão de PDF sem perda, que reorganiza os objetos do arquivo sem tocar no texto nem nas imagens, economizou 0.8% num documento de texto impresso pelo Chromium, 3.9% num arquivo do jsPDF (85.8% depois de comprimir os streams brutos com deflate), 6.5% num arquivo do Quartz do macOS e menos de 0.05% em qualquer arquivo com muitas imagens, medido em onze PDFs. O único arquivo que cresceu aumentou 7 bytes. O conteúdo de páginas excluídas sobrevivia à reorganização, então agora a ferramenta reconstrói esses arquivos.

Todo compressor de PDF oferece uma opção sem perda, e quase nenhum diz quanto ela vale. Medimos a nossa.

Dois termos, definidos

Compressão estrutural é reescrever o jeito como um PDF guarda os seus objetos (a tabela de referência cruzada, o empacotamento de objetos pequenos em streams, o filtro de compressão de cada stream) sem alterar um único glifo ou pixel. É o único tipo de compressão que pode ser chamado honestamente de sem perda.

Object stream (fluxo de objetos) é um recurso do PDF 1.5 que empacota muitos objetos pequenos (dicionários de página, descritores de fonte, anotações) num único stream comprimido, em vez de gravar cada um sem compressão. É dele que vem quase toda a economia estrutural, e é por isso que o programa que gerou o arquivo decide o resultado antes de o compressor rodar.

A medição

Geramos onze PDFs em 1º de outubro de 2026: as mesmas vinte páginas de texto impressas pelo Chromium 153 (produtor Skia/PDF m153), pelo Quartz do macOS via cupsfilter, pelo jsPDF 4.2.1 e pelo pdf-lib com e sem object streams; dez fotografias de 1600 pixels inseridas pelo Chromium e pelo pdf-lib; cinco páginas no estilo de escaneamento, cada uma um JPEG em tons de cinza de página inteira com qualidade 55; um documento de uma linha e uma página; um documento que teve cinco das suas dez páginas excluídas; e um arquivo criptografado com AES-256. Cada um passou pela compressStructural em src/lib/pdf/ops.ts (o código exato por trás da opção sem perda do nosso compressor) no Node 24, com o @cantoo/pdf-lib 2.11.1.

Arquivo Produtor Antes Depois Economia
20 páginas de texto Impressão do Chromium 82 109 B 81 426 B 0.8%
20 páginas de texto Quartz do macOS 48 441 B 45 278 B 6.5%
20 páginas de texto jsPDF 4.2.1 72 814 B 69 977 B 3.9%
20 páginas de texto pdf-lib, sem object streams 34 041 B 33 168 B 2.6%
20 páginas de texto pdf-lib, com object streams 33 166 B 33 173 B −0.02%
10 fotografias Impressão do Chromium 1 528 699 B 1 528 112 B 0.04%
10 fotografias pdf-lib 1 509 614 B 1 508 973 B 0.04%
5 páginas escaneadas pdf-lib 1 816 323 B 1 815 924 B 0.02%
1 linha, 1 página pdf-lib 1 307 B 1 059 B 19.0%
10 páginas, 5 excluídas pdf-lib 13 900 B 13 441 B 3.3%
Criptografado pdf-lib 2 940 B recusado —

Lendo a tabela

Nenhum dos quatro produtores gravou object streams, e os quatro gravaram uma tabela de referência cruzada clássica. A passada faz a mesma coisa com cada um: substitui a tabela por um stream de referência cruzada e empacota os objetos pequenos (dicionários de página, descritores de fonte, listas de recursos) em object streams. Então a economia é limitada pelos bytes que já estavam fora de streams desde o início. No arquivo do Chromium, eram 8 374 de 82 109 bytes, reduzidos a 6 896; no do Quartz, 8 234 de 48,441, reduzidos a 4 224. O Quartz economiza mais porque gravou 71 objetos para vinte páginas, contra 52 do Chromium, com a tabela mais prolixa das quatro. O arquivo do pdf-lib que já tinha object streams voltou 7 bytes maior: esse é todo o caso de “o seu arquivo pode ficar maior” nesta amostra, e é a diferença entre dois empacotamentos igualmente bons dos mesmos objetos.

O arquivo do jsPDF mostra com mais clareza o limite do método. O jsPDF 4.2.1 grava os streams de conteúdo sem compressão por padrão: 65 255 dos 72 814 bytes do arquivo são instruções de desenho brutas, e o zlib as reduz a 19 053. São 63.5% sem perda parados no arquivo. A passada estrutural não recodificava um stream existente, então encontrou 3.9% e deixou os 65 255 bytes brutos no lugar. Uma passada que comprimisse os streams brutos com deflate seria igualmente sem perda (o Flate devolve exatamente os mesmos bytes na decodificação) e, nesse produtor, faria dezesseis vezes mais diferença do que o reempacotamento.

Por isso a opção sem perda agora faz isso. Todo stream gravado sem filtro é comprimido com deflate e mantido só se o resultado for menor; streams que já têm filtro, como imagens JPEG, ficam intocados, assim como os metadados XMP, que a especificação pede que continuem legíveis por ferramentas que não interpretam PDF. Medido de novo num documento comparável de vinte páginas do jsPDF: 132 980 bytes viraram 18,855, uma economia de 85.8%, com o texto de todas as páginas ainda extraível do resultado.

Em qualquer arquivo com muitas imagens, a economia é um erro de arredondamento, porque os bytes estão nos streams de imagem e uma passada estrutural não os abre. Dez fotografias somando 1.5 MB devolveram 587 bytes. Cinco escaneamentos somando 1.8 MB devolveram 399 bytes. Os 19% do documento de uma linha são as mesmas poucas centenas de bytes de sobrecarga da tabela, num arquivo tão pequeno que essa sobrecarga é a maior parte dele.

As páginas excluídas ainda estavam lá

O documento editado é a descoberta que mudou a forma como descrevemos essa opção. Montamos dez páginas, cada uma com uma marca única no texto, excluímos cinco e salvamos. O arquivo salvo tinha 13 900 bytes e ainda guardava os streams de conteúdo das dez páginas: as páginas excluídas ficam sem referência, mas o pdf-lib grava todos os objetos que analisou. A passada estrutural reempacotou esse arquivo para 13 441 bytes com as dez marcas ainda dentro, e a contagem de objetos foi de 19 para 21.

Copiar as cinco páginas vivas para um documento novo, em vez disso, produziu 7 518 bytes (46% menor que o resultado “comprimido”), só com as marcas de 0 a 4. Reempacotar preserva os órfãos; reconstruir os descarta.

Isso importa para o tamanho, e importa mais para a privacidade: uma página que você excluiu antes de enviar ainda podia ser extraída de um arquivo que tinha passado pelo nosso compressor sem perda. Pior: a própria descrição da opção dizia que ela “drops unreferenced ones” (descarta os que não têm referência). Não descartava.

O que mudamos

A opção sem perda agora copia as páginas vivas para um arquivo novo sempre que é seguro fazer isso, e mantém o resultado só se ele for menor. Nem sempre é seguro: campos de formulário interativos e a árvore de marcadores (bookmarks) pertencem ao documento, não a uma página, então uma reconstrução os apagaria sem avisar. Um arquivo que tenha qualquer um dos dois é apenas reempacotado, e o resultado diz isso, em vez de dar a entender que os órfãos sumiram.

Medido de novo depois da mudança num arquivo comparável de dez páginas com cinco removidas: um reempacotamento simples deu 12 578 bytes com as dez marcas dentro; a nova passada deu 9 211 bytes só com as marcas de 0 a 4, 27% menor, e as páginas excluídas realmente eliminadas. Um teste no repositório agora monta exatamente esse arquivo e falha se o conteúdo de uma página excluída sobreviver à passada.

Em comparação com o método destrutivo

As outras duas opções da nossa ferramenta renderizam cada página como JPEG a 150 ou 110 dpi e a reinserem. Isso encolhe escaneamentos por um fator grande e transforma um documento de texto em imagens de texto, sem seleção, sem busca e sem nada para um leitor de tela. Os serviços genéricos conseguem uma grande economia sem esse custo rodando o Ghostscript num servidor para reduzir a resolução das imagens sem mexer na camada de texto; o Ghostscript é AGPL-3.0, e levá-lo para o navegador colocaria o site inteiro sob essa licença.

Então a oferta honesta é o que a tabela mostra: uma passada estrutural que vai encontrar alguns pontos percentuais num arquivo de um produtor mais antigo e nada num moderno, ou uma passada que rasteriza e custa a camada de texto. Se o documento tem campos de formulário ou marcadores e você quer que o conteúdo excluído desapareça, a passada sem perda não vai fazer isso por você, e agora ela avisa: extraia as páginas que vai manter para um arquivo novo, que é o que o Split PDF faz.