⚠️ Este é um site de tradução não oficial, sem relação com a ImageMagick Studio LLC. Para informações oficiais, consulte a página original (https://usage.imagemagick.org/anim_opt/index.html).

Exemplos do ImageMagick -- Otimização de Animação

Prefácio e Índice dos Exemplos do ImageMagick
Introdução à Otimização
Otimizador de GIF de Uso Geral do ImageMagick
Otimização de Quadros

Introdução à Otimização de Animação

Otimizar uma animação não é fácil, especialmente uma animação GIF, que tem restrições de cor, além da escolha entre diferentes técnicas de supressão de quadros e da possibilidade de usar sobreposições de 'subquadro' menores de um quadro para o outro. Ao otimizar uma animação, convém tentar otimizá-la na seguinte ordem.

Essa, porém, não é a ordem em que examinaremos essas técnicas de otimização. Para animações GIF, a Otimização de Quadros é a técnica de otimização mais básica e onde se pode obter os maiores ganhos. Por isso, será examinada primeiro. Provavelmente o aspecto mais difícil da otimização, com o qual os usuários têm problemas, é a Otimização de Cores, causada pelas limitações de cor das animações GIF. Um de seus aspectos, a Tabela de Cores Global Única, precisa ser feito como último passo antes de salvar em GIF; do contrário, você pode perder o efeito dos operadores ao salvar o arquivo GIF final.


Otimizador de GIF de Uso Geral do ImageMagick

O método '**Optimize**' de "[-layers](https://imagemagick.org/command-line-options/#layers)" usa várias das técnicas que discutiremos em detalhe abaixo para tentar otimizar uma animação GIF em um único passo razoável. Atualmente esta opção equivale a (nesta ordem)…

Nesse ponto você pode salvar imediatamente a animação GIF. Esses passos de otimização são razoavelmente seguros e podem ser aplicados à maioria das sequências de animação; contudo, não há garantia de que resultem em uma animação GIF menor. Isso vale em especial para uma sequência de vídeo bruto, em que uma Otimização de Transparência geralmente resulta na piora da taxa de compressão LZW. No entanto, para a maioria das animações GIF, que envolvem imagens no estilo desenho animado, o operador 'Optimize' deve produzir uma animação bem otimizada. Ainda assim, o operador continua em desenvolvimento e, no futuro, é provável que inclua também passos de otimização padrão adicionais, como…

  • Um limiar de 50% do canal alfa, tal como o IM normalmente faz ao salvar no formato de arquivo GIF, para remover pixels semitransparentes. Você ainda pode fazer o tratamento da semitransparência por conta própria de antemão para substituir isso, se quiser. Veja Transparência Booleana do GIF para mais detalhes.
  • Algum tipo de técnica de Otimização de Cores. O que exatamente ainda está por decidir e pode ser escolhido conforme a animação e o número de cores envolvidas. Sugestões são bem-vindas.
  • Uma operação de Tabela de Cores Global Única, "[+map](https://imagemagick.org/command-line-options/#map)".

Em outras palavras, espera-se que 'Optimize' venha a se tornar o otimizador genérico de animações GIF do IM, para uso rápido e fácil pelos usuários do IM. Até lá, tenha cuidado ao usá-lo, sobretudo em scripts, pois ele ainda vai mudar. É claro que muitos passos de otimização podem não valer o esforço para uma animação específica. Esta opção provavelmente também ficará bem lenta. Esse é o plano e a meta que esta seção dos Exemplos do IM tinha em vista.


Otimizações de Quadros

A otimização de quadros baseia-se em sobrepor uma subimagem menor em vez de sobrepor a imagem inteira por completo. Isso obviamente produz um número menor de pixels e, portanto, um arquivo menor em disco e para transmitir pela rede. Além disso, sobrepor um quadro menor significa que o computador cliente não precisa trabalhar tanto para mudar os pixels na tela. No entanto, o formato GIF oferece diferentes métodos de supressão para tratar o último quadro exibido, e isso pode resultar em sobreposições de tamanhos distintos. Não só isso: é possível dividir as sobreposições em várias partes, ou ações de atualização, produzindo uma animação mais complexa, porém mais otimizada. Por causa da complexidade da otimização de quadros, quaisquer otimizações de quadro existentes costumam ser removidas primeiro com a operação "[-coalesce](https://imagemagick.org/command-line-options/#coalesce)". Veja os Exemplos de Coalesce. Naturalmente, isso significa que quaisquer otimizações manuais que existissem também são removidas, por isso recomenda-se certa cautela.

Otimização Básica de Quadros

O método "[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)" produz uma otimização básica de quadros para uma animação GIF. Contudo, como foi mostrado nos Exemplos de Deconstruct da seção anterior, esse operador não funciona com todas as animações GIF quando há pixels transparentes envolvidos. Especificamente, quando uma animação apaga algum pixel colorido tornando-o transparente. Ou seja, ele só funciona com Animações de Sobreposição. O método '**OptimizeFrame**' de "[-layers](https://imagemagick.org/command-line-options/#layers)" foi projetado para ser um otimizador de quadros GIF, que tenta encontrar as menores imagens de sobreposição de subquadro, usando qualquer método de supressão do GIF. O resultado costuma ser uma Animação de Supressão Mista, embora muitas vezes também gere uma Animação de Quadros Apagados ou uma Animação de Sobreposição Pura, caso isso seja determinado como a melhor solução para a animação específica. Lembre-se de que a animação de entrada precisa ser uma 'animação coalescida', ou seja, deve consistir em uma sequência de quadros de imagem completos, todos do mesmo tamanho, sem qualquer deslocamento de tela. É claro que quaisquer métodos de supressão existentes em uma animação coalescida são completamente irrelevantes e serão ignorados pelo método 'OptimizeFrame'. Por exemplo, vamos tentar isso com uma Animação de Supressão Previous, criada na seção anterior. | |

  magick canvas_prev.gif -coalesce  -layers OptimizeFrame  optframe.gif
  gif_anim_montage optframe.gif optframe_frames.gif

[IM Output]
[IM Output]
[IM Output]
Como você pode ver, "[-layers](https://imagemagick.org/command-line-options/#layers) OptimizeFrame' devolveu corretamente nossa animação à sua forma original otimizada por quadros, usando Supressão Previous. Essa otimização funciona corretamente até para as mais complicadas Animações de Supressão Background… | |

  magick canvas_bgnd.gif -coalesce  -layers OptimizeFrame  optframe_bgnd.gif
  gif_anim_montage optframe_bgnd.gif optframe_bgnd_frames.gif

[IM Output]
[IM Output]
A animação está perfeitamente otimizada por quadros usando Supressão Background. Esse operador funciona corretamente para todas as animações GIF e geralmente devolve a melhor 'supressão e otimização de quadros' simples possível.
Agora, uma má notícia sobre qualquer tipo de otimização de quadros simples, como a que o IM oferece… Embora o '[OptimizeFrame](#optframe)' devolva a melhor otimização de quadros que o IM consegue determinar para uma dada animação, há alguns casos especiais em que ele não se sai bem. Entre eles estão…

  • Animações em que é preciso apagar pixels (voltando-os à transparência), mas as sobreposições de quadro são grandes demais para apagar de forma eficiente as pequenas áreas de pixels que precisam ser apagadas (veja a animação de buraco em movimento abaixo).
  • Animações que envolvem duas ou mais áreas pequenas de mudança bem distantes entre si. Elas são, na verdade, bastante comuns e péssimas de otimizar por quadros. (Veja Dividir Atualizações de Quadro abaixo)
  • Animações com fundos muito complexos que permanecem estáticos por longos períodos (mais de 3 quadros), mas então mudam ligeiramente antes de permanecer estáticos por outro longo período, e assim por diante… Ou um fundo estático que fica muito obscurecido por um período muito curto. Pode ser quase impossível para qualquer algoritmo de computador descobrir a 'melhor' otimização de quadros nessa situação complexa (ou seja: o que deve ser considerado um fundo estático?). Só seres humanos, com sua compreensão intuitiva do que veem, conseguem gerar uma boa sequência de sobreposição de quadros ótima nesses casos.

Procuramos exemplos de animações difíceis de otimizar; por favor, contribua. Se você encontrar um exemplo de animação para a qual o IM não consegue produzir uma boa otimização, envie-o para mim para estudo posterior. É assim que novas técnicas e possíveis soluções automáticas podem ser desenvolvidas. Naturalmente, publicarei seu nome como colaborador.

Sem Sobreposição de Pixels - imagem repetida a cada segundo quadro

[animation] Às vezes, a melhor otimização para uma imagem consiste em não sobrepor nenhum pixel! Por exemplo, à direita está uma animação simples, contribuída por nixscripter. Se olharmos seus quadros, você verá que ela não está muito otimizada. Mas note que todo segundo quadro da animação é simplesmente repetido.

  gif_anim_montage paddleball.gif paddleball_frames.gif

[IM Output]

Depois de otimizá-la por quadros, obtemos uma sequência de supressão GIF muito especial. | |

  magick paddleball.gif -coalesce -layers OptimizeFrame  paddleball_opt.gif
  gif_anim_montage paddleball_opt.gif paddleball_opt_frames.gif

[IM Output]
[IM Output]
O que acontece é que, em vez de sobrepor o quadro original, o IM optou por recuperar a primeira imagem usando a supressão GIF 'Previous'. Como esse quadro recuperado permanece como está, não há pixels alterados. Assim, a sobreposição de subquadro se reduz a nada. Infelizmente, nem o IM nem o formato GIF permitem ter uma imagem de tamanho zero, então uma imagem mínima especial de um único pixel transparente é usada no lugar. Essa imagem é conhecida como Imagem Perdida, pois também é muito usada quando "[-crop](https://imagemagick.org/command-line-options/#crop)" 'perde' os dados reais da imagem, produzindo o mesmo resultado. Essa imagem, na prática, apenas preserva os metadados do quadro, como: Método de Supressão, Atraso de Tempo e Iterações do Laço. Como tal, é uma parte essencial da animação, ainda que esteja 'vazia'. Portanto, ao sobrepor um único e mínimo pixel transparente, o IM economizou uma enorme quantidade de espaço (e tempo) nesta animação.

Animação de Buraco em Movimento - difícil de otimizar por quadros

Aqui está um caso extremo de animação GIF que não se otimiza muito bem por quadros com nenhum método normal de otimização. Essa animação consiste basicamente em uma imagem de fundo simples e imutável, mas com um 'buraco' transparente atravessando esse fundo, que muda de posição de quadro para quadro. Para criá-la, preciso montar uma sequência de imagens coalescida, em que recorto um buraco em uma imagem de fundo fixa, usando Composição Alfa em Camadas. Também usei uma chave "[+antialias](https://imagemagick.org/command-line-options/#antialias)" para garantir que apenas quatro cores sejam usadas: três azuis e a transparência. Assim, não precisamos lidar com Problemas de Otimização de Cores. | |

  magick +antialias -size 100x100 -delay 100 xc:SkyBlue -loop 0 \
          -fill DodgerBlue -draw 'circle 50,50 15,25' \
          -fill RoyalBlue  -draw 'circle 50,50 30,25' \
          null: \( -size 100x100 xc:none -draw 'circle 40,25 27,22' \) \
                \( +clone -rotate 90 \) \( +clone -rotate 90 \) \
                \( +clone -rotate 90 \) -compose DstOut -layers Composite \
          -set dispose background  moving_hole.gif
  gif_anim_montage moving_hole.gif moving_hole_frames.gif

[IM Output]
[IM Output]
Como você pode ver, a animação funciona, com um 'buraco' redondo mostrando a cor de fundo desta página, produzindo um arquivo de animação de [IM Text] bytes de tamanho. Então vamos tentar uma otimização de quadros direta para esta animação. | |

  magick moving_hole.gif  -layers OptimizeFrame  moving_hole_opt.gif
  gif_anim_montage moving_hole_opt.gif moving_hole_opt_frames.gif

[IM Output]
[IM Output]
Espere, nada aconteceu! A melhor otimização que o IM conseguiu foi nenhuma mudança! Será que a versão coalescida acima desta animação já é a mais ótima? Bem, para a animação como está… Sim, esta realmente é a melhor otimização simples que se pode obter apenas com otimização por supressão de quadros! Nada bom. O problema é que, para uma animação GIF 'apagar' ou 'limpar' os pixels desenhados por quadros anteriores, ela precisa usar um método de supressão 'Background'. Embora, em algumas situações especiais, um método de supressão 'Previous' também possa ser usado. Contudo, a supressão 'Background' só pode apagar áreas que acabaram de ser sobrepostas. Como o primeiro quadro foi uma sobreposição completa da imagem inteira, a imagem inteira será apagada. Mesmo que apenas uma pequena parte da animação precise ter seus pixels apagados. Como consequência, o segundo quadro inteiro precisa ser sobreposto, ainda que a maior parte desse quadro tenha acabado de ser exibida! Essa horrível situação de impasse continua por todo o restante da animação, não produzindo nenhuma otimização básica de quadros. Eu já havia dito que esta animação seria difícil de otimizar por quadros.

Duplicação de Quadros - um método para otimizar 'buracos' por quadros

Nem tudo está perdido, porém. Ao adicionar alguns quadros extras à animação, você dá ao método '[OptimizeFrame](#optframe)' um espaço em que ele pode aproveitar melhor os métodos de supressão do GIF disponíveis. Aqui, por exemplo, adicionamos um quadro extra duplicando a primeira imagem, mas dando a ela um atraso de tempo zero para não alterar as temporizações gerais da animação. | |

  magick moving_hole.gif[0] -set delay 0   moving_hole.gif \
          -layers OptimizeFrame    moving_hole_dup.gif
  gif_anim_montage moving_hole_dup.gif moving_hole_dup_frames.gif

[IM Output]
[IM Output]
Ao duplicar o primeiro quadro, a animação foi reduzida de [IM Text] bytes para [IM Text] bytes de tamanho. Assim, embora a animação tenha agora cinco quadros, ela é bem menor no tamanho total, por causa da redução enorme no tamanho das sobreposições de imagem de subquadro. A duplicação essencialmente separa a função de apagar pixels do método de supressão da função de sobrepor pixels realizada pelo próximo quadro. Tanto a supressão quanto a sobreposição são feitas como parte da mesma atualização de quadro pelos programas de animação GIF, de modo que nenhuma perda de velocidade ou qualidade deve ser perceptível. Esta é uma técnica complexa e delicada, raramente vista ou compreendida por projetistas de animação GIF ou por programas de otimização de GIF, mas seus benefícios valem muito a pena quando é necessária. No entanto, a redução no tamanho das imagens de subquadro dura pouco tempo, pois quadros posteriores também têm de apagar pixels para o próximo quadro, de modo que os quadros voltam a ficar grandes para continuar apagando pixels posteriores. Ou seja, como apagar pixels sempre resulta em quadros maiores, nunca menores. Então vamos tentar duplicar todos os quadros (exceto o último, que nunca precisa ser duplicado) para ver como isso afeta a imagem final… | |

  magick moving_hole.gif  \( -clone 0--1 -set delay 0 \) \
          +delete -insert 2 -insert 1 -insert 0 \
          -layers OptimizeFrame  moving_hole_double.gif
  gif_anim_montage x2 moving_hole_double.gif moving_hole_double_frames.gif

[IM Output]
[IM Output]
Como você pode ver, embora tenhamos quase o dobro de quadros, todos os tamanhos de imagem são bem menores, produzindo uma animação de [IM Text] bytes de tamanho, um resultado menor, embora nem de longe uma economia tão grande quanto a primeira duplicação de um único quadro que fizemos. Para que você acompanhe o que está acontecendo, o quadro '[Background](anim_basics.html#background)' é uma cópia exata do quadro anterior, sem alterar o que está sendo exibido. Contudo, ele define a área da animação que precisa ser apagada antes que a imagem do próximo quadro seja sobreposta. O quadro '[None](anim_basics.html#none)' seguinte então preenche os pixels que precisam ser alterados, bem como os pixels que a supressão dos quadros anteriores também apagou. Na animação acima, isso significa os pixels necessários para formar o novo buraco, além dos pixels usados para preencher o 'buraco' anterior. O resultado é menor, mas nem de longe tanto, pois adicionar quadros extras tem seu próprio custo. Ao menos cada um dos quadros adicionados também não tem sua própria tabela de cores; caso contrário, esta animação teria, na verdade, ficado maior, por causa do tamanho das tabelas de cores extras!

Layer Optimize Plus - Otimização com duplicação automática de quadros

Tenho o prazer de dizer que, a partir da versão 6.2.7, o IM agora consegue fazer a otimização por duplicação de quadros automaticamente, como parte de seu tratamento normal de otimização de quadros. Contudo, como adicionar quadros para tornar uma animação menor é uma medida tão radical, ela recebeu seu próprio método separado '**OptimizePlus**' de "[-layers](https://imagemagick.org/command-line-options/#layers)". Por exemplo, vamos fazer o IM realizar a otimização por duplicação de quadros… | |

  magick moving_hole.gif  -layers OptimizePlus   moving_hole_oplus.gif
  gif_anim_montage x2 moving_hole_oplus.gif moving_hole_oplus_frames.gif

[IM Output]
[IM Output]
Ou seja, o IM lhe deu o mesmo resultado do nosso exemplo anterior de duplicação de quadros. Assim, o arquivo GIF continua com [IM Text] bytes de tamanho. Contudo, 'OptimizePlus' só duplica quadros se o número de pixels no quadro atual e no próximo da animação resultante (3 quadros) for reduzido, de modo que podemos deixar o IM decidir se duplica ou não os quadros. Como o método '[OptimizePlus](#optimizeplus)' de "[-layers](https://imagemagick.org/command-line-options/#layers)" adiciona quadros extras ao criar uma animação GIF otimizada por quadros, ele também remove quaisquer quadros desnecessários ou extras que não alterem a animação final (mesclando os tempos de atraso conforme apropriado). Ou seja, ele também faz um '[RemoveDups](#removedups)' automático (veja a seguir). O método '[OptimizeFrame](#optframe)' não faz isso.

Remover Quadros Duplicados - mesclar imagens duplicadas consecutivas

Infelizmente, se você coalescer" esta animação, também obterá todos os quadros extras que a operação acima adicionou.

  magick moving_hole_oplus.gif -coalesce gif:- |\
     gif_anim_montage x2 - moving_hole_oplus_cframes.gif

[IM Output]

Para permitir que você remova esses quadros duplicados inúteis de uma animação coalescida, foi disponibilizado um método '**RemoveDups**'. Ele compara cada quadro com o quadro seguinte da animação e remove o primeiro quadro se forem idênticos (com a semelhança de cor definida pelo Fator de Fuzz atual). Além disso, para garantir que quaisquer temporizações da animação não se percam, os Atrasos de Tempo dos dois quadros também são mesclados. Por exemplo…

  magick moving_hole_oplus.gif -coalesce -layers RemoveDups  gif:- |\
     gif_anim_montage - moving_hole_oplus_rmdups_frames.gif

[IM Output]

E agora temos nossa forma coalescida original da animação. Para outro método de remover os quadros extras, veja o método '[RemoveZero](#removezero)' abaixo.

Dividir Atualizações de Quadro - atualizar separadamente duas mudanças distantes

Como você viu com a duplicação de quadros, ao separar a 'limpeza de pixels' da sobreposição de novos pixels, podemos reduzir o tamanho total de uma única sobreposição de quadro. Contudo, esta animação ainda produz algumas sobreposições muito grandes, compostas em sua maior parte por pixels que, na verdade, não mudam de um quadro para o outro. Ou seja, a sobreposição principal do quadro está atualizando apenas duas áreas bastante pequenas e bem distantes uma da outra, produzindo assim uma única imagem de sobreposição grande. Em vez de tentar atualizar ambas as mudanças simultaneamente, incluindo também todos aqueles pixels inalterados entre as duas áreas, atualizamos cada área separadamente. Ou seja, dividimos a atualização de quadro em duas fases, uma para cada área separada que mudou. Neste caso, podemos primeiro preencher o buraco e depois criar o novo buraco como uma atualização separada. Na verdade, não importa (a não ser talvez quanto às supressões) qual das duas mudanças separadas ocorre primeiro, mas você deve procurar ser lógico a respeito. Também pode acontecer de uma mudança ser mais fácil de criar do que a outra. Por exemplo, aqui insiro quadros extras para preencher o buraco antigo como uma atualização separada da 'escavação' do novo buraco. Este é o quadro intermediário mais fácil de gerar, além de ser a ordenação mais lógica das ações. É claro que você não precisa fazer isso para o último quadro, pois esse quadro é simplesmente descartado antes de a animação recomeçar o laço. | |

  magick moving_hole.gif \
          \( +antialias -size 100x100 -delay 0 xc:SkyBlue \
             -fill DodgerBlue -draw 'circle 50,50 15,25' \
             -fill RoyalBlue  -draw 'circle 50,50 30,25' \) \
          \( +clone \) -insert 1 \( +clone \) -insert 3  +swap \
          -set dispose background  moving_hole_split.gif
  gif_anim_montage x2 moving_hole_split.gif moving_hole_split_frames.gif

[IM Output]
[IM Output]
Lembre-se de que o quadro intermediário adicionado é diferente dos quadros exibidos ao usuário ao seu redor (aqueles com atraso de tempo diferente de zero). Isto não é uma simples 'duplicação de quadros', mas a separação de duas pequenas mudanças distantes. Essa adição de quadros intermediários não é um passo simples que se possa automatizar. Embora seja possível desenvolver uma heurística inteligente para gerar esses quadros intermediários, nem sempre é óbvio o que deve ser feito, muito menos se deve ser feito. Se você quiser tentar criar essa heurística, por favor me escreva. Então vamos tentar uma otimização de quadros padrão depois de adicionar esses quadros extras… | |

  magick moving_hole_split.gif \
               -layers OptimizeFrame     moving_hole_split_opt.gif
  gif_anim_montage x2 moving_hole_split_opt.gif \
                      moving_hole_split_opt_frames.gif

[IM Output]
[IM Output]
A adição desses 'quadros intermediários com atraso zero' permite que esta animação seja otimizada por quadros melhor do que a animação original não otimizada, produzindo uma animação de [IM Text] bytes. Contudo, para este caso específico, não é tão bom quanto usar uma técnica automatizada de Duplicação de Quadros (Veja o método de camadas 'OptimizePlus' acima). No entanto, adicionar 'quadros intermediários com atraso zero' não impede que você também aplique aquela técnica de 'duplicação de quadros'… | |

  magick moving_hole_split.gif \
               -layers OptimizePlus moving_hole_split_oplus.gif
  gif_anim_montage x2 moving_hole_split_oplus.gif \
                      moving_hole_split_oplus_frames.gif

[IM Output]
[IM Output]
Esta animação agora tem dois 'quadros intermediários com atraso zero' extras por atualização de quadro. O primeiro preenche o buraco antigo; o segundo apaga uma área que conterá pixels transparentes, antes de, finalmente, restaurar os pixels que não deveriam ter sido apagados. O resultado é a otimização de quadros mais ótima possível para esta animação-problema específica, resultando em [IM Text] bytes no tamanho final do arquivo. Ou seja, nossa animação de 4 quadros foi tornada menor com a adição de 6 quadros extras com atraso de tempo zero! Mais que o dobro do número original de quadros. Estranho, mas verdadeiro! É claro que também seria bom se os programas de animação GIF de fato reconhecessem os Quadros Intermediários com Atraso Zero pelo que são, a saber, atualizações intermediárias entre os quadros reais da animação. Mas, mesmo assim, quando as atualizações são muito separadas e muito pequenas, a leve pausa causada pelos quadros extras raramente é visível.
É claro que, se as duas partes separadas da animação não estiverem, de fato, relacionadas, então elas não precisam ser sincronizadas no tempo. Outra alternativa é que, em vez de adicionar quadros extras, você divida a animação em duas animações completamente separadas que possa exibir juntas em uma página web. Veja Dividir uma Animação. Esta animação em particular, porém, não pode ser dividida em animações separadas e disjuntas no tempo. Primeiro, as mudanças distantes precisam ser sincronizadas no tempo. E segundo, as quatro áreas que mudam se sobrepõem tanto na direção horizontal quanto na vertical. Isso significa que uma simples 'tabela' HTML não consegue reunir as subanimações em um todo completo, sem algum tipo de truque com CSS. Você consegue provar que estou errado? FUTURE: referência a um exemplo melhor de animação de 'dois objetos distantes', em 'Tratamento de Animação', digamos envolvendo dois objetos movendo-se separadamente.

Remover Quadros com Atraso Zero - remover atualizações intermediárias

É claro que, às vezes, você não tem interesse em manter esses quadros intermediários adicionados ou quer removê-los de uma animação, deixando apenas os quadros que serão de fato exibidos a um usuário por algum período de tempo. Você não pode simplesmente coalescer a animação e usar o método '[RemoveDups](#removedups)', pois nem todos os 'Quadros Intermediários' são semelhantes aos quadros ao seu redor e, portanto, não são duplicados. Contudo, como esse tipo de quadro tem Atraso de Tempo Zero, você pode usar outro método especial '**RemoveZero**' de "[-layers](https://imagemagick.org/command-line-options/#layers)", que removerá qualquer quadro que tenha atraso de tempo zero. Esse mesmo método também removerá os quadros adicionados usando as técnicas de Duplicação de Quadros e '[OptimizePlus](#optimizeplus)'. Por exemplo…

  magick moving_hole_split_oplus.gif -coalesce -layers RemoveZero gif:- |\
     gif_anim_montage - moving_hole_split_rmzero_frames.gif

[IM Output]

O que, mais uma vez, devolve a animação apenas aos quadros visíveis pelo usuário, simplificando a animação. É claro que, depois de remover os Quadros Intermediários com Atraso Zero, é muito difícil readicioná-los, pois a informação de mudança que eles contêm se perde. Consequentemente, a animação pode não se otimizar muito bem por quadros depois disso. Afinal, a otimização é um dos principais propósitos desses quadros.

Resultados e Resumo da Otimização de Quadros

Vamos resumir nossas otimizações da animação do buraco em movimento…

[IM Text]

Como você pode ver, usando um tratamento de quadros complexo, com a ajuda do IM e alguma intervenção humana, conseguimos otimizar por quadros a animação do 'buraco em movimento' para quase a metade de seu tamanho original, ainda que com quase três vezes o número de quadros do original. É claro que os resultados podem variar muito de animação para animação, mas as técnicas que usamos para a otimização de quadros são as mesmas. Basta um pouco de cuidado e previsão, coisa em que os humanos são bons e os computadores não. | _Há o ponto de que o IM não deveria levar em conta apenas o número de pixels no conjunto atual de quadros em análise, mas também o tamanho total do quadro extra adicionado e, talvez, os resultados gerais de compressão obtidos, ao tomar a decisão sobre como otimizar a imagem por quadros.

Por outro lado, o IM também não considera as economias resultantes no número de pixels que podem surgir além dos quadros diretamente envolvidos. Ou seja, os tamanhos de quadros posteriores também podem ser menores em consequência da duplicação de quadros ou do método de supressão usado. Isso é especialmente verdadeiro quando a escolha é usar ou não o método de 'supressão previous', que pode gerar reduções substanciais na contagem de pixels mais adiante em uma sequência de animação, em vez de imediatamente no próximo quadro. Uma boa escolha aqui muitas vezes exige a intervenção humana.

Por isso, não posso garantir que o IM produza as melhores escolhas de otimização para uma animação específica. Contudo, ele certamente faz uma boa tentativa, sem o uso de recursão, para fazer essa escolha. Ou seja, usando apenas as contagens imediatas de pixels para sua decisão.

Um algoritmo recursivo, que faz uma escolha e depois verifica qual o melhor tamanho final da animação que resulta dessa escolha (incluindo escolhas recursivas mais adiante), pode produzir uma otimização garantidamente ótima. Contudo, ele também poderia ser um operador extremamente lento e, para uma animação grande, poderia levar anos para tomar a decisão final. Ele também precisaria incluir as escolhas de otimização de compressão, pois estas poderiam afetar o resultado final. Em outras palavras, embora tal algoritmo pudesse garantir a melhor otimização, ele o faz a um pesado custo computacional.

É claro que um ser humano com conhecimento íntimo do que a animação tenta realizar geralmente se sairá melhor em animações complexas, como você viu acima com a divisão de atualizações de quadro.

Se você quiser tentar criar um operador recursivo de otimização de GIF, por favor, faça-o. Eu ajudarei no que puder. Ele superaria praticamente qualquer outro programa de otimização de GIF do mercado. Além disso, a maioria dos desenvolvedores de animação GIF provavelmente ficará muito grata por seus esforços (em termos financeiros)._
---|---


Tratamento de Semitransparência

O formato de arquivo GIF não permite o uso de pixels semitransparentes (Veja Transparência Booleana do GIF). Isso é um fato e, antes de conseguir otimizar corretamente uma animação, ou mesmo salvá-la em formato GIF, você precisa tratar quaisquer pixels semitransparentes que possam estar presentes, de uma maneira adequada à animação. Por padrão, se você não tratar esses pixels, o IM usará um limiar de 50% para tornar esses pixels totalmente transparentes ou totalmente opacos. Contudo, essa pode não ser a melhor maneira de tratar o problema, especialmente em imagens que contêm grandes áreas de pixels semitransparentes, como efeitos de sombra. Por exemplo, eu quis criar uma animação de teletransporte estilo Asgard de Stargate que pudesse levar praticamente qualquer subimagem como o objeto a ser teletransportado.

  magick -channel RGBA -fill white \
          \( medical.gif -repage 100x100+34+65 -coalesce -set delay 200 \) \
          \( +clone -motion-blur 0x20+90 -blur 0x3 -colorize 100% \
                +clone -colorize 30%  +swap  -composite  -set delay 10  \) \
          \( +clone -roll +0-20 -blur 0x3 -colorize 30% \
             -motion-blur 0x15+90 -motion-blur 0x15-90 -set delay 10 \) \
          \( +clone -colorize 30% \
             -motion-blur 0x30+90 -blur 0x5 -crop +0+10\! \) \
          \( +clone -motion-blur 0x50+90 -blur 0x2 -crop +0+20\! \) \
          \( +page -size 100x100 xc:none -set delay 200 \) \
          -set dispose background -coalesce   -loop 0     teleport.miff
  gif_anim_montage teleport.miff teleport_frames.png

[IM Output]

Deixei propositalmente a animação no formato de arquivo MIFF: interno do IM, pois isso garante que a imagem original seja preservada sem modificação, e usei o formato de arquivo PNG: para exibir os quadros, de modo que você possa ver todos os pixels semitransparentes nele contidos! Isto é importante não só para animações com pixels semitransparentes, mas também para as que têm muitas cores. Uma vez que a sequência de imagens tenha sido salva em GIF, suas chances de gerar uma boa otimização de cores passam de boas a difíceis. Certo, tenho uma sequência de animação. Se eu tentar salvá-la diretamente como GIF, o IM simplesmente aplicará um limiar a todos aqueles pixels semitransparentes. |

  magick teleport.miff teleport_thres.gif
  gif_anim_montage teleport_thres.gif teleport_thres_frames.gif

[IM Output]

[IM Output]

O resultado não se parece nada com o que queríamos. O tratamento de transparência padrão de 50% faz a animação parecer um 'ovo' que encolhe. Definitivamente não é o que quero alcançar com esta animação. Se esse tipo de tratamento de transparência for aceitável, é assim que se aplica, antes de continuar com suas outras otimizações…

  magick teleport.miff -channel A -threshold 50% +channel \
                 ...faça mais processamento agora...       teleport.gif

Uma vantagem adicional de usar o método manual acima é que você pode controlar o nível do limiar. Digamos '10%' para remover quase todos os pixels semitransparentes presentes, ou '90%' para torná-los todos opacos. |

  magick teleport.miff -channel A -threshold 90% +channel teleport_thres90.gif
  gif_anim_montage teleport_thres90.gif teleport_thres90_frames.gif

[IM Output]

[IM Output]

Mas aplicar um limiar a animações como esta não é uma boa solução, pois estraga de fato o efeito de transparência que estou tentando alcançar. A melhor solução geral para preservar todos os efeitos especiais na animação acima é simplesmente Adicionar uma Cor de Fundo Sólida. |

  magick teleport.miff -bordercolor skyblue \
                  -coalesce -border 0 teleport_bgnd.gif
  gif_anim_montage teleport_bgnd.gif teleport_bgnd_frames.gif

[IM Output]

[IM Output]

Isso remove TODA a transparência da animação, mas ao custo de só permitir que a animação funcione sobre uma cor de fundo específica. Mas, se você estiver criando a animação para uma página web específica, isso pode ser bem aceitável. Note, porém, que, para imagens com contornos nítidos, usar um padrão de pontilhamento como este pode produzir um contorno 'pontilhado' nas bordas nítidas. Por isso, não é recomendado para o caso geral. A outra solução é tentar gerar algum padrão de pixels transparentes e opacos de modo a preservar a semitransparência das imagens. E, para isso, o IM oferece uma vasta gama de opções de pontilhamento que podem resolver esse problema. FUTURE: algum link para uma seção, ainda a ser criada, sobre pontilhamento de transparência, comoQuantização e Pontilhamento. Note que a primeira solução óbvia, usar um Pontilhamento Monocromático do canal alfa, não é simples e provavelmente exige alguma Composição Multi-Imagem avançada para ser feita corretamente. Uma solução simples é usar uma técnica de Pontilhamento Ordenado por Pixel Difuso, que pode ser restrita apenas ao canal alfa, para remover os pixels semitransparentes. |

  magick teleport.miff -channel A -ordered-dither o8x8  teleport_od.gif
  gif_anim_montage teleport_od.gif teleport_od_frames.gif

[IM Output]

[IM Output]

O resultado é razoável, mas parece um objeto se dissolvendo mais do que se teletransportando. Usar um Meio-tom produzirá um efeito bem mais agradável, tornando o padrão de transparência mais marcante. |

  magick teleport.miff -channel A -ordered-dither h8x8a teleport_htone.gif
  gif_anim_montage teleport_htone.gif teleport_htone_frames.gif

[IM Output]

[IM Output]

Mas, para esta animação específica, descobri que usar um Mapa de Pontilhamento Projetado pelo Usuário para produzir linhas verticais (a partir de um padrão de pontilhamento de linhas horizontais) produz um efeito que realça a animação de teletransporte ao mesmo tempo que remove os pixels semitransparentes. |

  magick teleport.miff -rotate 90 \
          -channel A -ordered-dither hlines -rotate -90 teleport_lines.gif
  gif_anim_montage teleport_lines.gif teleport_lines_frames.gif

[IM Output]

[IM Output]

Como você pode ver, há um bom número de possibilidades para tratar a semitransparência em uma animação GIF.


Otimização de Cores

Tratar pixels semitransparentes é apenas a primeira limitação do formato de arquivo GIF. A próxima é o limite de 256 cores para cada tabela de cores na animação. Você tem permissão para ter uma tabela de cores separada para cada quadro. Isso significa que uma única animação pode ter mais de 256 cores. Contudo, mesmo isso nem sempre é uma boa ideia. Se você quiser apenas um resumo rápido das opções de otimização de cores disponíveis, sugiro que pule para os exemplos de conversão de Vídeo para GIF, onde os problemas de cor de uma animação são os piores possíveis.

Problema de Cores do GIF

As animações GIF, em particular, têm problemas para tratar cores: primeiro, não permitem cores semitransparentes; depois, têm um limite de 256 cores por quadro, ou um limite global de 256 cores. Por fim, sua melhor otimização de quadros não funcionará muito bem, a menos que as cores usadas para um pixel em um quadro também correspondam à mesma cor no quadro seguinte, quando aquela parte da imagem NÃO mudou! Isso pode parecer um problema fácil, mas a Redução de Cores é, ela mesma, um campo extremamente complexo, que exigiu sua própria seção completa nos Exemplos do IM. Os problemas de cor são, na verdade, a razão pela qual a maioria das animações GIF que você encontra na World Wide Web são do tipo desenho animado, ou têm aparência muito ruim. Especialmente se forem redimensionadas a partir de uma versão maior da animação. Em Redimensionar Animações, a otimização de cores provavelmente exigirá mais esforço do que o próprio processo de redimensionamento. Aqui vou supor que você tem a origem original da animação. Mas isso nem sempre é possível, então, se você estiver otimizando uma animação GIF modificada, pode ser necessária alguma cautela adicional. Contudo, se você tem uma animação com cores demais, a primeira coisa que precisa lembrar é…

Não salve diretamente em formato GIF,
use o formato de arquivo MIFF, OU imagens PNG separadas.

Assim que você salva em GIF, perde o controle sobre seus esforços de otimização de cores do GIF, e provavelmente tem uma animação GIF de aparência muito ruim, que não se otimizará muito bem usando as várias técnicas de Otimização de Quadros.

Animação Speed - uma Animação com cores em excesso

Primeiro, precisamos gerar uma animação GIF com uma quantidade enorme de cores, para que possamos realmente testar os problemas envolvidos na otimização de cores. | |

  magick -dispose none -channel RGBA \
          \( medical.gif -repage 100x60+5+14  -coalesce -set delay 100 \) \
          \( medical.gif -repage 100x44+34+6  -coalesce -set delay 10 \
             -motion-blur 0x12+0  -motion-blur 0x12+180 -wave -8x200 \) \
          \( medical.gif -repage 100x60+63+14 -coalesce -set delay 100 \) \
          \( medical.gif -repage 100x44+34+6  -coalesce -set delay 10 \
             -motion-blur 0x12+0  -motion-blur 0x12+180 -wave +8x200 \) \
          null: \( +page  -size 120x15 xc:SkyBlue xc:RoyalBlue \
                   -size 120x70 gradient:SkyBlue-RoyalBlue \
                   +swap -append -blur 0x3 -background white -rotate -25 \
                \) -gravity center -compose DstOver -layers Composite \
          -loop 0   speed.miff

  magick  speed.miff  speed.gif
  gif_anim_montage  speed.gif  speed_frames.gif

[IM Output]
[IM Output]
Note que não salvei a animação diretamente no formato GIF, mas em um arquivo de formato MIFF, "[speed.miff](../static/img/anim_opt/speed.miff)", primeiro. Isso preserva todos os aspectos da animação criada (ou modificada) originalmente, incluindo os metadados do GIF, os atrasos de temporização, bem como todas as cores da imagem sem distorção. Só depois de preservar a animação original é que converti diretamente a animação original para o formato GIF. Dessa forma, pude mostrar o que o código acima pretende alcançar, e por que o chamei de 'speed'. Isso também foi feito para fornecer uma animação GIF de referência para estudo e comparação posterior. Então vamos examinar vários detalhes de nossa animação original…

  magick identify -format "Number of Frames: %n\n" speed.miff | head -1

[IM Text]

  magick identify -format "Colors in Frame %p: %k\n"  speed.miff

[IM Text]

  magick speed.miff +append  -format "Total Number of Colors: %k"  info:

[IM Text]

Como você pode ver, cada imagem da animação tem um número muito grande de cores. Não só cada quadro tem um número diferente de cores, mas o primeiro e o terceiro quadros são muito parecidos em termos de cor, embora não exatamente iguais. Contudo, como o formato de arquivo GIF só pode salvar no máximo 256 cores por quadro, ao salvar isto em formato GIF o ImageMagick o fez da maneira mais rápida e simplória possível… Ele reduziu o número de cores de cada quadro da animação (um processo chamado Quantização de Cor)…

  magick identify -format "Colors in Frame %p: %k\n"  speed.gif
  magick speed.gif +append  -format "Total Number of Colors: %k"  info:

[IM Text]

Como o número reduzido de cores em cada quadro é ligeiramente diferente, o IM também precisou fornecer um mapa de cores separado para cada quadro da animação. Isso significa que o arquivo GIF tem uma 'Tabela de Cores Global', como sempre tem, mas também três 'Tabelas de Cores Locais' separadas. O comando "magick identify" não consegue lhe dizer quantas dessas tabelas de cores locais um arquivo GIF tem, pois a informação é específica demais do formato e não é importante para o processamento de imagem que o IM normalmente faz. Contudo, o programa mais específico "[Giftrans](http://www.ict.griffith.edu.au/anthony/software/#giftrans)" pode lhe dizer quantas tabelas de cores locais de baixo nível foram usadas…

  giftrans -L speed.gif 2>&1 | grep -c "Local Color Table:"

[IM Text]

Como você pode ver, esta animação tem [IM Text] tabelas de cores locais, uma a menos que o número de quadros presentes na imagem, exatamente como eu previra. Não só cada quadro tem um conjunto diferente de cores, mas também um padrão de cores ligeiramente diferente (o padrão de pontilhamento da imagem), conforme descrito em Problemas com Pontilhamentos por Correção de Erro. Normalmente, essa operação padrão de Quantização de Cor e Pontilhamento do IM é muito boa e perfeitamente adequada para figuras, especialmente fotos da vida real. Na verdade, os quadros individuais de uma animação geralmente ficarão ótimos. Todos os problemas surgem quando tentamos depois juntar esses quadros reduzidos em cor individualmente em uma única sequência de animação.

Otimizar Quadros Antes das Cores?

Como você viu acima, salvar uma animação diretamente em formato GIF funciona, mas você obterá bastante diferenças de cor de um quadro para o outro, o que é ruim para a Otimização de Quadros posterior (como você verá adiante). Para evitar que as diferenças de cor causem tais problemas, você pode fazer a Otimização de Quadros antes de salvar a animação, evitando assim as diferenças de cor introduzidas de um quadro para outro. Contudo, fique avisado de que fazer a otimização de quadros antes da redução de cores muda a dinâmica da redução de cores. Muitas vezes, menos das áreas estáticas e imóveis aparecerá no subquadro otimizado, o que significa que a quantização de cor para aquele quadro pode dar menos importância àquelas cores e, portanto, menos cores.

Otimização de Cores Aproximada

Contudo, às vezes você não tem acesso à animação original antes de ela ter sido salva em formato GIF. Isso é especialmente verdadeiro se você baixou a animação original da WWW. Isso significa que você já tem uma animação com todas aquelas distorções de cor do GIF já presentes, produzindo problemas com otimizações posteriores. Ora, como um conjunto ligeiramente diferente de cores é usado de um quadro para o outro, e um padrão diferente de pixels é usado para cada quadro da animação, cada quadro pode ser considerado uma imagem completamente diferente. Por exemplo, vamos comparar o primeiro e o terceiro quadros, que compartilham grande parte da mesma imagem de fundo… |

  magick compare  speed.gif'[0,2]' speed_compare.gif

[IM Output]
As áreas vermelhas do exemplo acima mostram duas áreas quadradas sólidas das regiões que são diferentes, exatamente como você esperaria. Mas também mostram faixas de diferenças de cor contornando o fundo dos dois quadros. Elas representam o padrão de pontilhamento 'agitado' ao longo das bordas do gradiente de fundo, onde pixels de cores diferentes foram usados para representar exatamente o mesmo fundo. Este também foi o par de quadros que mostrou as menores perturbações de fundo causadas pelo uso de conjuntos de cores e padrões de pontilhamento diferentes. As diferenças reais entre quadros consecutivos são muito piores, produzindo quase um vermelho sólido de diferença. | _Diferenças de imagem como esta também são um problema se suas imagens de origem tiverem sido armazenadas usando o formato de imagem JPEG. Esse formato usa um método de compressão com perdas que (mesmo com 100% de qualidade) causa leves diferenças de cor nas imagens. Contudo, as diferenças geralmente se confinam a um halo ao redor das áreas reais de diferença, em vez de se espalharem por toda a imagem.

Tudo o que posso dizer é: evite imagens JPEG para uso em animações, a menos que você planeje usar uma única imagem como imagem de fundo estática para TODOS os seus quadros._
---|---
Como tantos pixels da animação são diferentes de um quadro para o outro, não é de surpreender que, quando tentamos Otimizar por Quadros a animação, não obtenhamos otimização alguma…

  magick speed.gif  -layers OptimizeFrame  speed_opt2.gif
  gif_anim_montage  speed_opt2.gif  speed_opt2_frames.gif

[IM Output]

Contudo, a maioria das diferenças de cor de pixel entre as partes imutáveis dos quadros da animação é, na verdade, bem pequena. Não teria sido uma Redução de Cores muito boa se não fosse esse o caso. Isso significa que, ao pedir ao IM que relaxe um pouco suas comparações de cor, você pode fazê-lo ignorar diferenças de cor menores. Isso é feito ajustando um Fator de Fuzz apropriado.

  magick speed.gif  -fuzz 5%  -layers OptimizeFrame  speed_opt3.gif
  gif_anim_montage speed_opt3.gif speed_opt3_frames.gif

[IM Output]

Como você pode ver, com a adição de um pequeno Fator de Fuzz, o IM agora ignora os pixels que são apenas ligeiramente diferentes, produzindo uma Otimização de Quadros razoável. De quanto fator de fuzz você precisa depende de quanta dificuldade o IM teve para reduzir as cores das imagens originais. Neste caso, não foi muita, então bastou um fator bem pequeno. Se um pequeno fator de fuzz produzir um resultado aceitável, então basta defini-lo para sua Otimização de Quadros e Otimização de Transparência. Apenas lembre-se de que você ainda tem uma tabela de cores separada para cada quadro a cuidar, que é o próximo ponto de discussão. Note também que a Otimização de Quadros decidiu usar uma Supressão Previous para o segundo quadro. Ou seja, depois de exibir o segundo quadro, a imagem volta à supressão do quadro anterior (a primeira imagem) antes de sobrepor. Isso resultou em um tamanho de imagem de sobreposição menor do que se nenhuma supressão tivesse sido usada em toda parte. Se você quisesse apenas uma simples Animação de Sobreposição, usando apenas Supressão None em toda parte, poderia ter usado o antigo operador Deconstruct (também conhecido como Layers CompareAny) para gerá-la.

  magick speed.gif  -fuzz 5%  -deconstruct  speed_opt4.gif
  gif_anim_montage speed_opt4.gif speed_opt4_frames.gif

[IM Output]

Gerar uma Tabela de Cores Global Única

Ora, como cada quadro tem um conjunto diferente de cores, o IM foi forçado a salvar a imagem com uma tabela de cores separada para cada quadro: uma global para o primeiro quadro e 3 tabelas de cores locais para os quadros posteriores. Por exemplo, aqui usei o programa muito simples "[Giftrans](http://www.ict.griffith.edu.au/anthony/software/#giftrans)" para informar quantas tabelas de cores de quadro foram criadas.

  giftrans -L speed.gif 2>&1 | grep -c "Local Color Table:"

[IM Text]

Para uma animação totalmente coalescida (ou parecida com uma tira de filme), ter tabelas de cores separadas para cada quadro é perfeitamente adequado e razoável e, em tais situações, isso não é um problema. Ou seja, para apresentações de slides de imagens muito diferentes, tabelas de cores separadas produzirão o resultado de melhor aparência. Por isso, este é o comportamento normal de trabalho do IM. Todas essas tabelas de cores extras são, contudo, muito custosas, pois cada tabela de cores pode usar muito espaço. Até 768 bytes (256 cores × 3 bytes por cor, ou 3/4 de quilobyte) para cada quadro da imagem. Não só isso, mas a compressão do GIF não comprime essas tabelas de cores, apenas os dados de pixel! Se dedicar tanto espaço de arquivo a tabelas de cores separadas for um problema, especialmente para uma imagem que não muda muito de cor, como é o caso da maioria das animações GIF, então você pode fazer o IM usar apenas a tabela de cores global necessária, sem adicionar tabelas de cores locais. ---Para remover os mapas de cores locais, todas as imagens precisam se tornar do tipo paleta e usar todas a mesma paleta. Na linha de comando, você pode fazer isso definindo um "-map image" para definir a paleta do comando. Você não pode usar -colors, pois isso funciona sobre imagens individuais. A solução de linha de comando é uma opção especial "[+map](https://imagemagick.org/command-line-options/#map)", que faz uma redução global de cores para uma paleta comum que é adicionada a todas as imagens. NOTE que qualquer mudança na imagem provavelmente invalidará a paleta, de modo que, embora a redução de cores deva ser feita ANTES de você fazer as otimizações de quadros e/ou de compressão do GIF, a paleta comum precisa ser a última, logo antes de salvar. Se "[+map](https://imagemagick.org/command-line-options/#map)" não precisar reduzir o número de cores em uma imagem, ele não o fará nem pontilhará as cores, apenas adicionará uma paleta comum a todas as imagens. --- O IM pode gerar uma única tabela de cores global, se todos os quadros usarem a mesma paleta de cores. No IM, as paletas de cores só são atribuídas a uma imagem lendo-as de um formato de imagem que use tal paleta, ou atribuindo uma a ela usando o operador de redução de cores "[-map](https://imagemagick.org/command-line-options/#map)". Veja Pontilhar com Mapa de Cores Predefinido para mais detalhes. Uma maneira de gerar essa tabela de cores única é simplesmente "[-append](https://imagemagick.org/command-line-options/#append)" (concatenar) todos os quadros juntos e, em seguida, usar o comando "[-colors](https://imagemagick.org/command-line-options/#colors)" para reduzir o número de cores a um conjunto mínimo (menos de 256, ou menor se você quiser uma tabela de cores ainda menor). A tabela de cores resultante pode então ser aplicada à imagem original usando "[-map](https://imagemagick.org/command-line-options/#map)". Por exemplo, aqui reduzimos a imagem a um único conjunto de 64 cores. Isto usa o especial registro em memória MPR para atribuir o mapa de cores gerado ao comando "[-map](https://imagemagick.org/command-line-options/#map)". |

  magick speed.gif \
          \( -clone 0--1 -background none +append \
              -quantize transparent  -colors 63  -unique-colors \
             -write mpr:cmap    +delete \) \
          -map mpr:cmap      speed_cmap.gif

[IM Output]
Agora, se você examinar a animação resultante usando "[Giftrans](http://www.ict.griffith.edu.au/anthony/software/#giftrans)", verá que a imagem agora usa uma única tabela de cores 'global', em vez de uma tabela de cores separada para cada quadro. | _Uso uma cor "[-background](https://imagemagick.org/command-line-options/#background)" de 'None' antes de concatenar as imagens, o que lhe permite usar isto em animações não coalescidas, sem a possibilidade de adicionar cores extras desnecessárias.

A configuração especial "[-quantize](https://imagemagick.org/command-line-options/#quantize)" com o espaço de cor 'transparent' foi usada para garantir que o IM não tente gerar cores semitransparentes em seu mapa de cores. Algo inútil, já que estamos salvando o resultado em GIF, que não consegue tratar a semitransparência.

Por fim, reduzo as cores para 63, para deixar espaço para uma cor transparente. Algumas animações precisam de transparência, enquanto outras (como esta) ainda podem precisar dela mais tarde para Otimização de Compressão._
---|---
Para facilitar isso, o IM também oferece uma opção especial "[+map](https://imagemagick.org/command-line-options/#map)" que gera um mapa de cores comum (de 256 cores) sobre todos os quadros, aplicando-o globalmente. Isto é muito mais simples do que o método manual acima. |

  magick speed.miff  -alpha off +map   speed_map.gif

[IM Output]
Isto resultou em [IM Text] tabelas de cores 'locais' (ou extras e indesejadas) na imagem resultante. Usarei a versão de tabela de cores única da animação para as próximas seções de otimização, embora você pudesse, na verdade, fazer isto em qualquer ponto de suas otimizações de animação e, especialmente, antes do salvamento final. Como resultado da otimização da tabela de cores, a animação, que tinha [IM Text] bytes para o nosso GIF convertido diretamente, agora tem [IM Text] bytes, depois de usar o operador "[+map](https://imagemagick.org/command-line-options/#map)". Quanto mais quadros (e 'tabelas de cores locais') uma animação tiver, maior a economia. Ora, como qualquer modificação em uma animação geralmente remove a paleta salva de cada uma das imagens, é importante que o operador "[+map](https://imagemagick.org/command-line-options/#map)" seja a última operação antes de salvar a animação em GIF. Lembre-se:

A remoção dos mapas de cores locais deve ser a última otimização, antes de salvar em formato GIF.

Pontilhamento Ordenado, removendo a 'estática'

Em Construção

Note, contudo, que em todas as técnicas que examinamos até aqui, todas podem ter um padrão de pontilhamento que muda de uma sobreposição para outra. Uma agitação dos pixels que pode parecer estática de TV.

... pequeno número de cores ...

Com uma otimização de quadros de uma área menor e imóvel, você pode até obter áreas retangulares de estática que ficam ainda piores. ... Pontilhamento Ordenado ... Por ora, consulte o mais prático e menos detalhado Vídeo para GIF, Resumo de Otimização.


Otimização de Compressão

Uma vez que você tenha salvado sua animação em formato GIF, tratando os pixels semitransparentes e usando otimizações de cor e de quadros, você também consegue obter algumas reduções menores no tamanho do arquivo atendendo ao algoritmo de compressão do GIF. A compressão LZW ou a compressão Run-length que o formato de arquivo GIF pode usar comprime melhor se encontrar áreas maiores de cor constante, ou sequências de pixels que se repetem repetidamente.

Otimização de Transparência

Como você viu na Otimização de Quadros, uma imagem sobreposta muitas vezes apenas repete o que já está sendo exibido. Ou seja, ela sobrepõe os mesmos pixels coloridos que já estão presentes depois de aplicados os métodos de supressão do GIF. Mas por que se dar ao trabalho de repetir esses pixels? Se você já está usando transparência em uma imagem, tem uma cor de pixel transparente disponível. Ao converter essas áreas em transparência, você obtém áreas maiores de pixels transparentes uniformes. Isso pode comprimir melhor do que usar uma mistura de cores diferentes, necessária para corresponder à mesma área sendo sobreposta. Por exemplo, aqui está uma simples Animação de Sobreposição Otimizada por Quadros [IM Output] [IM Output]
Vamos agora usar o método '**OptimizeTransparency**' de "[-layers](https://imagemagick.org/command-line-options/#layers)" (Adicionado no IM v6.3.4-4) para substituir por transparência qualquer pixel que não altere o resultado exibido.
  magick bunny_bgnd.gif -layers OptimizeTransparency \
                                    +map   bunny_bgnd_opttrans.gif
  gif_anim_montage bunny_bgnd_opttrans.gif bunny_bgnd_opttrans_frames.gif

[IM Output]
[IM Output]
Como você pode ver, os subquadros agora têm grandes áreas transparentes, que não afetam a animação final resultante. As áreas que precisam ter os pixels alterados ainda são sobrepostas, mas as áreas que não mudam foram tornadas transparentes. Isso inclui também o interior do objeto sendo animado, deixando 'buracos' de aparência bastante horrível. Como as áreas maiores de cor transparente constante (em teoria) comprimem melhor, a animação 'bagunçada' resultante é bem menor, reduzindo o tamanho do arquivo do resultado otimizado por quadros, de [IM Text] bytes para [IM Text] bytes. Esta é uma economia bem grande para um esforço muito pequeno. Note que o método de otimização não precisou ser uma Animação Coalescida, e que o tamanho dos subquadros é mantido inalterado, de modo a preservar as necessidades de supressão deste quadro e dos posteriores. Assim, qualquer economia se dá apenas em termos de melhores taxas de compressão para o mesmo número de pixels na animação, e não no número real de pixels salvos no arquivo. Portanto, isto deve ser feito depois de você concluir qualquer Otimização de Quadros necessária, como um de seus passos finais de otimização.

FUTURE: link para 'remover fundo' de uma animação

É claro que, como a maioria dos outros métodos de "[-layers](https://imagemagick.org/command-line-options/#layers)" (comparação ou otimização), você pode especificar um Fator de Fuzz para ajustar 'quão parecidas' as cores são consideradas. Isso lhe permite tratar animações que foram mal pontilhadas em cor, embora, se você tivesse estudado a Otimização de Cores acima, não deveria ter esse problema. A ferramenta livre de GIF animado "**[InterGIF](http://utter.chaos.org.uk/~pdh/software/intergif.htm)**" também oferece esse mesmo tipo de otimização de compressão por transparência mostrada acima, mas sem a capacidade de também suportar um 'fator de fuzz' para tornar transparentes também mudanças de cor 'próximas'. Não a recomendo, exceto como alternativa quando o IM não estiver disponível.

Otimização LZW - (fora do IM)

Algumas aplicações conseguem otimizar ainda mais a taxa de compressão das imagens em uma animação, tornando-as ainda menores. Contudo, fazer isso exige um conhecimento especializado da compressão LZW que o formato de arquivo de imagem GIF normalmente usa. Basicamente, se uma sequência específica de pixels já foi tratada pelo algoritmo de compressão LZW, ele não se dará ao trabalho de torná-la em pixels transparentes, pois fazê-lo não melhoraria a compressão das imagens. Parece estranho, mas funciona. Infelizmente, o ImageMagick não faz isso, pois é um processo tão complexo que exige muita habilidade e recursos para obter uma heurística razoavelmente boa que produza um bom resultado no caso geral. Posso, contudo, lhe dar um exemplo prático dessa técnica usando a aplicação "[Gifsicle](http://www.lcdf.org/gifsicle/)" em seu nível de otimização mais alto, '-O2'. |

  gifsicle -O2 bunny_bgnd.gif -o bunny_bgnd_lzw_gifsicle.gif
  gif_anim_montage bunny_bgnd_lzw_gifsicle.gif bunny_bgnd_lzw_frames.gif

[IM Output]

[IM Output]

A otimização de compressão LZW reduziu a imagem de [IM Text] bytes com a otimização de transparência simples, para [IM Text] bytes com o "Gifsicle". Não é uma grande melhora. O aspecto mais importante, porém, é que, embora a otimização LZW tenha convertido pixels inalterados em transparência (como fizemos usando a Otimização de Transparência acima), ela não alterou uma sequência de pixels que já havia sido vista. Ou seja, apenas grupos de pixels que não haviam se repetido dentro da animação foram alterados, pois esses pixels (presumivelmente) já comprimiriam bem usando os padrões de compressão LZW. Note que a seleção de quais pixels devem ser tornados transparentes, para gerar padrões de pixels repetidos, é muito complexa e difícil, podendo até depender da implementação exata do LZW. É uma heurística, não um algoritmo perfeitamente previsível. Por isso, programas diferentes geralmente produzirão resultados diferentes, dependendo da imagem específica sendo comprimida. Um programa pode produzir uma taxa de compressão melhor para uma imagem, e outro pode ser melhor para uma imagem diferente.

Otimização LZW com Perdas - (fora do IM)

Outro método de melhoria da compressão envolveu a modificação ligeira das próprias cores dos pixels para 'correspondências de cores próximas', de modo a aumentar a repetição das referências de cor na imagem. Um padrão repetido naturalmente comprime melhor e, por isso, pode produzir taxas de compressão mais altas. Uma bifurcação da aplicação "Gifsicle" anterior, conhecida como giflossy, também gera um programa 'gifsicle', mas com a opção de modificar a imagem de maneiras menores (é 'com perdas') para reduzir bem mais o tamanho das imagens GIF, especialmente em animações. | |

  gifsicle -O3 --lossy=80 bunny_bgnd.gif -o bunny_bgnd_giflossy.gif
  gif_anim_montage bunny_bgnd_giflossy.gif bunny_bgnd_lossy_frames.gif

[IM Output]

[IM Output]


Created: 22 March 2007 ((sub-division of "animation")
Updated: 23 April 2007
Author: Anthony Thyssen, Anthony.Thyssen@gmail.com
Examples Generated with: [version image]
URL: https://usage.imagemagick.org/anim_opt/

Isto resultou em um tamanho de [IM Text], uma incrível redução de 1/3 no tamanho. Infelizmente, esse método envolveu alterar a imagem resultante e, por isso, a otimização é com perdas, pois pode perder informações sutis de cor. Do lado positivo, ela permite comprimir os quadros individuais, em vez da otimização de quadro para quadro. Aqui, por exemplo, gerei uma imagem de diferença da compressão LZW sem perdas anterior contra uma compressão LZW com perdas. |

  magick compare bunny_bgnd_lossy_frames.gif bunny_bgnd_lzw_frames.gif \
          bunny_bgnd_diff_frames.gif

[IM Output]

Como você pode ver, quase todas as modificações de cor foram na imagem de fundo de 'grama' original, e não no coelho de desenho animado. Basicamente, ela modificou as coisas apenas o suficiente para fazer uma enorme diferença e, para esta imagem, sem uma diferença real perceptível na aparência. É claro que a Quantização de Cor e Pontilhamento é, ela mesma, uma operação com perdas e geralmente é necessária de qualquer forma; portanto, usar um método de compressão com perdas para imagens GIF, e animações GIF, não é considerado tão ruim. Outro exemplo desse tipo de algoritmo, que foi patenteado para uso pelo Photoshop, veja aUS Patent 7031540 - Transformation to increase the lempel-ziv compressibility of images with minimal visual distortion. É uma leitura densa, mas detalha os métodos que ela usa para obter melhor compressão.

Otimização LZW com Pontilhamento Ordenado

Como o processo de pontilhamento costuma ser um processo com mais perdas do que as otimizações LZW, uma solução melhor pode ser tentar introduzir os padrões repetíveis como parte do processo de pontilhamento. Isso pode ser alcançado usando Pontilhamento Ordenado para produzir tais padrões e, assim, economias de compressão LZW muito mais fortes do que todos os métodos anteriores de Otimização LZW. Como bônus, isso também pode melhorar a Otimização de Quadros de animações da vida real com fundos estáticos. Isso seria especialmente verdadeiro se você limpasse artificialmente o fundo, de modo que ele de fato se tornasse um fundo estático e imutável. É claro que a Otimização de Compressão por Pontilhamento Ordenado só funciona para imagens que ainda não foram pontilhadas ou de outra forma otimizadas em cor. Por isso, ela só funciona para animações que ainda não foram otimizadas para o formato de imagem GIF. Além disso, atualmente o pontilhamento ordenado do IM só funciona para uma paleta de cores uniforme. O IM ainda não tem uma implementação de pontilhamento ordenado com paleta de 'melhores cores' ou 'fornecida pelo usuário', embora eu tenha visto programas que usam tal algoritmo para paletas de cores muito limitadas (e fixas). Você conhece algum algoritmo assim? Para um exemplo prático de uso do pontilhamento ordenado para melhorar a otimização de compressão LZW, veja Vídeo com Pontilhamento Ordenado.

Outras Otimizações LZW

Outras melhorias na otimização LZW também podem ser alcançadas por outros rearranjos do 'padrão de pontilhamento' na imagem. E algumas ferramentas de GIF conseguem fazer exatamente isso. Contudo, qualquer otimização desse tipo deve sempre ser verificada por um olho humano antes de ser aprovada, pois às vezes podem resultar mudanças de cor sutis, porém ruins.

Resumo da Otimização de Compressão

Aqui está um resumo completo dos tamanhos finais de arquivo alcançados usando otimizações de compressão.

[IM Text]

Como você pode ver, apenas leves melhorias no tamanho final da animação foram alcançadas usando a muito complexa Otimização LZW, em relação à Otimização de Transparência embutida. Contudo, os resultados também são altamente variáveis entre os muitos programas de aplicação de otimização de GIF disponíveis, e a animação específica sendo otimizada. Se você realmente precisa extrair até o último byte de um arquivo, então uma Otimização LZW pode ser exatamente o que você precisa. E, se você realmente precisa dos melhores resultados possíveis, deve tentar vários programas diferentes (e, portanto, implementações heurísticas) para ver qual deles comprime melhor sua animação específica, incluindo quais outros recursos de otimização eles oferecem. Normalmente, uma Otimização de Transparência é boa o suficiente para a maioria dos propósitos. Com a Otimização LZW produzindo apenas um resultado ligeiramente melhor, gerando uma economia muito pequena para tamanhos de transmissão em rede, e não para o tamanho de armazenamento em disco, pois este último usa 'blocos' ou 'trechos' de armazenamento maiores. Por causa disso, considero a Otimização LZW um exagero e não acho que valha o esforço, nem o dinheiro (a maioria dessas ferramentas é vendida comercialmente). | _Infelizmente, descobri que esses otimizadores de GIF não tratam TODOS os tipos de animações pré-otimizadas muito bem.

Por exemplo, meus testes mostram que o "[Gifsicle](http://www.lcdf.org/gifsicle/)" não trata uma animação que já foi otimizada usando uma técnica de 'supressão background'.

Por outro lado, descobri que o "[InterGIF](http://www.chaos.org.uk/~pdh/software/intergif.htm)" não trata animações que já foram otimizadas para usar uma tela inicial e a técnica de 'supressões previous'. Ele também se limita ao uso da Otimização de Transparência, que o IM agora oferece.

Por isso, recomendo que você não misture utilitários de otimização de GIF alimentando a saída de um utilitário em outro. Ao menos não sem primeiro coalescer a animação para remover quaisquer otimizações de quadro anteriores.

IM, Gifsicle e InterGIF, todos oferecem tais opções de coalescência para remover suas próprias otimizações, embora eu não possa garantir que as aplicações fora do IM coalescerão TODAS as animações corretamente. O IM o fará.

_
---|---
Como você não pode usar esses programas de forma confiável com as avançadas técnicas de Otimização de Quadros do IM (que selecionam e alternam automaticamente para o uso de diferentes técnicas de supressão do GIF), muitas vezes descobri que o IM produzirá com frequência um resultado geral melhor do que apenas usar esses otimizadores de compressão LZW. Sugiro também que você Coalesce o resultado novamente depois e compare seus quadros com a animação original não otimizada, para garantir que o programa fora do IM não estragou de alguma forma a animação por inteiro (veja a nota acima). Acredite, já vi acontecer, e os scripts deveriam verificar duas vezes se as animações continuam válidas.
Outro tutorial (usando ferramentas do Windows) sobre esse tipo de otimização é o WebReference Frame Optimation. Note que o site tem nome equivocado, pois trata de otimização de compressão.


Otimizações Menores

Há algumas outras técnicas de otimização que você pode usar com animações GIF e que muitas vezes são tão óbvias que passam despercebidas.

  • Remova os comentários do GIF.
    Muitas animações GIF têm um grande comentário de texto adicionado. Muitas vezes, eles foram adicionados automaticamente por editores gráficos como uma forma de publicidade. Por exemplo, o "Gimp" por padrão adiciona "Created with The GIMP" às imagens. Se o comentário não for necessário, ele é um desperdício de espaço. Remova-os adicionando um operador "[+set](https://imagemagick.org/command-line-options/#set) comment" ao comando "magick" do IM antes de o GIF ser salvo. Note, porém, que, se o comentário for um aviso de direitos autorais, pode não ser uma boa ideia removê-lo por razões legais.
  • Reduza o número de cores.
    Se a animação ficar bem com menos cores, use uma tabela de cores menor. As tabelas de cores são sempre uma potência de dois, então, se você conseguir usar menos de 32 cores, isso é muito menor do que usar 256 cores. Isto é especialmente importante, pois as tabelas de cores não são comprimidas pela compressão LZW usada para os dados de imagem do GIF. Além disso, usar menos cores geralmente produzirá melhor compressão LZW, pois mais sequências comuns de pixels são encontradas. Nem sempre é o caso, contudo, pois o pontilhamento de cor (devido à redução de cores) também pode piorar a compressão. Desligar o pontilhamento ou usar um pontilhamento ordenado pode ser importante aqui.
  • Reduza pela metade o número de quadros visíveis ao usuário.
    Se você aceitar uma animação menos suave, então reduzir pela metade o número total de quadros pode produzir uma boa melhoria no tamanho final do arquivo. É claro que você não obtém um arquivo com metade do tamanho, e a qualidade da animação é reduzida. Mas isso pode produzir uma redução muito grande no tamanho do arquivo.
  • Recorte/Redimensione a animação.
    Um tamanho de imagem menor significa um tamanho de arquivo menor. Portanto, se você não precisa de uma animação grande, não use uma animação grande. Uma pequena miniatura para representar uma animação ou vídeo maior é muitas vezes preferível, em uma listagem, ao objeto real.
  • Compressões Alternativas.
    Se você não pretende usar a animação como uma animação, ou seja, só quer armazená-la, desligue a compressão LZW e comprima o arquivo INTEIRO com "gzip" ou "bzip2" para armazenamento! O resultado é bem menor, embora exija que os servidores web deem as dicas corretas de 'conteúdo' e 'compressão' aos navegadores para que ele seja diretamente utilizável pelos navegadores cliente. O servidor web "Apache" não faz isso por padrão, mas pode ser configurado para fazê-lo. Melhor ainda, arquive o diretório inteiro de animações não comprimidas em um único arquivo, para uma compressão de armazenamento ainda melhor.

Se você tiver quaisquer outras ideias de otimização, por favor, me avise.


Outras Fontes de Informação sobre Otimização de GIF

O exposto acima completa os vários métodos e técnicas básicos para tratar animações. Contudo, para formar um quadro completo, você deve continuar para a próxima página dos exemplos do IM, que detalha técnicas para tratar problemas reais com Animações de Imagens reais. Além disso, muitas das técnicas acima são demonstradas nos exemplos práticos de Otimização de Vídeo para GIF. Recomendo também que você leia atentamente sobre Quantização de Cor, se você leva realmente a sério o trato com animações GIF, pois a redução de cores é muitas vezes a chave para um bom tratamento de animação GIF. Outras fontes úteis de técnicas de Otimização de Animação GIF que encontrei na WWW incluem…

Escreva-me se você achar que tem uma página que eu deveria listar aqui. Só adicionarei páginas de conteúdo útil, então não há garantias de que seu link será adicionado.