Exemplos de ImageMagick -- Anti-Aliasing
- Exemplos de ImageMagick: Prefácio e Índice
- Introdução ao Anti-Aliasing
- Desenhando Apenas com Cores Específicas
- Desenhando Círculos Finos em Bitmap
- Problemas de Anti-Aliasing e Preenchimento por Inundação
O anti-aliasing é uma parte importante de todas as operações de desenho no ImageMagick. Infelizmente, ele também pode causar muitos problemas. Esta página procura abordar esses problemas e apresentar soluções para eles.
Introdução ao Anti-Aliasing O ImageMagick, ao desenhar imagens, faz isso de uma maneira muito particular. Ele as desenha com uma operação chamada "anti-aliasing". Para demonstrar, desenha-se uma imagem sobre um fundo transparente e, em seguida, amplia-se uma pequena parte dela para que se possa ver o que está acontecendo.
magick -size 80x80 xc:none \
-fill white -draw "circle 40,40 15,20" \
-fill black -draw "line 5,30 78,2" drawn.png
magick drawn.png -crop 10x10+50+5 +repage -scale 80x80 drawn_mag.png
Poder-se-ia pensar que a imagem acima teria apenas três cores, 'white', 'black' e 'transparent', pois foi só isso que se pediu ao IM para usar. Mas, como se pode ver quando a imagem é ampliada, ela possui toda uma gama de cores. Ao fazer isso, o ImageMagick deixa a imagem com uma aparência mais suave e agradável, usando uma técnica chamada 'anti-aliasing'. Esse é um termo rebuscado que significa que ele preenche os pixels das bordas do objeto com uma mistura de cores e até de transparências, para deixar o objeto com um aspecto mais suave. Se nenhum anti-aliasing fosse feito, as bordas de todos os objetos desenhados apresentariam um efeito em forma de escada chamado 'aliasing', embora seja mais comumente referido como 'serrilhado' (jaggies). Aqui a imagem é desenhada novamente, mas desta vez pediu-se ao IM para desligar suas operações automáticas de anti-aliasing, usando "[+antialias](https://imagemagick.org/command-line-options/#antialias)".
magick -size 80x80 xc:none +antialias \
-fill white -draw "circle 40,40 15,20" \
-fill black -draw "line 5,30 78,2" drawn_jaggies.png
magick drawn_jaggies.png -crop 10x10+50+5 +repage -scale 80x80 \
drawn_jaggies_mag.png
Desta vez, a imagem realmente possui apenas três cores. Mas o resultado não é nada agradável. No IM mais recente, é desenhada uma única linha de pixels, em forma de escada. Em versões mais antigas do IM, a linha também teria uma aparência bastante espessa, deixando-a ainda pior. Basicamente, isso não é algo que normalmente se deseja fazer. A escada dos efeitos de 'aliasing', também comumente chamada de 'serrilhado' (jaggies), é justamente o que o IM tentava evitar. Mas, se forem necessárias cores específicas, será preciso aceitar isso ou usar outras técnicas (como a quantização de cores) para garantir que apenas certas cores sejam usadas. Note que, na verdade, ocorrem duas formas de anti-aliasing. A primeira é uma mistura das cores branca e preta da imagem, produzindo diversos tons de cor, cinza neste caso. A outra forma é uma mistura da cor e da transparência para gerar pixels semitransparentes na imagem. Esta última é algo que se deve ter em mente, pois muitos formatos de imagem (como o GIF) não conseguem lidar com pixels semitransparentes e tornarão esses pixels totalmente opacos ou totalmente transparentes. Os exemplos em Transparência Booleana do GIF demonstram métodos pelos quais é possível controlar o tratamento dos pixels semitransparentes ao salvar em tais formatos.
Resumo
O anti-aliasing é muito importante em qualquer tipo de desenho de imagem e algo que se deve ter em mente. Sem considerar as cores misturadas e os pixels semitransparentes gerados pelo anti-aliasing do IM, as imagens que se criam podem acabar com uma aparência muito ruim em alguns formatos. Isso se torna ainda mais importante ao criar imagens em um formato que não permite pixels semitransparentes, como o difundido formato "GIF". Veja Transparência Booleana do GIF para conhecer maneiras de lidar com esse problema. O IM é muito bom em fazer anti-aliasing de cores e transparências, mas, na verdade, muito ruim em desenhar apenas pixels puramente 'aliased' (para corresponder a um mapa de cores específico, por exemplo). Foi dito que esse será o foco de uma versão futura do IM.
Desenhando Usando Apenas Cores Específicas
Em Construção
Melhores maneiras de desenhar sem anti-aliasing, para gerar imagens com cores exatas. Ou seja, para 'Imagens Indexadas'. Especificamente, desenhar sobre uma tela transparente, aplicar limiar ao canal alfa e, em seguida, sobrepor, de modo que apenas os pixels totalmente opacos sejam desenhados.
Desenhando Círculos Finos em Bitmap
Aqui examina-se a tentativa de desenhar círculos de 'linha fina' em bitmap usando o IM. Normalmente isso é feito com um algoritmo de desenho de círculos em bitmap tipicamente conhecido como algoritmo de círculo de Bresenham, mas mais corretamente conhecido como Algoritmo do Ponto Médio para Círculos. Infelizmente, ele não está disponível no ImageMagick e talvez nunca esteja, pois não é necessário em um ambiente de desenho totalmente com anti-aliasing. Outra alternativa para desenhar círculos, que será examinada em breve, é usar a Morfologia para 'Dilatar' um único pixel, empregando o especial Núcleo em Anel.
Por exemplo, a maneira normal do IM de desenhar um círculo produz muitas cores cinza de anti-aliasing para dar ao círculo uma aparência suave. |
magick -size 15x15 xc: -fill none -stroke black \
-draw 'translate 7,7 circle 0,0 5,0' \
-scale 500% circle_antialiased.gif
![[IM Output]](../static/img/antialiasing/circle_antialiased.gif)
Simplesmente desligar o anti-aliasing, porém, produz círculos e linhas que não são uma bela linha fina de 'bitmap'. |
magick -size 15x15 xc: -fill none -stroke black +antialias \
-draw 'translate 7,7 circle 0,0 5,0' \
-scale 500% circle_aliased.gif
![[IM Output]](../static/img/antialiasing/circle_aliased.gif)
O que é preciso fazer é ajustar também a "[-strokewidth](https://imagemagick.org/command-line-options/#strokewidth)", cujo padrão é 1 pixel de largura, para algo menor, como 0,5 pixel de largura. |
magick -size 15x15 xc: -fill none -stroke black +antialias \
-strokewidth 0.5 -draw 'translate 7,7 circle 0,0 5,0' \
-scale 500% circle_thin_stroke.gif
![[IM Output]](../static/img/antialiasing/circle_thin_stroke.gif)
Melhor, mas ainda não perfeito. No entanto, também é possível tornar a largura do traço pequena demais, especialmente com raios de tamanho ímpar. |
magick -size 15x15 xc: -fill none -stroke black +antialias \
-strokewidth 0 -draw 'translate 7,7 circle 0,0 5,0' \
-scale 500% circle_zero_stroke.gif
![[IM Output]](../static/img/antialiasing/circle_zero_stroke.gif)
E aqui está uma boa solução para um círculo de 5 pixels centrado em uma posição de pixel real inteira. |
magick -size 15x15 xc: -fill none -stroke black +antialias \
-strokewidth 0.4 -draw 'translate 7,7 circle 0,0 5,0' \
-scale 500% circle_perfect.gif
![[IM Output]](../static/img/antialiasing/circle_perfect.gif)
No entanto, após muitos experimentos, não foi possível encontrar nenhuma "[-strokewidth](https://imagemagick.org/command-line-options/#strokewidth)" que funcione para todos os raios e centros. Especialmente um círculo ligeiramente descentralizado.
Não há solução ideal para todas as situações
Por exemplo, este círculo, que não está centrado em um pixel nem em uma fronteira de pixel, não só apresenta lacunas na parte superior, como também fica espesso demais na parte inferior! Que feio! |
magick -size 15x15 xc: -fill none -stroke black +antialias \
-strokewidth 0.47 -draw 'translate 7,7.3 circle 0,0 5,0' \
-scale 500% circle_bad_stroke.gif
![[IM Output]](../static/img/antialiasing/circle_bad_stroke.gif)
Aqui está uma tabela de bons valores de "[-strokewidth](https://imagemagick.org/command-line-options/#strokewidth)" para gerar um círculo fino de um único pixel de largura com um raio específico. Note que o melhor valor a usar varia conforme o círculo esteja centrado em um pixel real (como ' 5 , 5 ') ou em uma fronteira de meio pixel (como ' 5.5 , 5.5 ') Raio do Círculo | SW Real | SW meio
---|---|---
1 | 0.3 | 0.3 ¶
1.5 | 0.5 ¶ | 0.3
2 | 0.3 | 0.3 §
2.5 | 0.5 ¶ | 0.3 ¤
3 | 0.3 ¤ | 0.3
3.5 | 0.5 | 0.3 ¤
4 | 0.5 § | 0.3
4.5 | 0.5 | 0.3
5 | 0.4 | 0.3
5.5 | 0.5 ¶ | 0.3
6 | 0.3 | 0.5 §
6.5 | 0.5 | 0.43
7 | 0.5 | 0.434
7.5 | 0.5 § | 0.5 §
8 | 0.4 | 0.5
¤ Círculo pequeno muito bom
§ nenhuma largura ideal encontrada
¶ círculo muito ruim
NOTA: Para centrar um círculo em uma imagem, em coordenadas de desenho (coordenadas de pixel), é (size-1)/2
Problemas de Anti-Aliasing e Preenchimento por Inundação Devido aos recursos de anti-aliasing do IM, o preenchimento por inundação ("[-draw](https://imagemagick.org/command-line-options/#threshold) color floodfill") apresenta problemas quando usado em imagens com efeitos de anti-aliasing. Ele também tem problemas semelhantes com imagens lidas a partir do formato de imagem "JPG". Basicamente, como a maioria dos objetos no IM tem anti-aliasing (ou é lida de um arquivo de imagem no formato "JPG"), as cores próximas às bordas dos objetos desenhados raramente são a cor específica que o preenchimento por inundação está sendo usado para substituir. Isso significa que o preenchimento por inundação não preencherá as bordas exatas das áreas que se tenta preencher, a menos que o anti-aliasing seja totalmente evitado. Essencialmente, o preenchimento por inundação, ou mesmo a substituição de cor, não compreende o anti-aliasing nem usa técnicas de anti-aliasing por conta própria. Consequentemente, o preenchimento por inundação geralmente deixará de fora os pixels na borda exata da área que está sendo preenchida. Por exemplo, aqui realiza-se uma operação típica de preenchimento por inundação. Desenha-se um círculo e, em seguida, tenta-se preenchê-lo com um padrão... |
magick -size 60x60 xc:lightblue -strokewidth 2 \
-fill none -stroke red -draw "circle 30,30 5,30" \
-tile tile_weave.gif -draw "color 30,30 floodfill" \
tile_fill_1.gif
magick tile_fill_1.gif -crop 10x10+35+4 +repage -scale 80x80 \
tile_fill_1_mag.gif
![[IM Output]](../static/img/antialiasing/tile_fill_1_mag.gif)
Como se pode ver na parte ampliada da imagem, uma linha de pixels de 'cor divergente' foi completamente ignorada pela operação de preenchimento por inundação, pois a cor desses pixels não era exatamente igual à da área que estava sendo preenchida. Uma maneira de melhorar isso é preencher previamente as áreas que se pretende preencher com uma cor que combine com o padrão em uso. O padrão ainda não preencherá a área por completo, mas ao menos não ficará com uma aparência tão ruim. |
magick -size 60x60 xc:lightblue -strokewidth 2 \
-fill black -stroke red -draw "circle 30,30 5,30" \
-tile tile_weave.gif -draw "color 30,30 floodfill" \
tile_fill_2.gif
magick tile_fill_2.gif -crop 10x10+35+4 +repage -scale 60x60 \
tile_fill_2_mag.gif
![[IM Output]](../static/img/antialiasing/tile_fill_2_mag.gif)
Outra forma de fazer isso é preencher a área com o padrão usando um alto Fator de Fuzz, para forçar o padrão a preencher a área completamente, até a borda exata, sem deixar de fora os pixels da borda. |
magick -size 60x60 xc:lightblue -strokewidth 2 \
-fill none -stroke red -draw "circle 30,30 5,30" \
-fuzz 35% -tile tile_weave.gif -draw "color 30,30 floodfill" \
tile_fill_3.gif
magick tile_fill_3.gif -crop 10x10+35+4 +repage -scale 60x60 \
tile_fill_3_mag.gif
![[IM Output]](../static/img/antialiasing/tile_fill_3_mag.gif)
| Note que um alto 'fator de fuzz', como este, ou uma borda fina demais, pode fazer com que o padrão de preenchimento 'vaze' da área definida. É sempre necessário algum cuidado ao usar uma operação de preenchimento por inundação. Por isso, ela não é de fato recomendada como solução geral.
---|---
O problema disso é que, como o preenchimento por inundação, por sua própria natureza, NÃO usa anti-aliasing, as bordas da área preenchida sofrem com os efeitos de 'serrilhado' (jaggies) ou de aliasing. É possível melhorar essa situação separando o desenho da imagem em etapas distintas. Crie um círculo colorido, preencha-o e depois desenhe a borda. |
magick -size 60x60 xc:lightblue -fill black -draw "circle 30,30 5,30" \
-tile tile_weave.gif -draw "color 30,30 floodfill" +tile \
-fill none -stroke red -strokewidth 2 -draw "circle 30,30 5,30" \
tile_fill_4.gif
magick tile_fill_4.gif -crop 10x10+35+4 +repage -scale 60x60 \
tile_fill_4_mag.gif
![[IM Output]](../static/img/antialiasing/tile_fill_4_mag.gif)
Esta é uma maneira simples de melhorar o preenchimento por inundação. Outra é usar uma sobreposição com forma definida, mas esse pode ser um método complicado de resolver. Mais adiante serão examinadas modificações semelhantes em imagens existentes. É claro que, se a própria área a ser preenchida por inundação estiver sendo desenhada e não se estiver usando uma imagem existente, a solução ideal seria evitar o preenchimento por inundação especificando o padrão de preenchimento na operação de desenho original. |
magick -size 60x60 xc:lightblue -strokewidth 2 \
-tile tile_weave.gif -stroke red -draw "circle 30,30 5,30" \
tile_fill_5.gif
magick tile_fill_5.gif -crop 10x10+35+4 +repage -scale 60x60 \
tile_fill_5_mag.gif
FUTURO: problemas de anti-aliasing em imagens já existentes (especialmente no formato JPG).
Por exemplo, recolorir e sobrepor uma imagem de texto ou diagrama sobre uma cor
ou um fundo.
Também readicionar transparência a arquivos GIF e a JPEGs reescalonados para uso como ícone.
**Suavização ou anti-aliasing de imagens com conjunto de cores limitado**
Especificamente imagens em bitmap (preto e branco puros).
Primeiro, o anti-aliasing não funciona em imagens em bitmap.
O anti-aliasing envolve usar uma mistura de cores e transparências para tentar
suavizar o efeito de 'escada' ou 'serrilhado' de linhas inclinadas e fronteiras
de cor. Se apenas duas cores estiverem disponíveis, o anti-aliasing NÃO pode ocorrer!
A imagem precisa ser convertida, no mínimo, de P&B ou tons de cinza antes de
o anti-aliasing poder ser usado.
Uma maneira simples de suavizar as bordas é usar uma pequena quantidade de desfoque após ler
uma imagem em P&B ou uma imagem com uma paleta de tamanho minúsculo.
EG: magick image.xbm -blur 0x.3 smoothed_image.png
![[IM Output]](../static/img/antialiasing/drawn.png)
![[IM Output]](../static/img/antialiasing/drawn_mag.png)
![[IM Output]](../static/img/antialiasing/drawn_jaggies.png)
![[IM Output]](../static/img/antialiasing/drawn_jaggies_mag.png)
![[IM Output]](../static/img/antialiasing/tile_fill_5.gif)
![[IM Output]](../static/img/antialiasing/tile_fill_5_mag.gif)