Sim, o bom e velho GIF. Amado por sua versatilidade, odiado por suas patentes e parcialmente obsoleto devido às suas limitações (e patentes), o GIF consiste, no centro, de uma paleta de cores e uma imagem indexada por paleta compactada usando o algoritmo LZW.
Sua tarefa é gravar um programa que leia uma imagem no formato ASCII PPM (número mágico "P3") da entrada padrão e grave a mesma imagem (pixel a pixel idêntico) no formato GIF na saída padrão. A saída pode estar no formato binário ou em texto ASCII com cada byte representado por um número entre 0 e 255 (inclusive), separados por espaços em branco.
A imagem de entrada é garantida para não ter mais de 256 cores diferentes.
Pontuação:
Seu programa será testado em 3 imagens de amostra e sua pontuação será calculada da seguinte forma:
tamanho do programa + soma (tamanho da saída - tamanho de referência para cada imagem de amostra) A
pontuação mais baixa vence.
Requisitos:
- Seu programa deve funcionar com qualquer tipo de imagem semelhante de vários tamanhos e não deve se limitar às imagens de amostra. Você pode, por exemplo, restringir as dimensões a múltiplos de 2 ou assumir que a cor máxima em ppm é 255, mas ainda deve funcionar com uma grande variedade de imagens de entrada.
- A saída deve ser um arquivo GIF válido que possa ser carregado com qualquer programa compatível (depois de converter novamente em binário se estiver usando a opção de saída ASCII).
- Você não pode usar nenhuma função de processamento de imagem (embutida ou de terceiros); seu programa deve conter todo o código relevante.
- Seu programa deve ser executável no Linux usando software disponível gratuitamente.
- O código fonte deve usar apenas caracteres ASCII.
Imagens de exemplo:
Aqui estão as três imagens de amostra que serão usadas para a pontuação. Você pode baixar um arquivo zip com os arquivos ppm (use o botão de download na parte superior da página). Ou você pode convertê-los a partir das imagens png abaixo, usando o ImageMagick com o seguinte comando:
convert file.png -compress none file.ppm
Também estou fornecendo as somas de verificação MD5 dos arquivos ppm para confirmação.
1. âmbar
Tamanho de referência: 38055
Soma de verificação MD5 do ppm: d1ad863cb556869332074717eb278080
2. olhos azuis
Tamanho de referência: 28638
soma de verificação MD5 do ppm: e9ad410057a5f6c25a22a534259dcf3a
3. pimentas
Tamanho de referência: 53586
Soma de verificação MD5 do ppm: 74112dbdbb8b7de5216f9e24c2e1a627
fonte
Respostas:
Perl, 515 + -2922 + 0 + -2571 = -4978
Outra abordagem. Desta vez, estou tentando salvar a imagem em blocos de tamanho 64xH. Isso é bom de acordo com as especificações, mas alguns softwares podem mostrar apenas o primeiro bloco ou uma animação. Os ladrilhos se comprimem melhor por causa da melhor localização espacial. Ainda faço a compressão normal também para a segunda imagem e escolho o que veio mais curto. Como isso comprime a imagem duas vezes, é duas vezes mais lento em comparação à minha solução anterior.
Perl, 354 + 12 + 0 + -1 = 365
418 9521 51168 56639Existe algum erro no meu código ou a segunda imagem é otimizada para um codificador específico, pois uma mudança aparentemente insignificante reduziu exatamente o tamanho da referência. Leva cerca de 30s-60s por imagem.
Versão Golfed.
A única decisão que um compressor GIF pode tomar é quando redefinir o dicionário LZW. Em geral, devido ao modo como as imagens para esta tarefa foram escolhidas, o melhor momento para fazer isso é cada código 4096, que é o momento em que o dicionário transborda. Com esse limite, o dicionário nunca transborda, o que economiza alguns bytes na implementação. É assim que funciona em detalhes:
Perl, 394 + -8 + 0 + -12 = 374
Adicionar uma heurística para adivinhar o ponto de redefinição melhora a compactação um pouco, mas não o suficiente para justificar o código extra:
fonte
CJam, pontuação 155 + 35306 + 44723 + 21518 = 101702
Apenas uma implementação de referência idiota. É lento, não faz nenhuma compressão real e não é um jogo de golfe.
fonte