## 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.')