Acabei de encontrar o seguinte: Coloquei várias cópias idênticas de uma imagem png em uma pasta e tentei compactar essa pasta com os seguintes métodos:
tar czf folder.tar.gz folder/
tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
(este funciona bem para imagens idênticas, no entanto, para imagens semelhantes, o ganho é zero)zip -r folder.zip folder/
Quando eu chequei o tamanho do .tar.gz
, .tar.xz
, .zip
percebi que é quase o mesmo que o de folder/
.
Entendo que uma imagem png em si pode ter um alto nível de compactação e, portanto, não pode ser mais compactada. No entanto, ao mesclar muitas imagens png semelhantes (neste caso até idênticas) a um arquivo e depois compactá-lo, esperaria que o tamanho necessário diminuísse acentuadamente. No caso de imagens idênticas, eu esperaria um tamanho aproximadamente do tamanho de uma única imagem.
data-compression
um convidado
fonte
fonte
.bmp
), o arquivo tar.gz deve poder tirar proveito da similaridade. (Pelo menos se a semelhança é um monte de pixels sendo idêntico)Respostas:
Veja como os algoritmos de compactação funcionam. Pelo menos aqueles na família Lempel-Ziv (
gzip
usa LZ77 ,zip
aparentemente tambémxz
usa e usa LZMA ) comprimem um pouco localmente : semelhanças que estão distantes umas das outras não podem ser identificadas.Os detalhes diferem entre os métodos, mas o ponto principal é que, quando o algoritmo atinge a segunda imagem, ele já "esqueceu" o início da primeira. E assim por diante.
Você pode tentar alterar manualmente os parâmetros do método de compactação; se tamanho da janela (LZ77) resp. Se o tamanho do bloco / bloco (métodos posteriores) for pelo menos tão grande quanto duas imagens, você provavelmente verá uma maior compressão.
Observe que o acima descrito realmente se aplica apenas se você tiver imagens idênticas ou imagens descompactadas quase idênticas . Se houver diferenças, as imagens compactadas podem não se parecer com nada na memória. Não sei como funciona a compactação PNG; convém verificar manualmente as representações hexadecimais das imagens que você possui para substrings compartilhados.
Observe também que, mesmo com parâmetros alterados e redundância a serem explorados, você não terá o tamanho de uma imagem. Dicionários maiores significam um tamanho maior de palavra-código e, mesmo que duas imagens sejam exatamente idênticas, você pode codificar a segunda usando várias palavras-código (que apontam para a primeira).
fonte
Por que isso acontece? Na verdade, existem dois efeitos diferentes acontecendo aqui:
Cada arquivo compactado independentemente. Alguns programas de arquivamento - incluindo zip - compactam cada arquivo independentemente, sem memória de um arquivo para outro. Em outras palavras, cada arquivo é compactado separadamente, e os arquivos compactados são concatenados em um arquivo morto.
Memória de curto prazo. Alguns programas de arquivamento podem usar informações sobre um arquivo para ajudar a compactar melhor o próximo arquivo. Eles efetivamente concatenam os arquivos e compactam o resultado. Isto é uma melhoria.
Veja também a resposta de Nayuki para mais discussão sobre isso.
No entanto, há um segundo problema. Alguns esquemas de compactação - incluindo zip, gzip e bzip2 - têm uma memória limitada. Eles compactam os dados rapidamente e lembram os 32KB anteriores, mas não lembram nada dos dados que ocorreram muito antes no arquivo. Em outras palavras, eles não poderão encontrar dados duplicados se as duplicatas ocorrerem a mais de 32 KB de distância. Como resultado, se os arquivos idênticos forem curtos (menores que cerca de 32 KB), o algoritmo de compactação poderá remover os dados duplicados, mas se os arquivos idênticos forem longos, o algoritmo de compactação será processado e se tornará inútil: não poderá detectar nenhum dos a duplicata em seus dados. (O Bzip lembra os últimos 900 KB ou mais de dados, em vez de 32 KB.)
Todos os algoritmos de compactação padrão têm algum tamanho máximo de memória, além do qual eles não conseguem detectar padrões ... mas, para alguns, esse número é muito maior que outros. Para o Bzip, é algo como 900 KB. Para xz, é algo como 8 MB (com configurações padrão). Para 7z, é algo como 2 GB. 2 GB é maior que o suficiente para reconhecer as cópias duplicadas de arquivos PNG (que geralmente são muito menores que 2 GB). Além disso, o 7z também tenta ser esperto ao colocar arquivos que provavelmente são semelhantes um ao outro no arquivo morto, para ajudar o compressor a funcionar melhor; tar não sabe nada sobre isso.
Ver também a resposta de Raphael e resposta de Nayuki para mais explicações deste efeito.
Como isso se aplica à sua configuração. Para seu exemplo específico, você está trabalhando com imagens PNG. As próprias imagens PNG são compactadas, para que você possa pensar em cada arquivo PNG como basicamente uma sequência de bytes de aparência aleatória, sem padrões ou duplicação no arquivo. Não há nada para um compressor explorar, se ele olhar para uma única imagem PNG. Portanto, se você tentar compactar um único arquivo PNG (ou criar um arquivo zip / tar / ... contendo apenas um único arquivo PNG), não terá compactação.
Agora, vejamos o que acontece se você tentar armazenar várias cópias do mesmo arquivo PNG:
Arquivos pequenos. Se o arquivo PNG for muito pequeno, tudo, exceto o zip, funcionará muito bem. O zip falhará de maneira espetacular: ele comprime cada arquivo de forma independente, portanto não tem chance de detectar a redundância / duplicação entre os arquivos. Além disso, ao tentar compactar cada arquivo PNG, ele não obtém compactação; o tamanho de um arquivo zip será enorme. Por outro lado, o tamanho de um arquivo tar (compactado com gzip, bzip2 ou xz) e um arquivo 7z será pequeno, pois basicamente armazena uma cópia do arquivo e percebe que os outros são idênticos - eles se beneficiam de reter memória de um arquivo para outro.
Arquivos grandes. Se o arquivo PNG for grande, apenas 7z funcionará bem. Em particular, o zip continua a falhar espetacularmente. Além disso, tar.zip e tar.bzip2 falham muito, pois o tamanho do arquivo é maior que a janela de memória do compressor: como o compressor vê a primeira cópia do arquivo, ele não pode encolher (uma vez que já foi compactado ); no momento em que começa a ver o início da segunda cópia do arquivo, ele já esqueceu as sequências de bytes vistas no início do primeiro arquivo e não consegue estabelecer a conexão de que esses dados são realmente duplicados.
Por outro lado, tar.xz e 7z continuam se saindo bem com várias cópias de um arquivo PNG grande. Eles não têm a limitação de "tamanho pequeno da memória" e podem perceber que a segunda cópia do arquivo é idêntica à primeira cópia, portanto, não há necessidade de armazená-lo novamente.
O que você pode fazer sobre isso. Use 7z. Ele possui várias heurísticas que ajudarão a detectar arquivos idênticos ou semelhantes e a compactar muito bem nesse caso. Você também pode ver o lrzip com a compactação lzop.
Como eu sei? Consegui verificar isso tentando algumas experiências com 100 cópias de um arquivo contendo bytes aleatórios. Tentei 100 cópias de um arquivo 4KB, 100 cópias de um arquivo de 1 MB e 100 cópias de um arquivo de 16 MB. Aqui está o que eu encontrei:
Como você pode ver, o zip é horrível, por menor que seja o seu arquivo. 7z e xz são bons se suas imagens não forem muito grandes (mas xz será frágil e depende da ordem em que as imagens são colocadas no arquivo morto, se você tiver algumas duplicatas e outras não duplicadas misturadas). 7z é muito bom, mesmo para arquivos grandes.
Referências. Isso também é explicado bem em várias postagens no Super Usuário. Dê uma olhada:
fonte
tar
eles e depois comprimei comxz
(que funcionou muito bem para imagens idênticas), no entanto, no caso de imagens semelhantes, o ganho é zero. Tentei com 71 imagens, cada uma com um tamanho de ~ 831 KB.Em primeiro lugar, observe que o formato da imagem PNG é basicamente pixels RGB brutos (com alguma filtragem de luz) enviados pelo formato de compactação DEFLATE. De um modo geral, os arquivos compactados (PNG, JPEG, MP3, etc.) não terão nenhum benefício em serem compactados novamente. Portanto, para fins práticos, podemos tratar seu arquivo PNG como dados aleatórios incompressíveis para o restante do experimento.
Segundo, observe que os formatos ZIP e gzip também usam o codec DEFLATE. (Isso explicaria por que zipar ou compactar um único arquivo produzirá essencialmente o mesmo tamanho de saída.)
Agora permita-me comentar cada caso de teste individualmente:
tar czf folder.tar.gz folder/
Isso cria um arquivo TAR (não compactado) que concatena todos os seus arquivos PNG idênticos (com uma pequena quantidade de metadados e preenchimento adicionados). Em seguida, esse arquivo único é enviado através do compressor gzip para criar um arquivo de saída compactado.
Infelizmente, o formato DEFLATE suporta apenas uma janela de dicionário LZ77 de 32768 bytes. Portanto, mesmo que o TAR contenha dados repetitivos, se seu arquivo PNG for maior que 32 KiB, o compressor DEFLATE não poderá se lembrar dos dados o suficiente para aproveitar o fato de que dados idênticos são recorrentes.
Por outro lado, se você tentar novamente essa experiência com, por exemplo, um arquivo PNG de 20 KB duplicado 10 vezes, é muito provável que você obtenha um arquivo gzip apenas um pouco maior que 20 KB.
tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
Isso cria um arquivo TAR como antes e depois usa o formato xz e o compressor LZMA / LZMA2. Não consegui encontrar informações sobre o LZMA nessa situação, mas no 7-Zip for Windows eu sei que ele pode suportar grandes tamanhos de janelas de dicionário (por exemplo, 64 MiB). Portanto, é possível que você estivesse usando configurações abaixo do ideal e que o codec LZMA pudesse reduzir o arquivo TAR para apenas o tamanho de um arquivo PNG.
zip -r folder.zip folder/
O formato ZIP não suporta arquivos "sólidos"; isto é, todo arquivo é compactado independentemente. Assumimos que todo arquivo é incompressível. Portanto, o fato de que cada arquivo é idêntico não pode ser explorado, e o arquivo ZIP será tão grande quanto a concatenação direta de todos os arquivos.
fonte
xz
por padrão, é executado noxz -6
modo, que usa um dicionário de 8 MiB LZMA2 . Não consegui encontrar imediatamente na página de manual disponível no meu sistema Debian qual é o tamanho da janela padrão para o compressor.tar czf folder.tar.gz folder/ && xz --stdout folder.tar.gz > folder.tar.gz.xz
sem nenhum efeito (o que faz sentido de acordo com o que você explicou). Acho que me perdi um pouco em todo esse material de compactação: D Ao usartar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz
, na verdade, acabo com um pouco mais do que o tamanho de uma imagem (o que também faz sentido de acordo com o tamanho da janela dict padrão de 64 MiB). Eu atualizei minha pergunta de acordo. Obrigado!tar -> gzip -> xz
, o gzip DEFLATE pode compactar cada cópia dos dados PNG de uma maneira diferente, para que o xz não consiga detectar as redundâncias.O problema é que (a maioria) dos esquemas de compactação não têm conhecimento sobre os dados que você possui. Mesmo se você descompactar seus PNGs em bitmaps e compactá-los no tarball, não obterá resultados (significativamente) menores.
No caso de muitas imagens semelhantes, um esquema de compactação apropriado seria um codec de vídeo.
Usando a codificação sem perdas, você deve obter quase o resultado de compactação perfeito esperado.
Se você quiser testá-lo, use algo como isto:
https://trac.ffmpeg.org/wiki/Create%20a%20video%20slideshow%20from%20images
fonte
PNG é a combinação de Filters + LZ77 + Huffman (a combinação de LZ77 + Huffman é chamada Deflate) nessa ordem:
etapa 1) se o filtro for diferente de Nenhum, o valor dos pixels será substituído pela diferença dos pixels adjacentes (para obter mais detalhes, consulte http://www.libpng.org/pub/png/book/chapter09.html ) . Isso aumenta a compactação das imagens com gradientes (então ... 4 5 6 7 fica ... 1 1 1 1) e pode ajudar em áreas da mesma cor (... 3 3 3 5 5 5 5 5 5 fica 0 0 0 2 0 0 0 0 0). Por padrão, os filtros são ativados em imagens de 24 bits e desativados em imagens de 8 bits com uma paleta.
etapa 2) os dados são compactados com o LZ77, que substitui seqüências repetidas (correspondências) de bytes por uma tupla que contém a distância da correspondência e a duração da correspondência.
passo 3) o resultado do passo 2 é codificado com o código Huffman que substitui símbolos de comprimento fixo por códigos de comprimento variável, quanto mais frequente o símbolo, menor o código.
Existem vários problemas:
Uma pequena alteração que afeta poucos pixels resultará em alterações nos resultados das 3 etapas da compactação png:
1) O valor filtrado dos pixels adjacentes será alterado (dependendo do filtro usado). Isso amplificará os efeitos de pequenas mudanças.
2) A alteração significa que as correspondências nessa área serão diferentes. Por exemplo, alterar 333333 para 333533 faz com que outra ocorrência de 333333 não corresponda mais, por isso seleciona outra correspondência para 333333 com uma distância diferente ou seleciona a mesma correspondência, mas com um comprimento menor e, em seguida, outra correspondência nos últimos 3 bytes. Por si só, isso mudará muito os resultados.
3) O maior problema está na etapa 3. O código huffman usa um número variável de bits, portanto, mesmo uma pequena alteração resultará em que tudo o que se segue não está mais alinhado. AFAIK A maioria dos algoritmos de compactação não pode detectar correspondências que não estejam alinhadas por bytes, de modo a impedir (ou pelo menos reduzir muito) a compactação nos dados já compactados que seguem a alteração, a menos que o compressor possa detectar correspondências que não estão alinhadas por bytes.
Os outros problemas já estão cobertos por outras respostas:
4) O Gzip usa o mesmo algoritmo Deflate com um dicionário de 32 KB, portanto, se os arquivos png forem maiores que 32 KB, as correspondências não serão detectadas, mesmo que sejam idênticas. O Bzip2 é melhor nesse aspecto, pois usa um bloco de 900 KB. O XZ usa o LZMA, cujo IIRC possui um dicionário de 4 MB no nível de compactação padrão. 5) O formato Zip não usa compactação sólida, portanto, não comprime arquivos semelhantes ou idênticos.
Talvez os compressores da família PAQ ou PPMD sejam compactados melhor, mas se você precisar compactar muitos arquivos de imagem semelhantes, poderá considerar três abordagens:
1) Armazene as imagens não compactadas (com PNG -0 ou em um formato sem compactação) e comprima com um compressor com um dicionário grande ou tamanho de bloco. (LZMA funcionará bem)
2) Outra opção seria manter os filtros, mas remover a compactação Deflate dos PNGs. Isso pode ser feito, por exemplo, com o utilitário ( AdvDef ). Em seguida, você comprime os PNGs descompactados resultantes. Após a descompactação, você pode manter o PNG não compactado ou compactá-lo novamente com AdvDef (mas isso levará tempo).
Você precisa testar as duas abordagens para ver qual comprime mais.
3) A última opção seria converter as imagens png em um vídeo, compactá-las com um compressor de vídeo sem perdas como x264 sem perdas (tomando cuidado especial com o uso do formato de cor certo) e, em seguida, extrair os quadros para imagens png individuais. Isso pode ser feito com o ffmpeg. Você também precisaria manter o mapeamento entre o número do quadro e o nome original.
Essa seria a abordagem mais complexa, mas se os pngs fizerem parte de uma animação, poderá ser a mais eficaz. No entanto, você precisará de um formato de vídeo que suporte transparência, se necessário.
Edit: Também existe o formato MNG, caso não seja usado com frequência.
fonte
Quando você tem conjuntos de dados especiais, usa algoritmos especiais, não ferramentas de uso múltiplo.
A resposta é que as compressões sem perdas escolhidas não são feitas para o que você faz. Ninguém espera que você comprima a mesma imagem duas vezes, e mesmo se você fizer isso (por acidente) com todas as entradas anteriores, seu algoritmo seria O (n ^ 2) (talvez um pouco melhor, mas a abordagem ingênua pelo menos seria n ^ 2)
A maioria dos programas de compressão testados em O (n) enfatizam a velocidade sobre a taxa de compressão ideal. Ninguém quer rodar seu computador por 5 horas apenas para poupar alguns mb, principalmente nos dias de hoje. Para entradas maiores, qualquer coisa acima de O (n) se torna um problema de tempo de execução.
Outra questão é ram. Você não pode acessar todas as partes de sua entrada a qualquer momento, quando ela for grande o suficiente. Mesmo desconsiderando isso, a maioria das pessoas não quer desistir de toda a memória RAM ou CPU apenas para comprimir alguma coisa.
Se você possui padrões em seus arquivos que deseja compactar, precisará executar operações manuais neles, escrever sua própria compactação ou potencialmente usar um "archive" -type-compression (nano). Uma compactação para armazenamento a longo prazo, muito lenta para o uso diário.
Outra opção potencialmente seria uma compactação de vídeo sem perdas.
fonte
O formato de arquivo PNG já usa o algoritmo de compactação DEFLATE internamente. Esse é o mesmo algoritmo usado pelo xz, gzip e zip - apenas em algumas variações.
tar.gz
etar.xz
aproveite a semelhança entre arquivos, o quezip
não acontece.Portanto, na verdade, você executa a compactação DEFLATE sobre os arquivos compactados DEFLATE - é por isso que os arquivos mantêm quase o tamanho original.
O
bzip2
programa (também um algoritmo relacionado) é melhor quando se trata de arquivos (quase) idênticos.fonte
bzip2
pega:tar -cjf archive.tar.bz2 *.png
. Atualizado na minha resposta.