---
# System prepended metadata

title: Grupo de estudos em Python - 21/5

---

## Espaço de Tecnologias e Artes - Sesc Avenida Paulista 
### `hackmd.io/@sesc-av-paulista/estudos-em-python-21-maio`
# Grupo de estudos em Python 

## 21/5 Convertendo e redimensionando Imagens

### O que eu preciso para começar?

- Vamos usar o **Thonny IDE**, que é livre já com um interpretador Python, você pode baixar em https://thonny.org
- Como instalar bibliotecas no Thonny?
    - **Usando a interface gráfica** menu *Tools/Ferramentas > Manage Packages/Gerenciar Pacotes*
    - **Usando o shell aberto pelo Thonny** em *Tools > Open System Shell*
        - Como se faz em geral no Python: `pip install <nome da lib>`, mas idealmente você deve usar um "virtual environment" antes, só que no caso do Thonny provê já esse env

### Algumas bibliotecas

- Pillow - Python Image Library - PIL (Fork)
    - https://pypi.org/project/pillow/
    - [Documentação oficial](https://pillow.readthedocs.io/en/stable/)
    
### Exemplos


#### Convertendo PNGs em JPGs em uma pasta

Salva arquivos convertidos na mesma pasta que os originais.
obs: pode não reconhecer alguns .png salvado da web.

```python=
from tkinter.filedialog import askdirectory
from pathlib import Path

from PIL import Image

# Abre uma janela para selecionar uma pasta
string_pasta = askdirectory()  # '' se for cancelada a seleção
if string_pasta:  # só executa se a pasta foi selecionada
    caminho_pasta = Path(string_pasta)
    # iterando pela pasta escolhida
    for caminho_arquivo in caminho_pasta.iterdir(): 
        if caminho_arquivo.suffix == '.png': # checa sufixo .png
            # constroi path de saída 
            caminho_saida = caminho_pasta / (caminho_arquivo.stem + '.jpg')
            try:  # bloco try, pra se der problema ...
                with Image.open(caminho_arquivo) as im:  # carrega imagem
                    im.save(caminho_saida)  # salva imagem
                    print(f'Salvei {caminho_saida.name}')
            except OSError:  # ... trata exceção 
                print(f'Não foi possível converter {caminho_arquivo}!')
    print('Terminei de olhar a pasta!')
else:
    print('Cancelado!')

```

### Gerador de thumbnails

Cria uma pasta nova ao lado da original escolhida, acrescentando "_thumbs" no nome.
obs: percorre toda a pasta selecionada salvando arquivos de imagem em thumbnails. Gera imagens com tamanho diferentes.

```python=
from tkinter.filedialog import askdirectory
from pathlib import Path

from PIL import Image

# Abre uma janela para selecionar uma pasta
string_pasta = askdirectory()  # '' se for cancelada a seleção
if string_pasta:  # só executa se a pasta foi selecionada
    caminho_pasta = Path(string_pasta) # transforma  str em objeto Path
    # constroi caminho para a pasta de saída com '_thumbs' no final do nome
    caminho_thumbs = caminho_pasta.parent / (caminho_pasta.name + '_thumbs')
    caminho_thumbs.mkdir(exist_ok=True) # cria pasta, ok se já existir
    # iterando pela pasta escolhida com as imagens
    for caminho_arquivo in caminho_pasta.iterdir(): 
            # constroi path de saída 
            caminho_saida = caminho_thumbs / caminho_arquivo.name 
            # bloco try, pra se der problema ... vai pular o que não for imagem
            try:  
                with Image.open(caminho_arquivo) as im:  # carrega imagem
                    largura_maxima = 25
                    altura_maxima = 255
                    im.thumbnail((largura_maxima, altura_maxima))
                    im.save(caminho_saida)  # salva imagem
                    print(f'Salvei {caminho_saida.name}')
            except OSError:  # ... trata exceção 
                print(f'Não foi possível criar thubnail de {caminho_arquivo}!')
    print('Terminei de olhar a pasta!')
else:
    print('Cancelado!')


```

### Convertendo um arquivo em grayscale
obs: Selecione um arquivo por vez
```python=
from tkinter.filedialog import askopenfilename
from pathlib import Path

from PIL import Image

# Abre uma janela para selecionar um arquivo só numa pasta
string_arquivo = askopenfilename() # '' se cancelada
if string_arquivo:  # só executa se a arquivo foi selecionad0o
    caminho_arquivo = Path(string_arquivo) # transforma  str em objeto Path
    novo_nome = caminho_arquivo.stem + '_alterado' + caminho_arquivo.suffix
    caminho_saida = caminho_arquivo.parent / novo_nome
    try:
        with Image.open(caminho_arquivo) as im:  # carrega imagem
            # converte em grayscale ('LA' preserva alpha, mas não rola em JPG por exemplo)
            convertida = im.convert('L') 
            convertida.save(caminho_saida)  # salva imagem 
            print(f'Salvei {caminho_saida.name}')
    except Exception as erro:  # ... trata exceção 
        print(erro)

```

### Convertendo um arquivo em rgb
obs: Selecione um arquivo por vez

```python=
from tkinter.filedialog import askopenfilename
from pathlib import Path

from PIL import Image

# Abre uma janela para selecionar um arquivo só numa pasta
string_arquivo = askopenfilename() # '' se cancelada
if string_arquivo:  # só executa se a arquivo foi selecionad0o
    caminho_arquivo = Path(string_arquivo) # transforma  str em objeto Path
    novo_nome = caminho_arquivo.stem + '_alterado' + caminho_arquivo.suffix
    caminho_saida = caminho_arquivo.parent / novo_nome
    try:
        with Image.open(caminho_arquivo) as im:  # carrega imagem
            rgb2xyz = (
    0.412453, 0.357580, 0.180423, 0,    # vermelho 0 A 255 / Ultimo parametro opacidade
    0.212671, 0.715160, 0.072169, 0,    # verde 0 A 255
    0.019334, 0.119193, 0.950227, 0)    # azul 0 A 255
            convertida = im.convert("RGB", rgb2xyz) # converte em RGB
            convertida.save(caminho_saida)  # salva imagem
            print(f'Salvei {caminho_saida.name}')
    except Exception as erro:  # ... trata exceção 
        print(erro)
```

### PNGs -> GIF usando `imageio`

Este script para rodar na linha de comando converte PNGs em um pasta em um GIF usando a biblioteca `imageio`

- https://pypi.org/project/imageio/

Importante: todos os PGNs precisam ter as mesmas dimensões e estar localizado no mesmo arquivo que o .py. (para ajustar as dimensções pode usar o https://www.iloveimg.com/pt/redimensionar-imagem#resize-options,pixels)

```python=
"""
Cria GIF from PNGs em um diretório/pasta!
Imagens precisam ser todas do mesmo tamanho em pixels
"""
from pathlib import Path
import argparse

import imageio

# usando argparse para definir os comandos
parser = argparse.ArgumentParser(
    prog='PNG frames to GIF animation'
    )
parser.add_argument(
    '-i', '--input',
    help='Input folder containing the PNG images'
    )
parser.add_argument(
    '-o', '--output', default='output.gif',
    help='Output GIF file name'
    )
parser.add_argument(
    '-d', '--duration', default=200, type=int,
    help='Frame duration in milliseconds',
    )
parser.add_argument(
    '-l', '--loop', default=0, type=int,
    help='Number of loops (default=0, keep looping)',
    )

args = parser.parse_args()

# define path da pasta de entrada (ou diretório atual)
input_dir = Path(args.input or Path.cwd())

if input_dir.is_dir():  # se for mesmo um diretório
    try:  # tenta fazer uma lista de imagens .png
        images = [imageio.v3.imread(file_path)
                  for file_path in sorted(input_dir.iterdir())
                  if file_path.suffix.lower() == '.png']
        if images:  # se tiver imagens na lista
            # monta caminho do arquivo de saída
            output_path = input_dir / args.output
            imageio.v3.imwrite(
                output_path,
                images,
                duration=int(args.duration),
                loop=args.loop,
                )
            print(f'Animation saved at:\n{output_path}\n')
        else:  # não tinha imagens
            print(f'No PNG images found at:\n{input_dir}')
    except Exception as e:  # algum outro erro
        if str(e).startswith('all input arrays'):
            print('Select only images of same size.')
        else:    
            print(str(e))
else:
    print(f'{input_dir}\nis not a valid input dir.')

    

