Criando imagens em Python

pillow-1_abertura

O primeiro programa de computador que escrevi copiei era algo que desenhava triângulos na tela e talvez seja este o motivo da minha predileção em escrever programas que desenham e não escrevam coisas na tela¹. E em Python é possível criar, carregar, converter ou mesmo modificar imagens sem muito esforço utilizando a biblioteca Pillow — ela é um fork da PIL da qual herdou o nome do módulo — e que permite fazer coisas muito interessantes.

(¹) Aliás um dos primeiros programas que escrevi em Python foi um simulador do MC6847 da Motorola usando PyGame (mas isto é assunto pra outra publicação).

Instalação

A documentação do projeto contém instruções detalhadas de como fazê-lo mas na maioria das distribuições Linux ela está inclusa por padrão nas dependências do próprio Python. Porém, caso opte por trabalhar dentro do virtualenv, será necessário instalá-la, então…

$ pip install pillow

Ao menos precisei fazê-lo aqui no Ubuntu 19.10.

Teste rápido

Sem muita enrolação, um teste simples e prático…

from PIL import Image

WIDTH, HEIGHT = 1024, 512
FILENAME = ("teste_pillow.png", "PNG")

pillow_obj = Image.new("RGB", (WIDTH, HEIGHT))
pixel_set = pillow_obj.load()

for row in range(HEIGHT // 2):
    for col in range(WIDTH // 2):
        color = (row, abs(col - row), col)
        rev_col, rev_row = WIDTH - col - 1, HEIGHT - row - 1
        pixel_set[col, row] = color
        pixel_set[rev_col, row] = color
        pixel_set[col, rev_row] = color
        pixel_set[rev_col, rev_row] = color

pillow_obj.save(*FILENAME)

Até pensei em procurar uma rotina para desenho de fractais², mas me contive, e este exemplo ficou bem mais simples e curto também.

O resultado…

pillow-1_imagem-de-teste

Agora as explicações importantes.

  1. A primeira linha carrega a biblioteca, em seguida são definidas constantes para armazenar as dimensões e também o nome do arquivo. Daí o objeto Image é instanciado em pillow_obj em modo RGB e resolução de 1024×512 pixeis.
  2. A parte principal, é a variável pixel_set, que recebe um array com as mesmas dimensões da imagem, com cada pixel correspondendo a uma tupla de três valores que identificam as quantidades de vermelho, verde e azul dele.
  3. Os dois laços, usando row e col, cuidam da atribuição das cores para cada um dos pixeis do primeiro quarto da tela (canto superior esquerdo) e também de espelhá-los nos demais.
  4. E por último o método save() se encarrega salvar a imagem em disco usando o formato PNG.

(²) As pessoas gostam de ver fractais.

Conversão entre formatos

Que tal converter uma imagens de um formato para outro? E tão simples que pode ser feito diretamente pelo console…

Python 3.7.5 (default, Nov 20 2019, 09:21:52) 
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image
>>> Image.open("teste_pillow.png").save("teste_pillow.tiff")

E assim converter facilmente a imagem do primeiro exemplo de PNG para Tiff (mas também poderia ser JPEG).

Editando imagens

pillow-1_abertura

Também é possível editar o arquivo de uma imagem já existente para criar outra.

from PIL import Image

FILENAME = ("outro_teste_pillow.png", "PNG")

pillow_obj = Image.open("teste_pillow.png")
pixel_set = pillow_obj.load()
width = pillow_obj.width
height = pillow_obj.height

for row in range(height // 2):
    for col in range(width // 2):
        r, g, b = pixel_set[col, row]
        pixel_set[col, row] = (b, g, r)
        pixel_set[rev_col, rev_row] = (b, g, r)

pillow_obj.save(*FILENAME)

É um reaproveitamento do primeiro programa e a diferença aqui é o uso do método open() — ao invés do new() — que cuida de converter o arquivo e permitindo que ele seja editado no mesmo sistema das tuplas e aí pode-se fazer qualquer coisa!

No caso é a modificação do arranjo nos componentes RGB dentro da imagem mas somente nos cantos superior esquerdo e inferior direito dela. Aliás, você testar este programa com qualquer outro arquivo e ver o que acontece!

Também é possível também aplicar transformações como rotação ou espelhamentos horizontal e vertical nas imagens.

Finalizando

pillow-1_fractal

Além de recursos para criação e transformação o Pillow possui também funcionalidades que permitem cortar, redimensionar, aplicar filtros etc e vale a pena consultar a documentação do módulo para conhecer o que ele tem disponível,

E como não resisti, incluí um fractal! Os arquivos usados aqui encontram-se no repositório git do blog e, de brinde, aproveitei para escrever um gerador de fractais usando como base algo feito em MSX-BASIC há alguns anos! 🙂