Como exportar uma imagem
Um quadro (frame) é o resultado visual produzido na área de desenho do sketch no Processing em um determinado momento. Para salvar um quadro em um arquivo bitmap/raster, como por exemplo PNG, TIF ou JPG, usamos a função save_frame()
.
Passamos como argumento o nome do arquivo que deve ser salvo, e a extensão de três letras após o ponto no nome do arquivo indica o formato que deve ser salvo. Por exemplo save_frame("imagem.jpg")
salva um arquivo JPG na pasta do sketch. Se utilizarmos alguns caracteres “#” no nome do arquivo eles serão substituídos pelo número do frame.
Um exemplo simples
O código abaixo exemplifica como salvar uma imagem PNG de um quadro. Quando uma tecla é pressionada, é executada a função key_pressed()
e se for identificada a tecla “s” (key == 's'
) é execuatada a função save_frame()
, que grava uma imagem.
def setup():
size(500, 500)
def draw():
background(0, 0, 200)
x, y = random(width), random(height)
circle(x, y, 100)
def keyPressed():
if key == 's':
save_frame('frame#####.png') # os ##### viram o número do frame no nome do arquivo
print(f'PNG do frame {frame_count} salvo')
Resulta em arquivo semelhante a este “frame421.png” na pasta do sketch:
save_frame()
dentro do draw()
Usar save_frame()
dentro do laço principal draw()
torna o sketch muito mais lento, pois salva uma imagem a cada frame do draw. Se o nome do arquivo for sempre o mesmo, ele vai ser sobreescrito, mas podemos acrescentar alguns carateres #
no nome do arquivo, que serão substitúidos pelo número do quadro, e dessa maneira, um número grande de quadros pode ser salvo em alguns segundos, o que deve ser feito com cuidado (pode entupir o disco do seu computador).
Normalmente é criada uma condição que interrompe o sketch com exit()
ou que só permite salvar um certo número de imagens (no exemplo abaixo, um quadro a cada 5 com frame_count % 5 == 0
e também fazemos um limite com frame_count <= 100
).
def draw():
# desenho
...
# salva só a cada 5 frames até o frame 100
if frame_count % 5 == 0 and frame_count <= 100:
save_frame("imagem#####.png")
Neste outro exemplo, data e horário no nome do arquivo, e interrupção do sketch com exit()
ao final.
nome_output = '{}-{}-{}-{}-{}-{}-frame#####.png'.format(
year(), month(), day(), hour(), minute(), second())
def draw():
# desenho
...
save_frame(nome_output)
if frame_count > 100:
exit() # interrompe a execução do sketch
Exportando em resolução maior do que a da tela
Um objeto * Py5Graphics * é uma espécie de tela virtual que pode gravar o resultado do desenho em paralelo à área de desenho normal, podendo também receber ajustes especiais aplicados apenas a esse objeto-tela, como .scale()
no exemplo abaixo, o que permite exportar uma imagem 10 vezes maior do que a mostrada na tela. Outro ponto interessante deste método é que permite exportar imagens com o fundo transparente.
Exportando um sketch estático
def setup():
size(50, 50)
# preparo da gravação
fator_escala = 10 # um número que multiplica a largura e altura da imagem
f = create_graphics(width * fator_escala, height * fator_escala)
begin_record(f) # início da gravação
# ajustes que só afetam o arquivo sendo gravado
f.scale(fator_escala)
f.stroke_weight(0.5)
# instruções que aparecem na tela e no arquivo
background(0, 200, 0) # não use background() se quiser o fundo transparente
circle(6, 6, 10)
end_record() # fim da gravação
# se acrescentar instruções de desenho daqui em diante aparecerem só na tela
f.save('imagem_ampliada.png') # finalmente salva o arquivo
# use f.save('imagem_ampliada.png', drop_alpha=False) para exportar um png com fundo transparente
Repare que a espessura de linha está sendo ajustada para um valor diferente com f.strokeWeight()
. Sem o ajuste ela ficaria 10 vezes maior no arquivo do que na área de desenho normal(acompanhando e resto da imagem) e desta maneira ela fica apenas 5 vezes maior no arquivo.
Exportando um único frame de um sketch interativo
fator_escala = 10
salvar_png = False
def setup():
size(200, 200) # com fator 10, vira 2000px x 2000px
def draw():
global salvar_png
if salvar_png:
output_buffer = create_graphics(width * fator_escala,
height * fator_escala)
begin_record(output_buffer)
output_buffer.scale(fator_escala)
file_name = f'{frame_count}.png' # outra maneira
# seu desenho vai aqui
background(0, 100, 0)
circle(mouse_x, mouse_y, width / 2)
if salvar_png:
salvar_png = False
end_record()
output_buffer.save(file_name)
print(f'{file_name} salvo.')
def key_pressed():
global salvar_png
if key == 'h':
salvar_png = True
Gravando frames acumulados de um sketch
Este exemplo começa a gravar a acumulação de frames quando se aperta a tecla ‘r’. O resultado é um PNG com fundo transparente e escalado 10 vezes em relação ao que vemos na tela.
fator_escala = 10
gravando = False
def setup():
size(200, 200) # com fator 10, vira 2000px x 2000px
def draw():
# Este exemplo não usa background no draw(), e na tele se vê um fundo cinza
# mas no PNG gravado o fundo ficará transparente
if gravando:
output_buffer.scale(fator_escala) # precisa escalar novamente a cada frame
circle(mouse_x, mouse_y, width / 5)
def key_pressed():
global gravando, file_name, output_buffer
if key == 'r': # a tecla 'r' liga e desliga a gravação (recording)
if not gravando:
gravando = True
background(200) # limpa a tela (mas não entra na gravação)
output_buffer = create_graphics(width * fator_escala,
height * fator_escala)
begin_record(output_buffer)
file_name = f'{frame_count}.png'
print(f'iniciando a gravação de {file_name}')
else:
gravando = False
end_record()
# drop_alpha=False é necessário no momento para salvar fundo transparente
output_buffer.save(file_name, drop_alpha=False)
print(f'{file_name} gravado.')
Exportando apenas parte da tela (e em um local selecionado!)
No exemplo a seguir, vamos usar a estratégia de desenhar em um objeto Py5Graphics
como no exemplo anterior, e demonstrar também as seguintes possibilidades:
- Salvar um frame de um sketch interativo(com
draw()
) - Salvar apenas parte da imagem na tela(útil para remover elementos de interface/controle)
- Acrescentar ajustes ou elementos apenas na imagem salva
- Escolher onde salvar a imagem(fora da pasta do sketch).
Ambos os textos da imagem acima, em preto e em branco, não estarão presentes no arquivo salvo, assim como toda a àrea cinza em volta ou qualquer elemento nela desenhado.
salvar = False
def setup():
size(500, 500)
global w, h, margem, f
# dimensões da imagem e um deslocamento / margem
w, h, margem = 400, 400, 50
f = create_graphics(w, h)
def draw():
global salvar
translate(margem, margem) # 0, 0 no canto da imagem a ser salva
# instruções antes do beginRecord só aparecem na tela
# Se não for criado fundo depois de beginRecord, no arquivo fundo
# transparente
background(100) # fundo geral na tela apenas
fill(0)
text('Só na tela', 0, -20)
# início da gravação
if salvar:
begin_record(f) # início da gravação
# As instruções aqui aparecem na tela e no arquivo
no_stroke()
fill(0, 0, 200)
rect(0, 0, w, h) # fundo no arquivo usando um retângulo
fill(0, 200, 0)
circle(100, 100, 100)
# fim da gravação
if salvar:
# instruções com 'f.' aparecem só na gravação
f.fill(255, 0, 0)
f.text('Só na gravação', 20, 300)
end_record()
salvar = False
# em vez de f.save("arquivo_na_pasta_do_sketch.png")
# vamos usar esta função selectOtuput que chama por nós salva_arquivo()
select_output("Escolha onde Salvar", salva_arquivo)
# instruções depois do end_record também aparecem só na tela
fill(255)
text('Também só na tela', 10, 20)
Note o texto em vermelho que só aparece no arquivo salvo.